Merge "Change date and decimal separators for Uzbek (uz)"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Tue, 18 Mar 2014 07:48:28 +0000 (07:48 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Tue, 18 Mar 2014 07:48:28 +0000 (07:48 +0000)
305 files changed:
RELEASE-NOTES-1.23
docs/hooks.txt
docs/magicword.txt
img_auth.php
includes/AjaxResponse.php
includes/AutoLoader.php
includes/CacheHelper.php
includes/Category.php
includes/EditPage.php
includes/FormOptions.php
includes/GitInfo.php
includes/HistoryBlob.php
includes/Html.php
includes/MimeMagic.php
includes/OutputPage.php
includes/Pager.php
includes/Sanitizer.php
includes/Setup.php
includes/Skin.php
includes/SkinTemplate.php
includes/User.php
includes/UserMailer.php
includes/WatchedItem.php
includes/api/ApiFormatBase.php
includes/changes/RCCacheEntryFactory.php
includes/db/DatabaseMysqli.php
includes/db/DatabaseOracle.php
includes/db/DatabasePostgres.php
includes/db/LoadBalancer.php
includes/filerepo/file/LocalFile.php
includes/job/Job.php [deleted file]
includes/job/JobQueue.php [deleted file]
includes/job/JobQueueDB.php [deleted file]
includes/job/JobQueueFederated.php [deleted file]
includes/job/JobQueueGroup.php [deleted file]
includes/job/JobQueueRedis.php [deleted file]
includes/job/JobSpecification.php [deleted file]
includes/job/README [deleted file]
includes/job/aggregator/JobQueueAggregator.php [deleted file]
includes/job/aggregator/JobQueueAggregatorMemc.php [deleted file]
includes/job/aggregator/JobQueueAggregatorRedis.php [deleted file]
includes/job/jobs/AssembleUploadChunksJob.php [deleted file]
includes/job/jobs/DoubleRedirectJob.php [deleted file]
includes/job/jobs/DuplicateJob.php [deleted file]
includes/job/jobs/EmaillingJob.php [deleted file]
includes/job/jobs/EnotifNotifyJob.php [deleted file]
includes/job/jobs/HTMLCacheUpdateJob.php [deleted file]
includes/job/jobs/NullJob.php [deleted file]
includes/job/jobs/PublishStashedFileJob.php [deleted file]
includes/job/jobs/RefreshLinksJob.php [deleted file]
includes/job/jobs/RefreshLinksJob2.php [deleted file]
includes/job/jobs/UploadFromUrlJob.php [deleted file]
includes/job/utils/BacklinkJobUtils.php [deleted file]
includes/jobqueue/Job.php [new file with mode: 0644]
includes/jobqueue/JobQueue.php [new file with mode: 0644]
includes/jobqueue/JobQueueDB.php [new file with mode: 0644]
includes/jobqueue/JobQueueFederated.php [new file with mode: 0644]
includes/jobqueue/JobQueueGroup.php [new file with mode: 0644]
includes/jobqueue/JobQueueRedis.php [new file with mode: 0644]
includes/jobqueue/JobSpecification.php [new file with mode: 0644]
includes/jobqueue/README [new file with mode: 0644]
includes/jobqueue/aggregator/JobQueueAggregator.php [new file with mode: 0644]
includes/jobqueue/aggregator/JobQueueAggregatorMemc.php [new file with mode: 0644]
includes/jobqueue/aggregator/JobQueueAggregatorRedis.php [new file with mode: 0644]
includes/jobqueue/jobs/AssembleUploadChunksJob.php [new file with mode: 0644]
includes/jobqueue/jobs/DoubleRedirectJob.php [new file with mode: 0644]
includes/jobqueue/jobs/DuplicateJob.php [new file with mode: 0644]
includes/jobqueue/jobs/EmaillingJob.php [new file with mode: 0644]
includes/jobqueue/jobs/EnotifNotifyJob.php [new file with mode: 0644]
includes/jobqueue/jobs/HTMLCacheUpdateJob.php [new file with mode: 0644]
includes/jobqueue/jobs/NullJob.php [new file with mode: 0644]
includes/jobqueue/jobs/PublishStashedFileJob.php [new file with mode: 0644]
includes/jobqueue/jobs/RefreshLinksJob.php [new file with mode: 0644]
includes/jobqueue/jobs/RefreshLinksJob2.php [new file with mode: 0644]
includes/jobqueue/jobs/UploadFromUrlJob.php [new file with mode: 0644]
includes/jobqueue/utils/BacklinkJobUtils.php [new file with mode: 0644]
includes/logging/LogEventsList.php
includes/logging/LogPage.php
includes/logging/LogPager.php
includes/media/DjVuImage.php
includes/normal/RandomTest.php
includes/normal/Utf8Test.php
includes/normal/UtfNormal.php
includes/normal/UtfNormalBench.php
includes/normal/UtfNormalGenerate.php
includes/normal/UtfNormalMemStress.php
includes/normal/UtfNormalTest.php
includes/normal/UtfNormalUtil.php
includes/objectcache/BagOStuff.php
includes/parser/CoreTagHooks.php
includes/parser/Parser.php
includes/parser/Preprocessor_DOM.php
includes/parser/Preprocessor_Hash.php
includes/profiler/Profiler.php
includes/profiler/ProfilerMwprof.php
includes/profiler/ProfilerSimple.php
includes/resourceloader/ResourceLoaderStartUpModule.php
includes/revisiondelete/RevisionDelete.php
includes/search/SearchEngine.php
includes/search/SearchMySQL.php
includes/search/SearchOracle.php
includes/search/SearchPostgres.php
includes/specialpage/SpecialPage.php
includes/specials/SpecialImport.php
includes/specials/SpecialRevisiondelete.php
includes/specials/SpecialStatistics.php
includes/specials/SpecialUpload.php
includes/templates/Usercreate.php
includes/templates/Userlogin.php
languages/messages/MessagesAf.php
languages/messages/MessagesAln.php
languages/messages/MessagesAn.php
languages/messages/MessagesAr.php
languages/messages/MessagesArz.php
languages/messages/MessagesAs.php
languages/messages/MessagesAst.php
languages/messages/MessagesAz.php
languages/messages/MessagesAzb.php
languages/messages/MessagesBa.php
languages/messages/MessagesBar.php
languages/messages/MessagesBcc.php
languages/messages/MessagesBcl.php
languages/messages/MessagesBe.php
languages/messages/MessagesBe_tarask.php
languages/messages/MessagesBg.php
languages/messages/MessagesBjn.php
languages/messages/MessagesBn.php
languages/messages/MessagesBo.php
languages/messages/MessagesBr.php
languages/messages/MessagesBs.php
languages/messages/MessagesCa.php
languages/messages/MessagesCe.php
languages/messages/MessagesCkb.php
languages/messages/MessagesCs.php
languages/messages/MessagesCy.php
languages/messages/MessagesDa.php
languages/messages/MessagesDe.php
languages/messages/MessagesDiq.php
languages/messages/MessagesDsb.php
languages/messages/MessagesEgl.php
languages/messages/MessagesEl.php
languages/messages/MessagesEn.php
languages/messages/MessagesEo.php
languages/messages/MessagesEs.php
languages/messages/MessagesEt.php
languages/messages/MessagesEu.php
languages/messages/MessagesExt.php
languages/messages/MessagesFa.php
languages/messages/MessagesFi.php
languages/messages/MessagesFr.php
languages/messages/MessagesFrp.php
languages/messages/MessagesFrr.php
languages/messages/MessagesFy.php
languages/messages/MessagesGan_hans.php
languages/messages/MessagesGan_hant.php
languages/messages/MessagesGd.php
languages/messages/MessagesGl.php
languages/messages/MessagesGrc.php
languages/messages/MessagesGsw.php
languages/messages/MessagesGu.php
languages/messages/MessagesHak.php
languages/messages/MessagesHe.php
languages/messages/MessagesHi.php
languages/messages/MessagesHif_latn.php
languages/messages/MessagesHil.php
languages/messages/MessagesHr.php
languages/messages/MessagesHsb.php
languages/messages/MessagesHu.php
languages/messages/MessagesHy.php
languages/messages/MessagesIa.php
languages/messages/MessagesId.php
languages/messages/MessagesIlo.php
languages/messages/MessagesIs.php
languages/messages/MessagesIt.php
languages/messages/MessagesJa.php
languages/messages/MessagesJv.php
languages/messages/MessagesKa.php
languages/messages/MessagesKab.php
languages/messages/MessagesKbd_cyrl.php
languages/messages/MessagesKiu.php
languages/messages/MessagesKk_arab.php
languages/messages/MessagesKk_cyrl.php
languages/messages/MessagesKk_latn.php
languages/messages/MessagesKn.php
languages/messages/MessagesKo.php
languages/messages/MessagesKrc.php
languages/messages/MessagesKsh.php
languages/messages/MessagesLb.php
languages/messages/MessagesLi.php
languages/messages/MessagesLt.php
languages/messages/MessagesLv.php
languages/messages/MessagesLzh.php
languages/messages/MessagesMai.php
languages/messages/MessagesMdf.php
languages/messages/MessagesMg.php
languages/messages/MessagesMin.php
languages/messages/MessagesMk.php
languages/messages/MessagesMl.php
languages/messages/MessagesMn.php
languages/messages/MessagesMr.php
languages/messages/MessagesMs.php
languages/messages/MessagesMt.php
languages/messages/MessagesNan.php
languages/messages/MessagesNb.php
languages/messages/MessagesNds.php
languages/messages/MessagesNds_nl.php
languages/messages/MessagesNl.php
languages/messages/MessagesNn.php
languages/messages/MessagesOc.php
languages/messages/MessagesOr.php
languages/messages/MessagesPa.php
languages/messages/MessagesPam.php
languages/messages/MessagesPdc.php
languages/messages/MessagesPl.php
languages/messages/MessagesPms.php
languages/messages/MessagesPnb.php
languages/messages/MessagesPs.php
languages/messages/MessagesPt.php
languages/messages/MessagesPt_br.php
languages/messages/MessagesQqq.php
languages/messages/MessagesQu.php
languages/messages/MessagesRm.php
languages/messages/MessagesRo.php
languages/messages/MessagesRoa_tara.php
languages/messages/MessagesRu.php
languages/messages/MessagesRue.php
languages/messages/MessagesSa.php
languages/messages/MessagesSah.php
languages/messages/MessagesScn.php
languages/messages/MessagesSco.php
languages/messages/MessagesSgs.php
languages/messages/MessagesSh.php
languages/messages/MessagesSi.php
languages/messages/MessagesSk.php
languages/messages/MessagesSl.php
languages/messages/MessagesSo.php
languages/messages/MessagesSq.php
languages/messages/MessagesSr_ec.php
languages/messages/MessagesSr_el.php
languages/messages/MessagesStq.php
languages/messages/MessagesSu.php
languages/messages/MessagesSv.php
languages/messages/MessagesSw.php
languages/messages/MessagesSzl.php
languages/messages/MessagesTa.php
languages/messages/MessagesTe.php
languages/messages/MessagesTg_cyrl.php
languages/messages/MessagesTh.php
languages/messages/MessagesTk.php
languages/messages/MessagesTl.php
languages/messages/MessagesTr.php
languages/messages/MessagesTt_cyrl.php
languages/messages/MessagesUg_arab.php
languages/messages/MessagesUk.php
languages/messages/MessagesUz.php
languages/messages/MessagesVec.php
languages/messages/MessagesVep.php
languages/messages/MessagesVi.php
languages/messages/MessagesVo.php
languages/messages/MessagesVro.php
languages/messages/MessagesWa.php
languages/messages/MessagesWo.php
languages/messages/MessagesWuu.php
languages/messages/MessagesYi.php
languages/messages/MessagesYo.php
languages/messages/MessagesYue.php
languages/messages/MessagesZh_hans.php
languages/messages/MessagesZh_hant.php
maintenance/benchmarks/bench_strtr_str_replace.php
maintenance/generateJsonI18n.php
maintenance/language/messages.inc
maintenance/purgeList.php
maintenance/syncFileBackend.php
resources/mediawiki.api/mediawiki.api.category.js
resources/mediawiki.api/mediawiki.api.edit.js
resources/mediawiki.api/mediawiki.api.js
resources/mediawiki.api/mediawiki.api.parse.js
resources/mediawiki.api/mediawiki.api.watch.js
resources/oojs-ui/i18n/ce.json
resources/oojs-ui/i18n/cs.json
resources/oojs-ui/i18n/gl.json
resources/oojs-ui/i18n/hu.json
resources/oojs-ui/i18n/ilo.json
resources/oojs-ui/i18n/pt.json
resources/oojs-ui/oojs-ui.js
resources/oojs-ui/oojs-ui.svg.css
skins/Vector.php
skins/vector/components/animations.less [new file with mode: 0644]
skins/vector/components/common.less
skins/vector/styles.less
tests/parser/ParserTestResult.php
tests/parser/parserTest.inc
tests/parser/parserTests.txt
tests/phpunit/MediaWikiTestCase.php
tests/phpunit/includes/ArticleTablesTest.php
tests/phpunit/includes/ExtraParserTest.php
tests/phpunit/includes/TitleTest.php
tests/phpunit/includes/UserTest.php
tests/phpunit/includes/api/ApiQueryAllPagesTest.php
tests/phpunit/includes/libs/JavaScriptMinifierTest.php
tests/phpunit/includes/search/SearchUpdateTest.php
tests/phpunit/includes/specials/SpecialPreferencesTest.php
tests/phpunit/includes/upload/UploadStashTest.php
tests/phpunit/phpunit.php
tests/testHelpers.inc

index 3a809d3..379b219 100644 (file)
@@ -293,6 +293,12 @@ changes to languages because of Bugzilla reports.
 * RecentChange::mExtra['lang'] is no longer set and should no longer be used.
   Extensions should read from other configuration variables, including
   $wgLocalInterwikis, to identify the current wiki.
+* Sections in the parser test framework have been renamed and the old
+  section names are deprecated.  Please use "!!wikitext" and "!!html"
+  (or "!!html/php") instead of "!!input" and "!!result".  This allows
+  us to extend parser tests to accommodate additional input/output
+  pairs, such as "!!html/parsoid" (for the output of the Parsoid
+  parser, where it differs from the PHP parser).
 
 ==== Removed classes ====
 * FakeMemCachedClient (deprecated in 1.18)
index a833484..e944d55 100644 (file)
@@ -1824,7 +1824,7 @@ $isMinor: Whether or not the edit was marked as minor
 $isWatch: (No longer used)
 $section: (No longer used)
 $flags: Flags passed to WikiPage::doEditContent()
-$revision: New Revision of the article
+$revision: New Revision of the article (can be null for edits that change nothing)
 $status: Status object about to be returned by doEditContent()
 $baseRevId: the rev ID (or false) this edit was based on
 
index 46fcecc..6b4d37e 100644 (file)
@@ -86,10 +86,10 @@ function wfGetCustomMagicWordValue( &$parser, $var1, $var2 ){
        return "custom: var1 is $var1, var2 is $var2";
 }
 
-Note: the 'ParserFirstCallInit' hook is only aviable since 1.12. To work with
+Note: the 'ParserFirstCallInit' hook is only available since 1.12. To work with
 an older version, you'll need to use an extension function.
 
 Online documentation (contains more informations):
 Magic words: https://www.mediawiki.org/wiki/Manual:Magic_words
 Variables: https://www.mediawiki.org/wiki/Manual:Variable
-Parser functions: https://www.mediawiki.org/wiki/Manual:Parser_functions
\ No newline at end of file
+Parser functions: https://www.mediawiki.org/wiki/Manual:Parser_functions
index 7765dd3..391fb29 100644 (file)
@@ -92,11 +92,11 @@ function wfImageAuthMain() {
                if ( strpos( $path, $prefix ) === 0 ) {
                        $be = FileBackendGroup::singleton()->backendFromPath( $storageDir );
                        $filename = $storageDir . substr( $path, strlen( $prefix ) ); // strip prefix
-                       // Check basic user authorization
-                       if ( !RequestContext::getMain()->getUser()->isAllowed( 'read' ) ) {
-                               wfForbidden( 'img-auth-accessdenied', 'img-auth-noread', $path );
-                               return;
-                       }
+                       // Check basic user authorization
+                       if ( !RequestContext::getMain()->getUser()->isAllowed( 'read' ) ) {
+                               wfForbidden( 'img-auth-accessdenied', 'img-auth-noread', $path );
+                               return;
+                       }
                        if ( $be->fileExists( array( 'src' => $filename ) ) ) {
                                wfDebugLog( 'img_auth', "Streaming `" . $filename . "`." );
                                $be->streamFile( array( 'src' => $filename ),
index ac8a9f0..334cee3 100644 (file)
@@ -215,7 +215,7 @@ class AjaxResponse {
                $fname = 'AjaxResponse::checkLastModified';
 
                if ( !$timestamp || $timestamp == '19700101000000' ) {
-                       wfDebug( "$fname: CACHE DISABLED, NO TIMESTAMP\n" );
+                       wfDebug( "$fname: CACHE DISABLED, NO TIMESTAMP\n", 'log' );
                        return false;
                }
 
index cfddb72..b290e8d 100644 (file)
@@ -657,35 +657,35 @@ $wgAutoloadLocalClasses = array(
        'WebInstallerPage' => 'includes/installer/WebInstallerPage.php',
 
        # includes/job
-       'IJobSpecification' => 'includes/job/JobSpecification.php',
-       'Job' => 'includes/job/Job.php',
-       'JobQueue' => 'includes/job/JobQueue.php',
-       'JobQueueAggregator' => 'includes/job/aggregator/JobQueueAggregator.php',
-       'JobQueueAggregatorMemc' => 'includes/job/aggregator/JobQueueAggregatorMemc.php',
-       'JobQueueAggregatorRedis' => 'includes/job/aggregator/JobQueueAggregatorRedis.php',
-       'JobQueueDB' => 'includes/job/JobQueueDB.php',
-       'JobQueueConnectionError' => 'includes/job/JobQueue.php',
-       'JobQueueError' => 'includes/job/JobQueue.php',
-       'JobQueueGroup' => 'includes/job/JobQueueGroup.php',
-       'JobQueueFederated' => 'includes/job/JobQueueFederated.php',
-       'JobQueueRedis' => 'includes/job/JobQueueRedis.php',
-       'JobSpecification' => 'includes/job/JobSpecification.php',
-
-       # includes/job/jobs
-       'DoubleRedirectJob' => 'includes/job/jobs/DoubleRedirectJob.php',
-       'DuplicateJob' => 'includes/job/jobs/DuplicateJob.php',
-       'EmaillingJob' => 'includes/job/jobs/EmaillingJob.php',
-       'EnotifNotifyJob' => 'includes/job/jobs/EnotifNotifyJob.php',
-       'HTMLCacheUpdateJob' => 'includes/job/jobs/HTMLCacheUpdateJob.php',
-       'NullJob' => 'includes/job/jobs/NullJob.php',
-       'RefreshLinksJob' => 'includes/job/jobs/RefreshLinksJob.php',
-       'RefreshLinksJob2' => 'includes/job/jobs/RefreshLinksJob2.php',
-       'UploadFromUrlJob' => 'includes/job/jobs/UploadFromUrlJob.php',
-       'AssembleUploadChunksJob' => 'includes/job/jobs/AssembleUploadChunksJob.php',
-       'PublishStashedFileJob' => 'includes/job/jobs/PublishStashedFileJob.php',
-
-       # includes/job/utils
-       'BacklinkJobUtils' => 'includes/job/utils/BacklinkJobUtils.php',
+       'IJobSpecification' => 'includes/jobqueue/JobSpecification.php',
+       'Job' => 'includes/jobqueue/Job.php',
+       'JobQueue' => 'includes/jobqueue/JobQueue.php',
+       'JobQueueAggregator' => 'includes/jobqueue/aggregator/JobQueueAggregator.php',
+       'JobQueueAggregatorMemc' => 'includes/jobqueue/aggregator/JobQueueAggregatorMemc.php',
+       'JobQueueAggregatorRedis' => 'includes/jobqueue/aggregator/JobQueueAggregatorRedis.php',
+       'JobQueueDB' => 'includes/jobqueue/JobQueueDB.php',
+       'JobQueueConnectionError' => 'includes/jobqueue/JobQueue.php',
+       'JobQueueError' => 'includes/jobqueue/JobQueue.php',
+       'JobQueueGroup' => 'includes/jobqueue/JobQueueGroup.php',
+       'JobQueueFederated' => 'includes/jobqueue/JobQueueFederated.php',
+       'JobQueueRedis' => 'includes/jobqueue/JobQueueRedis.php',
+       'JobSpecification' => 'includes/jobqueue/JobSpecification.php',
+
+       # includes/jobqueue/jobs
+       'DoubleRedirectJob' => 'includes/jobqueue/jobs/DoubleRedirectJob.php',
+       'DuplicateJob' => 'includes/jobqueue/jobs/DuplicateJob.php',
+       'EmaillingJob' => 'includes/jobqueue/jobs/EmaillingJob.php',
+       'EnotifNotifyJob' => 'includes/jobqueue/jobs/EnotifNotifyJob.php',
+       'HTMLCacheUpdateJob' => 'includes/jobqueue/jobs/HTMLCacheUpdateJob.php',
+       'NullJob' => 'includes/jobqueue/jobs/NullJob.php',
+       'RefreshLinksJob' => 'includes/jobqueue/jobs/RefreshLinksJob.php',
+       'RefreshLinksJob2' => 'includes/jobqueue/jobs/RefreshLinksJob2.php',
+       'UploadFromUrlJob' => 'includes/jobqueue/jobs/UploadFromUrlJob.php',
+       'AssembleUploadChunksJob' => 'includes/jobqueue/jobs/AssembleUploadChunksJob.php',
+       'PublishStashedFileJob' => 'includes/jobqueue/jobs/PublishStashedFileJob.php',
+
+       # includes/jobqueue/utils
+       'BacklinkJobUtils' => 'includes/jobqueue/utils/BacklinkJobUtils.php',
 
        # includes/json
        'FormatJson' => 'includes/json/FormatJson.php',
@@ -1213,17 +1213,17 @@ class AutoLoader {
                        }
 
                        if ( isset( self::$autoloadLocalClassesLower[$lowerClass] ) ) {
-                               if ( function_exists( 'wfDebug' ) ) {
-                                       wfDebug( "Class {$className} was loaded using incorrect case.\n" );
+                               if ( function_exists( 'wfDebugLog' ) ) {
+                                       wfDebugLog( 'autoloader', "Class {$className} was loaded using incorrect case" );
                                }
                                $filename = self::$autoloadLocalClassesLower[$lowerClass];
                        }
                }
 
                if ( !$filename ) {
-                       if ( function_exists( 'wfDebug' ) ) {
+                       if ( function_exists( 'wfDebugLog' ) ) {
                                # FIXME: This is not very polite.  Assume we do not manage the class.
-                               wfDebug( "Class {$className} not found; skipped loading\n" );
+                               wfDebugLog( 'autoloader', "Class {$className} not found; skipped loading" );
                        }
 
                        # Give up
index f0ae5a3..f6cd3a6 100644 (file)
@@ -205,8 +205,7 @@ class CacheHelper implements ICacheHelper {
                                'cachedspecial-viewing-cached-ttl',
                                $context->getLanguage()->formatDuration( $this->cacheExpiry )
                        )->escaped();
-               }
-               else {
+               } else {
                        $message = $context->msg(
                                'cachedspecial-viewing-cached-ts'
                        )->escaped();
@@ -277,25 +276,20 @@ class CacheHelper implements ICacheHelper {
 
                                if ( !is_integer( $itemKey ) ) {
                                        wfWarn( "Attempted to get item with non-numeric key while the next item in the queue has a key ($itemKey) in " . __METHOD__ );
-                               }
-                               elseif ( is_null( $itemKey ) ) {
+                               } elseif ( is_null( $itemKey ) ) {
                                        wfWarn( "Attempted to get an item while the queue is empty in " . __METHOD__ );
-                               }
-                               else {
+                               } else {
                                        $value = array_shift( $this->cachedChunks );
                                }
-                       }
-                       else {
+                       } else {
                                if ( array_key_exists( $key, $this->cachedChunks ) ) {
                                        $value = $this->cachedChunks[$key];
                                        unset( $this->cachedChunks[$key] );
-                               }
-                               else {
+                               } else {
                                        wfWarn( "There is no item with key '$key' in this->cachedChunks in " . __METHOD__ );
                                }
                        }
-               }
-               else {
+               } else {
                        if ( !is_array( $args ) ) {
                                $args = array( $args );
                        }
@@ -305,8 +299,7 @@ class CacheHelper implements ICacheHelper {
                        if ( $this->cacheEnabled ) {
                                if ( is_null( $key ) ) {
                                        $this->cachedChunks[] = $value;
-                               }
-                               else {
+                               } else {
                                        $this->cachedChunks[$key] = $value;
                                }
                        }
index 126b8fe..df5ad7d 100644 (file)
@@ -195,27 +195,37 @@ class Category {
                return $cat;
        }
 
-       /** @return mixed DB key name, or false on failure */
+       /**
+        * @return mixed DB key name, or false on failure
+        */
        public function getName() {
                return $this->getX( 'mName' );
        }
 
-       /** @return mixed Category ID, or false on failure */
+       /**
+        * @return mixed Category ID, or false on failure
+        */
        public function getID() {
                return $this->getX( 'mID' );
        }
 
-       /** @return mixed Total number of member pages, or false on failure */
+       /**
+        * @return mixed Total number of member pages, or false on failure
+        */
        public function getPageCount() {
                return $this->getX( 'mPages' );
        }
 
-       /** @return mixed Number of subcategories, or false on failure */
+       /**
+        * @return mixed Number of subcategories, or false on failure
+        */
        public function getSubcatCount() {
                return $this->getX( 'mSubcats' );
        }
 
-       /** @return mixed Number of member files, or false on failure */
+       /**
+        * @return mixed Number of member files, or false on failure
+        */
        public function getFileCount() {
                return $this->getX( 'mFiles' );
        }
index 9a27d23..5f5cb53 100644 (file)
@@ -772,8 +772,7 @@ class EditPage {
                                $this->sectiontitle = $request->getVal( 'preloadtitle' );
                                // Once wpSummary isn't being use for setting section titles, we should delete this.
                                $this->summary = $request->getVal( 'preloadtitle' );
-                       }
-                       elseif ( $this->section != 'new' && $request->getVal( 'summary' ) ) {
+                       } elseif ( $this->section != 'new' && $request->getVal( 'summary' ) ) {
                                $this->summary = $request->getText( 'summary' );
                                if ( $this->summary !== '' ) {
                                        $this->hasPresetSummary = true;
index cd6e207..a8da67e 100644 (file)
@@ -373,22 +373,32 @@ class FormOptions implements ArrayAccess {
         * @see http://php.net/manual/en/class.arrayaccess.php
         */
        /* @{ */
-       /** Whether the option exists. */
+       /**
+        * Whether the option exists.
+        * @return bool
+        */
        public function offsetExists( $name ) {
                return isset( $this->options[$name] );
        }
 
-       /** Retrieve an option value. */
+       /**
+        * Retrieve an option value.
+        * @return mixed
+        */
        public function offsetGet( $name ) {
                return $this->getValue( $name );
        }
 
-       /** Set an option to given value. */
+       /**
+        * Set an option to given value.
+        */
        public function offsetSet( $name, $value ) {
                $this->setValue( $name, $value );
        }
 
-       /** Delete the option. */
+       /**
+        * Delete the option.
+        */
        public function offsetUnset( $name ) {
                $this->delete( $name );
        }
index 877c2d2..6b092d9 100644 (file)
@@ -82,18 +82,18 @@ class GitInfo {
         * @return string The HEAD
         */
        public function getHead() {
-               $HEADfile = "{$this->basedir}/HEAD";
+               $headFile = "{$this->basedir}/HEAD";
 
-               if ( !is_readable( $HEADfile ) ) {
+               if ( !is_readable( $headFile ) ) {
                        return false;
                }
 
-               $HEAD = file_get_contents( $HEADfile );
+               $head = file_get_contents( $headFile );
 
-               if ( preg_match( "/ref: (.*)/", $HEAD, $m ) ) {
+               if ( preg_match( "/ref: (.*)/", $head, $m ) ) {
                        return rtrim( $m[1] );
                } else {
-                       return rtrim( $HEAD );
+                       return rtrim( $head );
                }
        }
 
@@ -102,20 +102,20 @@ class GitInfo {
         * @return string A SHA1 or false
         */
        public function getHeadSHA1() {
-               $HEAD = $this->getHead();
+               $head = $this->getHead();
 
                // If detached HEAD may be a SHA1
-               if ( self::isSHA1( $HEAD ) ) {
-                       return $HEAD;
+               if ( self::isSHA1( $head ) ) {
+                       return $head;
                }
 
                // If not a SHA1 it may be a ref:
-               $REFfile = "{$this->basedir}/{$HEAD}";
-               if ( !is_readable( $REFfile ) ) {
+               $refFile = "{$this->basedir}/{$head}";
+               if ( !is_readable( $refFile ) ) {
                        return false;
                }
 
-               $sha1 = rtrim( file_get_contents( $REFfile ) );
+               $sha1 = rtrim( file_get_contents( $refFile ) );
 
                return $sha1;
        }
@@ -150,11 +150,11 @@ class GitInfo {
         * @return string The branch name, HEAD, or false
         */
        public function getCurrentBranch() {
-               $HEAD = $this->getHead();
-               if ( $HEAD && preg_match( "#^refs/heads/(.*)$#", $HEAD, $m ) ) {
+               $head = $this->getHead();
+               if ( $head && preg_match( "#^refs/heads/(.*)$#", $head, $m ) ) {
                        return $m[1];
                } else {
-                       return $HEAD;
+                       return $head;
                }
        }
 
index 9c50895..a3ed700 100644 (file)
@@ -78,7 +78,9 @@ class ConcatenatedGzipHistoryBlob implements HistoryBlob
        public $mMaxSize = 10000000;
        public $mMaxCount = 100;
 
-       /** Constructor */
+       /**
+        * Constructor
+        */
        public function __construct() {
                if ( !function_exists( 'gzdeflate' ) ) {
                        throw new MWException( "Need zlib support to read or write this kind of history object (ConcatenatedGzipHistoryBlob)\n" );
index 0eb6474..c4fc29a 100644 (file)
@@ -689,6 +689,7 @@ class Html {
                }
                return self::element( 'textarea', $attribs, $spacedValue );
        }
+
        /**
         * Build a drop-down box for selecting a namespace
         *
index f5c28ab..e3b8577 100644 (file)
@@ -508,8 +508,7 @@ class MimeMagic {
                                // trust the file extension
                                $mime = $this->guessTypesForExtension( $ext );
                        }
-               }
-               elseif ( $mime === 'application/x-opc+zip' ) {
+               } elseif ( $mime === 'application/x-opc+zip' ) {
                        if ( $this->isMatchingExtension( $ext, $mime ) ) {
                                // A known file extension for an OPC file,
                                // find the proper mime type for that file extension
index efcd838..9cba0cc 100644 (file)
@@ -685,7 +685,7 @@ class OutputPage extends ContextSource {
                        return false;
                }
                if ( !$wgCachePages ) {
-                       wfDebug( __METHOD__ . ": CACHE DISABLED\n", 'log' );
+                       wfDebug( __METHOD__ . ": CACHE DISABLED\n" );
                        return false;
                }
 
index 6a10e88..747d2c1 100644 (file)
@@ -249,6 +249,7 @@ abstract class IndexPager extends ContextSource implements Pager {
        function setOffset( $offset ) {
                $this->mOffset = $offset;
        }
+
        /**
         * Set the limit from an other source than the request
         *
index 90548fe..245714d 100644 (file)
@@ -631,8 +631,7 @@ class Sanitizer {
                                # Remove the comment, leading and trailing
                                # spaces, and leave only one newline.
                                $text = substr_replace( $text, "\n", $spaceStart, $spaceLen + 1 );
-                       }
-                       else {
+                       } else {
                                # Remove just the comment.
                                $text = substr_replace( $text, '', $start, $end - $start );
                        }
@@ -1303,6 +1302,7 @@ class Sanitizer {
                        array( 'Sanitizer', 'normalizeCharReferencesCallback' ),
                        $text );
        }
+
        /**
         * @param string $matches
         * @return string
@@ -1839,7 +1839,7 @@ class Sanitizer {
                $rfc5322_atext = "a-z0-9!#$%&'*+\\-\/=?^_`{|}~";
                $rfc1034_ldh_str = "a-z0-9\\-";
 
-               $HTML5_email_regexp = "/
+               $html5_email_regexp = "/
                ^                      # start of string
                [$rfc5322_atext\\.]+    # user part which is liberal :p
                @                      # 'apostrophe'
@@ -1848,6 +1848,6 @@ class Sanitizer {
                $                      # End of string
                /ix"; // case Insensitive, eXtended
 
-               return (bool)preg_match( $HTML5_email_regexp, $addr );
+               return (bool)preg_match( $html5_email_regexp, $addr );
        }
 }
index d7438e5..777ca37 100644 (file)
@@ -512,9 +512,9 @@ $messageMemc = wfGetMessageCacheStorage();
 $parserMemc = wfGetParserCacheStorage();
 $wgLangConvMemc = wfGetLangConverterCacheStorage();
 
-wfDebug( 'CACHES: ' . get_class( $wgMemc ) . '[main] ' .
+wfDebugLog( 'caches', get_class( $wgMemc ) . '[main] ' .
        get_class( $messageMemc ) . '[message] ' .
-       get_class( $parserMemc ) . "[parser]\n" );
+       get_class( $parserMemc ) . '[parser]' );
 
 wfProfileOut( $fname . '-memcached' );
 
index 6722cca..9312a0d 100644 (file)
@@ -182,7 +182,9 @@ abstract class Skin extends ContextSource {
                return $skin;
        }
 
-       /** @return string skin name */
+       /**
+        * @return string skin name
+        */
        public function getSkinName() {
                return $this->skinname;
        }
@@ -1247,6 +1249,7 @@ abstract class Skin extends ContextSource {
                wfProfileOut( __METHOD__ );
                return $bar;
        }
+
        /**
         * Add content from a sidebar system message
         * Currently only used for MediaWiki:Sidebar (but may be used by Extensions)
index bf572d0..32f0ed3 100644 (file)
@@ -402,6 +402,8 @@ class SkinTemplate extends Skin {
                // that interface elements are in a different language.
                $tpl->set( 'userlangattributes', '' );
                $tpl->set( 'specialpageattributes', '' ); # obsolete
+               // Used by VectorBeta to insert HTML before content but after the heading for the page title. Defaults to empty string.
+               $tpl->set( 'prebodyhtml', '' );
 
                if ( $userLangCode !== $wgContLang->getHtmlCode() || $userLangDir !== $wgContLang->getDir() ) {
                        $escUserlang = htmlspecialchars( $userLangCode );
index 6d9f372..9b47acf 100644 (file)
@@ -697,6 +697,7 @@ class User {
                return $this->getPasswordValidity( $password ) === true;
        }
 
+
        /**
         * Given unvalidated password input, return error message on failure.
         *
@@ -704,6 +705,33 @@ class User {
         * @return mixed: true on success, string or array of error message on failure
         */
        public function getPasswordValidity( $password ) {
+               $result = $this->checkPasswordValidity( $password );
+               if ( $result->isGood() ) {
+                       return true;
+               } else {
+                       $messages = array();
+                       foreach ( $result->getErrorsByType( 'error' ) as $error ) {
+                               $messages[] = $error['message'];
+                       }
+                       foreach ( $result->getErrorsByType( 'warning' ) as $warning ) {
+                               $messages[] = $warning['message'];
+                       }
+                       if ( count( $messages ) === 1 ) {
+                               return $messages[0];
+                       }
+                       return $messages;
+               }
+       }
+
+       /**
+        * Check if this is a valid password for this user. Status will be good if
+        * the password is valid, or have an array of error messages if not.
+        *
+        * @param string $password Desired password
+        * @return Status
+        * @since 1.23
+        */
+       public function checkPasswordValidity( $password ) {
                global $wgMinimalPasswordLength, $wgContLang;
 
                static $blockedLogins = array(
@@ -711,30 +739,37 @@ class User {
                        'Apitestsysop' => 'testpass', 'Apitestuser' => 'testpass' # r75605
                );
 
+               $status = Status::newGood();
+
                $result = false; //init $result to false for the internal checks
 
                if ( !wfRunHooks( 'isValidPassword', array( $password, &$result, $this ) ) ) {
-                       return $result;
+                       $status->error( $result );
+                       return $status;
                }
 
                if ( $result === false ) {
                        if ( strlen( $password ) < $wgMinimalPasswordLength ) {
-                               return 'passwordtooshort';
+                               $status->error( 'passwordtooshort', $wgMinimalPasswordLength );
+                               return $status;
                        } elseif ( $wgContLang->lc( $password ) == $wgContLang->lc( $this->mName ) ) {
-                               return 'password-name-match';
+                               $status->error( 'password-name-match' );
+                               return $status;
                        } elseif ( isset( $blockedLogins[$this->getName()] ) && $password == $blockedLogins[$this->getName()] ) {
-                               return 'password-login-forbidden';
+                               $status->error( 'password-login-forbidden' );
+                               return $status;
                        } else {
-                               //it seems weird returning true here, but this is because of the
+                               //it seems weird returning a Good status here, but this is because of the
                                //initialization of $result to false above. If the hook is never run or it
                                //doesn't modify $result, then we will likely get down into this if with
                                //a valid password.
-                               return true;
+                               return $status;
                        }
                } elseif ( $result === true ) {
-                       return true;
+                       return $status;
                } else {
-                       return $result; //the isValidPassword hook set a string $result and returned true
+                       $status->error( $result );
+                       return $status; //the isValidPassword hook set a string $result and returned true
                }
        }
 
index fe80929..4c2ecba 100644 (file)
@@ -262,8 +262,7 @@ class UserMailer {
                                wfDebug( "PEAR Mail_Mime package is not installed. Falling back to text email.\n" );
                                // remove the html body for text email fall back
                                $body = $body['text'];
-                       }
-                       else {
+                       } else {
                                require_once 'Mail/mime.php';
                                if ( wfIsWindows() ) {
                                        $body['text'] = str_replace( "\n", "\r\n", $body['text'] );
index fe97843..a6e7516 100644 (file)
@@ -70,16 +70,26 @@ class WatchedItem {
                return $this->mTitle;
        }
 
-       /** Helper to retrieve the title namespace */
+       /**
+        * Helper to retrieve the title namespace
+        * @return int
+        */
        protected function getTitleNs() {
                return $this->getTitle()->getNamespace();
        }
 
-       /** Helper to retrieve the title DBkey */
+       /**
+        * Helper to retrieve the title DBkey
+        * @return string
+        */
        protected function getTitleDBkey() {
                return $this->getTitle()->getDBkey();
        }
-       /** Helper to retrieve the user id */
+
+       /**
+        * Helper to retrieve the user id
+        * @return int
+        */
        protected function getUserId() {
                return $this->mUser->getId();
        }
index 49a02fe..3c924bc 100644 (file)
@@ -275,8 +275,8 @@ See the <a href='https://www.mediawiki.org/wiki/API'>complete documentation</a>,
                // identify requests to api.php
                $text = preg_replace( '#^(\s*)(api\.php\?[^ <\n\t]+)$#m', '\1<a href="\2">\2</a>', $text );
                if ( $this->mHelp ) {
-                       // make strings inside * bold
-                       $text = preg_replace( "#\\*[^<>\n]+\\*#", '<b>\\0</b>', $text );
+                       // make lines inside * bold
+                       $text = preg_replace( '#^(\s*)(\*[^<>\n]+\*)(\s*)$#m', '$1<b>$2</b>$3', $text );
                }
 
                // Armor links (bug 61362)
index 49ce1b3..3e289cf 100644 (file)
@@ -81,7 +81,7 @@ class RCCacheEntryFactory {
 
        /**
         * @param RecentChange $cacheEntry
-        * @param User $User
+        * @param User $user
         *
         * @return boolean
         */
index 635909c..b371ae0 100644 (file)
@@ -57,6 +57,17 @@ class DatabaseMysqli extends DatabaseMysqlBase {
                                . " have you compiled PHP with the --with-mysqli option?\n" );
                }
 
+               // Other than mysql_connect, mysqli_real_connect expects an explicit port
+               // parameter. So we need to parse the port out of $realServer
+               $port = null;
+               $hostAndPort = IP::splitHostAndPort( $realServer );
+               if ( $hostAndPort ) {
+                       $realServer = $hostAndPort[0];
+                       if ( $hostAndPort[1] ) {
+                               $port = $hostAndPort[1];
+                       }
+               }
+               
                $connFlags = 0;
                if ( $this->mFlags & DBO_SSL ) {
                        $connFlags |= MYSQLI_CLIENT_SSL;
@@ -83,7 +94,7 @@ class DatabaseMysqli extends DatabaseMysqlBase {
                                usleep( 1000 );
                        }
                        if ( $mysqli->real_connect( $realServer, $this->mUser,
-                               $this->mPassword, $this->mDBname, null, null, $connFlags )
+                               $this->mPassword, $this->mDBname, $port, null, $connFlags )
                        ) {
                                return $mysqli;
                        }
index 998dd75..6e0490d 100644 (file)
@@ -1034,8 +1034,8 @@ class DatabaseOracle extends DatabaseBase {
                $table = strtoupper( $this->removeIdentifierQuotes( $table ) );
                $index = strtoupper( $index );
                $owner = strtoupper( $this->mDBname );
-               $SQL = "SELECT 1 FROM all_indexes WHERE owner='$owner' AND index_name='{$table}_{$index}'";
-               $res = $this->doQuery( $SQL );
+               $sql = "SELECT 1 FROM all_indexes WHERE owner='$owner' AND index_name='{$table}_{$index}'";
+               $res = $this->doQuery( $sql );
                if ( $res ) {
                        $count = $res->numRows();
                        $res->free();
@@ -1056,8 +1056,8 @@ class DatabaseOracle extends DatabaseBase {
                $table = $this->tableName( $table );
                $table = $this->addQuotes( strtoupper( $this->removeIdentifierQuotes( $table ) ) );
                $owner = $this->addQuotes( strtoupper( $this->mDBname ) );
-               $SQL = "SELECT 1 FROM all_tables WHERE owner=$owner AND table_name=$table";
-               $res = $this->doQuery( $SQL );
+               $sql = "SELECT 1 FROM all_tables WHERE owner=$owner AND table_name=$table";
+               $res = $this->doQuery( $sql );
                if ( $res && $res->numRows() > 0 ) {
                        $exists = true;
                } else {
index c8830d3..6aee528 100644 (file)
@@ -349,11 +349,11 @@ class DatabasePostgres extends DatabaseBase {
        }
 
        function hasConstraint( $name ) {
-               $SQL = "SELECT 1 FROM pg_catalog.pg_constraint c, pg_catalog.pg_namespace n " .
+               $sql = "SELECT 1 FROM pg_catalog.pg_constraint c, pg_catalog.pg_namespace n " .
                        "WHERE c.connamespace = n.oid AND conname = '" .
                        pg_escape_string( $this->mConn, $name ) . "' AND n.nspname = '" .
                        pg_escape_string( $this->mConn, $this->getCoreSchema() ) . "'";
-               $res = $this->doQuery( $SQL );
+               $res = $this->doQuery( $sql );
 
                return $this->numRows( $res );
        }
@@ -1360,10 +1360,10 @@ __INDEXATTR__;
                $table = $this->realTableName( $table, 'raw' );
                $etable = $this->addQuotes( $table );
                $eschema = $this->addQuotes( $schema );
-               $SQL = "SELECT 1 FROM pg_catalog.pg_class c, pg_catalog.pg_namespace n "
+               $sql = "SELECT 1 FROM pg_catalog.pg_class c, pg_catalog.pg_namespace n "
                        . "WHERE c.relnamespace = n.oid AND c.relname = $etable AND n.nspname = $eschema "
                        . "AND c.relkind IN ('" . implode( "','", $types ) . "')";
-               $res = $this->query( $SQL );
+               $res = $this->query( $sql );
                $count = $res ? $res->numRows() : 0;
 
                return (bool)$count;
@@ -1421,13 +1421,13 @@ SQL;
        }
 
        function constraintExists( $table, $constraint ) {
-               $SQL = sprintf( "SELECT 1 FROM information_schema.table_constraints " .
+               $sql = sprintf( "SELECT 1 FROM information_schema.table_constraints " .
                        "WHERE constraint_schema = %s AND table_name = %s AND constraint_name = %s",
                        $this->addQuotes( $this->getCoreSchema() ),
                        $this->addQuotes( $table ),
                        $this->addQuotes( $constraint )
                );
-               $res = $this->query( $SQL );
+               $res = $this->query( $sql );
                if ( !$res ) {
                        return null;
                }
index 5f880d6..de4c2f5 100644 (file)
@@ -493,13 +493,6 @@ class LoadBalancer {
        public function reuseConnection( $conn ) {
                $serverIndex = $conn->getLBInfo( 'serverIndex' );
                $refCount = $conn->getLBInfo( 'foreignPoolRefCount' );
-               $dbName = $conn->getDBname();
-               $prefix = $conn->tablePrefix();
-               if ( strval( $prefix ) !== '' ) {
-                       $wiki = "$dbName-$prefix";
-               } else {
-                       $wiki = $dbName;
-               }
                if ( $serverIndex === null || $refCount === null ) {
                        wfDebug( __METHOD__ . ": this connection was not opened as a foreign connection\n" );
 
@@ -516,6 +509,14 @@ class LoadBalancer {
 
                        return;
                }
+
+               $dbName = $conn->getDBname();
+               $prefix = $conn->tablePrefix();
+               if ( strval( $prefix ) !== '' ) {
+                       $wiki = "$dbName-$prefix";
+               } else {
+                       $wiki = $dbName;
+               }
                if ( $this->mConns['foreignUsed'][$serverIndex][$wiki] !== $conn ) {
                        throw new MWException( __METHOD__ . ": connection not found, has " .
                                "the connection been freed already?" );
index c7b257a..cfa26b0 100644 (file)
@@ -903,12 +903,13 @@ class LocalFile extends File {
 
                // Get a list of old thumbnails and URLs
                $files = $this->getThumbnails( $archiveName );
-               $dir = array_shift( $files );
-               $this->purgeThumbList( $dir, $files );
 
                // Purge any custom thumbnail caches
                wfRunHooks( 'LocalFilePurgeThumbnails', array( $this, $archiveName ) );
 
+               $dir = array_shift( $files );
+               $this->purgeThumbList( $dir, $files );
+
                // Purge the squid
                if ( $wgUseSquid ) {
                        $urls = array();
@@ -947,12 +948,12 @@ class LocalFile extends File {
                        }
                }
 
-               $dir = array_shift( $files );
-               $this->purgeThumbList( $dir, $files );
-
                // Purge any custom thumbnail caches
                wfRunHooks( 'LocalFilePurgeThumbnails', array( $this, false ) );
 
+               $dir = array_shift( $files );
+               $this->purgeThumbList( $dir, $files );
+
                // Purge the squid
                if ( $wgUseSquid ) {
                        SquidUpdate::purge( $urls );
diff --git a/includes/job/Job.php b/includes/job/Job.php
deleted file mode 100644 (file)
index 5fc1e06..0000000
+++ /dev/null
@@ -1,330 +0,0 @@
-<?php
-/**
- * Job queue task base code.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @defgroup JobQueue JobQueue
- */
-
-/**
- * Class to both describe a background job and handle jobs.
- * The queue aspects of this class are now deprecated.
- * Using the class to push jobs onto queues is deprecated (use JobSpecification).
- *
- * @ingroup JobQueue
- */
-abstract class Job implements IJobSpecification {
-       /** @var string */
-       public $command;
-
-       /** @var array|bool Array of job parameters or false if none */
-       public $params;
-
-       /** @var array Additional queue metadata */
-       public $metadata = array();
-
-       /** @var Title */
-       protected $title;
-
-       /** @var bool Expensive jobs may set this to true */
-       protected $removeDuplicates;
-
-       /** @var string Text for error that occurred last */
-       protected $error;
-
-       /*-------------------------------------------------------------------------
-        * Abstract functions
-        *------------------------------------------------------------------------*/
-
-       /**
-        * Run the job
-        * @return bool Success
-        */
-       abstract public function run();
-
-       /*-------------------------------------------------------------------------
-        * Static functions
-        *------------------------------------------------------------------------*/
-
-       /**
-        * Create the appropriate object to handle a specific job
-        *
-        * @param string $command Job command
-        * @param Title $title Associated title
-        * @param array|bool $params Job parameters
-        * @throws MWException
-        * @return Job
-        */
-       public static function factory( $command, Title $title, $params = false ) {
-               global $wgJobClasses;
-               if ( isset( $wgJobClasses[$command] ) ) {
-                       $class = $wgJobClasses[$command];
-
-                       return new $class( $title, $params );
-               }
-               throw new MWException( "Invalid job command `{$command}`" );
-       }
-
-       /**
-        * Batch-insert a group of jobs into the queue.
-        * This will be wrapped in a transaction with a forced commit.
-        *
-        * This may add duplicate at insert time, but they will be
-        * removed later on, when the first one is popped.
-        *
-        * @param array $jobs of Job objects
-        * @return bool
-        * @deprecated since 1.21
-        */
-       public static function batchInsert( $jobs ) {
-               return JobQueueGroup::singleton()->push( $jobs );
-       }
-
-       /**
-        * Insert a group of jobs into the queue.
-        *
-        * Same as batchInsert() but does not commit and can thus
-        * be rolled-back as part of a larger transaction. However,
-        * large batches of jobs can cause slave lag.
-        *
-        * @param array $jobs of Job objects
-        * @return bool
-        * @deprecated since 1.21
-        */
-       public static function safeBatchInsert( $jobs ) {
-               return JobQueueGroup::singleton()->push( $jobs, JobQueue::QOS_ATOMIC );
-       }
-
-       /**
-        * Pop a job of a certain type.  This tries less hard than pop() to
-        * actually find a job; it may be adversely affected by concurrent job
-        * runners.
-        *
-        * @param $type string
-        * @return Job|bool Returns false if there are no jobs
-        * @deprecated since 1.21
-        */
-       public static function pop_type( $type ) {
-               return JobQueueGroup::singleton()->get( $type )->pop();
-       }
-
-       /**
-        * Pop a job off the front of the queue.
-        * This is subject to $wgJobTypesExcludedFromDefaultQueue.
-        *
-        * @return Job|bool False if there are no jobs
-        * @deprecated since 1.21
-        */
-       public static function pop() {
-               return JobQueueGroup::singleton()->pop();
-       }
-
-       /*-------------------------------------------------------------------------
-        * Non-static functions
-        *------------------------------------------------------------------------*/
-
-       /**
-        * @param $command
-        * @param $title
-        * @param $params array|bool
-        */
-       public function __construct( $command, $title, $params = false ) {
-               $this->command = $command;
-               $this->title = $title;
-               $this->params = $params;
-
-               // expensive jobs may set this to true
-               $this->removeDuplicates = false;
-       }
-
-       /**
-        * @return string
-        */
-       public function getType() {
-               return $this->command;
-       }
-
-       /**
-        * @return Title
-        */
-       public function getTitle() {
-               return $this->title;
-       }
-
-       /**
-        * @return array
-        */
-       public function getParams() {
-               return $this->params;
-       }
-
-       /**
-        * @return int|null UNIX timestamp to delay running this job until, otherwise null
-        * @since 1.22
-        */
-       public function getReleaseTimestamp() {
-               return isset( $this->params['jobReleaseTimestamp'] )
-                       ? wfTimestampOrNull( TS_UNIX, $this->params['jobReleaseTimestamp'] )
-                       : null;
-       }
-
-       /**
-        * @return bool Whether only one of each identical set of jobs should be run
-        */
-       public function ignoreDuplicates() {
-               return $this->removeDuplicates;
-       }
-
-       /**
-        * @return bool Whether this job can be retried on failure by job runners
-        * @since 1.21
-        */
-       public function allowRetries() {
-               return true;
-       }
-
-       /**
-        * @return integer Number of actually "work items" handled in this job
-        * @see $wgJobBackoffThrottling
-        * @since 1.23
-        */
-       public function workItemCount() {
-               return 1;
-       }
-
-       /**
-        * Subclasses may need to override this to make duplication detection work.
-        * The resulting map conveys everything that makes the job unique. This is
-        * only checked if ignoreDuplicates() returns true, meaning that duplicate
-        * jobs are supposed to be ignored.
-        *
-        * @return array Map of key/values
-        * @since 1.21
-        */
-       public function getDeduplicationInfo() {
-               $info = array(
-                       'type' => $this->getType(),
-                       'namespace' => $this->getTitle()->getNamespace(),
-                       'title' => $this->getTitle()->getDBkey(),
-                       'params' => $this->getParams()
-               );
-               if ( is_array( $info['params'] ) ) {
-                       // Identical jobs with different "root" jobs should count as duplicates
-                       unset( $info['params']['rootJobSignature'] );
-                       unset( $info['params']['rootJobTimestamp'] );
-                       // Likewise for jobs with different delay times
-                       unset( $info['params']['jobReleaseTimestamp'] );
-               }
-
-               return $info;
-       }
-
-       /**
-        * @see JobQueue::deduplicateRootJob()
-        * @param string $key A key that identifies the task
-        * @return array Map of:
-        *   - rootJobSignature : hash (e.g. SHA1) that identifies the task
-        *   - rootJobTimestamp : TS_MW timestamp of this instance of the task
-        * @since 1.21
-        */
-       public static function newRootJobParams( $key ) {
-               return array(
-                       'rootJobSignature' => sha1( $key ),
-                       'rootJobTimestamp' => wfTimestampNow()
-               );
-       }
-
-       /**
-        * @see JobQueue::deduplicateRootJob()
-        * @return array
-        * @since 1.21
-        */
-       public function getRootJobParams() {
-               return array(
-                       'rootJobSignature' => isset( $this->params['rootJobSignature'] )
-                               ? $this->params['rootJobSignature']
-                               : null,
-                       'rootJobTimestamp' => isset( $this->params['rootJobTimestamp'] )
-                               ? $this->params['rootJobTimestamp']
-                               : null
-               );
-       }
-
-       /**
-        * @see JobQueue::deduplicateRootJob()
-        * @return bool
-        * @since 1.22
-        */
-       public function hasRootJobParams() {
-               return isset( $this->params['rootJobSignature'] )
-                       && isset( $this->params['rootJobTimestamp'] );
-       }
-
-       /**
-        * Insert a single job into the queue.
-        * @return bool true on success
-        * @deprecated since 1.21
-        */
-       public function insert() {
-               return JobQueueGroup::singleton()->push( $this );
-       }
-
-       /**
-        * @return string
-        */
-       public function toString() {
-               $paramString = '';
-               if ( $this->params ) {
-                       foreach ( $this->params as $key => $value ) {
-                               if ( $paramString != '' ) {
-                                       $paramString .= ' ';
-                               }
-                               if ( is_array( $value ) ) {
-                                       $value = "array(" . count( $value ) . ")";
-                               } elseif ( is_object( $value ) && !method_exists( $value, '__toString' ) ) {
-                                       $value = "object(" . get_class( $value ) . ")";
-                               }
-                               $value = (string)$value;
-                               if ( mb_strlen( $value ) > 1024 ) {
-                                       $value = "string(" . mb_strlen( $value ) . ")";
-                               }
-
-                               $paramString .= "$key=$value";
-                       }
-               }
-
-               if ( is_object( $this->title ) ) {
-                       $s = "{$this->command} " . $this->title->getPrefixedDBkey();
-                       if ( $paramString !== '' ) {
-                               $s .= ' ' . $paramString;
-                       }
-
-                       return $s;
-               } else {
-                       return "{$this->command} $paramString";
-               }
-       }
-
-       protected function setLastError( $error ) {
-               $this->error = $error;
-       }
-
-       public function getLastError() {
-               return $this->error;
-       }
-}
diff --git a/includes/job/JobQueue.php b/includes/job/JobQueue.php
deleted file mode 100644 (file)
index a537861..0000000
+++ /dev/null
@@ -1,745 +0,0 @@
-<?php
-/**
- * Job queue base code.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @defgroup JobQueue JobQueue
- * @author Aaron Schulz
- */
-
-/**
- * Class to handle enqueueing and running of background jobs
- *
- * @ingroup JobQueue
- * @since 1.21
- */
-abstract class JobQueue {
-       /** @var string Wiki ID */
-       protected $wiki;
-
-       /** @var string Job type */
-       protected $type;
-
-       /** @var string Job priority for pop() */
-       protected $order;
-
-       /** @var int Time to live in seconds */
-       protected $claimTTL;
-
-       /** @var int Maximum number of times to try a job */
-       protected $maxTries;
-
-       /** @var bool Allow delayed jobs */
-       protected $checkDelay;
-
-       /** @var BagOStuff */
-       protected $dupCache;
-
-       const QOS_ATOMIC = 1; // integer; "all-or-nothing" job insertions
-
-       const ROOTJOB_TTL = 2419200; // integer; seconds to remember root jobs (28 days)
-
-       /**
-        * @param array $params
-        * @throws MWException
-        */
-       protected function __construct( array $params ) {
-               $this->wiki = $params['wiki'];
-               $this->type = $params['type'];
-               $this->claimTTL = isset( $params['claimTTL'] ) ? $params['claimTTL'] : 0;
-               $this->maxTries = isset( $params['maxTries'] ) ? $params['maxTries'] : 3;
-               if ( isset( $params['order'] ) && $params['order'] !== 'any' ) {
-                       $this->order = $params['order'];
-               } else {
-                       $this->order = $this->optimalOrder();
-               }
-               if ( !in_array( $this->order, $this->supportedOrders() ) ) {
-                       throw new MWException( __CLASS__ . " does not support '{$this->order}' order." );
-               }
-               $this->checkDelay = !empty( $params['checkDelay'] );
-               if ( $this->checkDelay && !$this->supportsDelayedJobs() ) {
-                       throw new MWException( __CLASS__ . " does not support delayed jobs." );
-               }
-               $this->dupCache = wfGetCache( CACHE_ANYTHING );
-       }
-
-       /**
-        * Get a job queue object of the specified type.
-        * $params includes:
-        *   - class      : What job class to use (determines job type)
-        *   - wiki       : wiki ID of the wiki the jobs are for (defaults to current wiki)
-        *   - type       : The name of the job types this queue handles
-        *   - order      : Order that pop() selects jobs, one of "fifo", "timestamp" or "random".
-        *                  If "fifo" is used, the queue will effectively be FIFO. Note that job
-        *                  completion will not appear to be exactly FIFO if there are multiple
-        *                  job runners since jobs can take different times to finish once popped.
-        *                  If "timestamp" is used, the queue will at least be loosely ordered
-        *                  by timestamp, allowing for some jobs to be popped off out of order.
-        *                  If "random" is used, pop() will pick jobs in random order.
-        *                  Note that it may only be weakly random (e.g. a lottery of the oldest X).
-        *                  If "any" is choosen, the queue will use whatever order is the fastest.
-        *                  This might be useful for improving concurrency for job acquisition.
-        *   - claimTTL   : If supported, the queue will recycle jobs that have been popped
-        *                  but not acknowledged as completed after this many seconds. Recycling
-        *                  of jobs simple means re-inserting them into the queue. Jobs can be
-        *                  attempted up to three times before being discarded.
-        *   - checkDelay : If supported, respect Job::getReleaseTimestamp() in the push functions.
-        *                  This lets delayed jobs wait in a staging area until a given timestamp is
-        *                  reached, at which point they will enter the queue. If this is not enabled
-        *                  or not supported, an exception will be thrown on delayed job insertion.
-        *
-        * Queue classes should throw an exception if they do not support the options given.
-        *
-        * @param array $params
-        * @return JobQueue
-        * @throws MWException
-        */
-       final public static function factory( array $params ) {
-               $class = $params['class'];
-               if ( !class_exists( $class ) ) {
-                       throw new MWException( "Invalid job queue class '$class'." );
-               }
-               $obj = new $class( $params );
-               if ( !( $obj instanceof self ) ) {
-                       throw new MWException( "Class '$class' is not a " . __CLASS__ . " class." );
-               }
-
-               return $obj;
-       }
-
-       /**
-        * @return string Wiki ID
-        */
-       final public function getWiki() {
-               return $this->wiki;
-       }
-
-       /**
-        * @return string Job type that this queue handles
-        */
-       final public function getType() {
-               return $this->type;
-       }
-
-       /**
-        * @return string One of (random, timestamp, fifo, undefined)
-        */
-       final public function getOrder() {
-               return $this->order;
-       }
-
-       /**
-        * @return bool Whether delayed jobs are enabled
-        * @since 1.22
-        */
-       final public function delayedJobsEnabled() {
-               return $this->checkDelay;
-       }
-
-       /**
-        * Get the allowed queue orders for configuration validation
-        *
-        * @return array Subset of (random, timestamp, fifo, undefined)
-        */
-       abstract protected function supportedOrders();
-
-       /**
-        * Get the default queue order to use if configuration does not specify one
-        *
-        * @return string One of (random, timestamp, fifo, undefined)
-        */
-       abstract protected function optimalOrder();
-
-       /**
-        * Find out if delayed jobs are supported for configuration validation
-        *
-        * @return bool Whether delayed jobs are supported
-        */
-       protected function supportsDelayedJobs() {
-               return false; // not implemented
-       }
-
-       /**
-        * Quickly check if the queue has no available (unacquired, non-delayed) jobs.
-        * Queue classes should use caching if they are any slower without memcached.
-        *
-        * If caching is used, this might return false when there are actually no jobs.
-        * If pop() is called and returns false then it should correct the cache. Also,
-        * calling flushCaches() first prevents this. However, this affect is typically
-        * not distinguishable from the race condition between isEmpty() and pop().
-        *
-        * @return bool
-        * @throws JobQueueError
-        */
-       final public function isEmpty() {
-               wfProfileIn( __METHOD__ );
-               $res = $this->doIsEmpty();
-               wfProfileOut( __METHOD__ );
-
-               return $res;
-       }
-
-       /**
-        * @see JobQueue::isEmpty()
-        * @return bool
-        */
-       abstract protected function doIsEmpty();
-
-       /**
-        * Get the number of available (unacquired, non-delayed) jobs in the queue.
-        * Queue classes should use caching if they are any slower without memcached.
-        *
-        * If caching is used, this number might be out of date for a minute.
-        *
-        * @return int
-        * @throws JobQueueError
-        */
-       final public function getSize() {
-               wfProfileIn( __METHOD__ );
-               $res = $this->doGetSize();
-               wfProfileOut( __METHOD__ );
-
-               return $res;
-       }
-
-       /**
-        * @see JobQueue::getSize()
-        * @return int
-        */
-       abstract protected function doGetSize();
-
-       /**
-        * Get the number of acquired jobs (these are temporarily out of the queue).
-        * Queue classes should use caching if they are any slower without memcached.
-        *
-        * If caching is used, this number might be out of date for a minute.
-        *
-        * @return int
-        * @throws JobQueueError
-        */
-       final public function getAcquiredCount() {
-               wfProfileIn( __METHOD__ );
-               $res = $this->doGetAcquiredCount();
-               wfProfileOut( __METHOD__ );
-
-               return $res;
-       }
-
-       /**
-        * @see JobQueue::getAcquiredCount()
-        * @return int
-        */
-       abstract protected function doGetAcquiredCount();
-
-       /**
-        * Get the number of delayed jobs (these are temporarily out of the queue).
-        * Queue classes should use caching if they are any slower without memcached.
-        *
-        * If caching is used, this number might be out of date for a minute.
-        *
-        * @return int
-        * @throws JobQueueError
-        * @since 1.22
-        */
-       final public function getDelayedCount() {
-               wfProfileIn( __METHOD__ );
-               $res = $this->doGetDelayedCount();
-               wfProfileOut( __METHOD__ );
-
-               return $res;
-       }
-
-       /**
-        * @see JobQueue::getDelayedCount()
-        * @return int
-        */
-       protected function doGetDelayedCount() {
-               return 0; // not implemented
-       }
-
-       /**
-        * Get the number of acquired jobs that can no longer be attempted.
-        * Queue classes should use caching if they are any slower without memcached.
-        *
-        * If caching is used, this number might be out of date for a minute.
-        *
-        * @return int
-        * @throws JobQueueError
-        */
-       final public function getAbandonedCount() {
-               wfProfileIn( __METHOD__ );
-               $res = $this->doGetAbandonedCount();
-               wfProfileOut( __METHOD__ );
-
-               return $res;
-       }
-
-       /**
-        * @see JobQueue::getAbandonedCount()
-        * @return int
-        */
-       protected function doGetAbandonedCount() {
-               return 0; // not implemented
-       }
-
-       /**
-        * Push one or more jobs into the queue.
-        * This does not require $wgJobClasses to be set for the given job type.
-        * Outside callers should use JobQueueGroup::push() instead of this function.
-        *
-        * @param Job|array $jobs A single job or an array of Jobs
-        * @param int $flags Bitfield (supports JobQueue::QOS_ATOMIC)
-        * @return bool Returns false on failure
-        * @throws JobQueueError
-        */
-       final public function push( $jobs, $flags = 0 ) {
-               return $this->batchPush( is_array( $jobs ) ? $jobs : array( $jobs ), $flags );
-       }
-
-       /**
-        * Push a batch of jobs into the queue.
-        * This does not require $wgJobClasses to be set for the given job type.
-        * Outside callers should use JobQueueGroup::push() instead of this function.
-        *
-        * @param array $jobs List of Jobs
-        * @param int $flags Bitfield (supports JobQueue::QOS_ATOMIC)
-        * @throws MWException
-        * @return bool Returns false on failure
-        */
-       final public function batchPush( array $jobs, $flags = 0 ) {
-               if ( !count( $jobs ) ) {
-                       return true; // nothing to do
-               }
-
-               foreach ( $jobs as $job ) {
-                       if ( $job->getType() !== $this->type ) {
-                               throw new MWException(
-                                       "Got '{$job->getType()}' job; expected a '{$this->type}' job." );
-                       } elseif ( $job->getReleaseTimestamp() && !$this->checkDelay ) {
-                               throw new MWException(
-                                       "Got delayed '{$job->getType()}' job; delays are not supported." );
-                       }
-               }
-
-               wfProfileIn( __METHOD__ );
-               $ok = $this->doBatchPush( $jobs, $flags );
-               wfProfileOut( __METHOD__ );
-
-               return $ok;
-       }
-
-       /**
-        * @see JobQueue::batchPush()
-        * @param array $jobs
-        * @param $flags
-        * @return bool
-        */
-       abstract protected function doBatchPush( array $jobs, $flags );
-
-       /**
-        * Pop a job off of the queue.
-        * This requires $wgJobClasses to be set for the given job type.
-        * Outside callers should use JobQueueGroup::pop() instead of this function.
-        *
-        * @throws MWException
-        * @return Job|bool Returns false if there are no jobs
-        */
-       final public function pop() {
-               global $wgJobClasses;
-
-               if ( $this->wiki !== wfWikiID() ) {
-                       throw new MWException( "Cannot pop '{$this->type}' job off foreign wiki queue." );
-               } elseif ( !isset( $wgJobClasses[$this->type] ) ) {
-                       // Do not pop jobs if there is no class for the queue type
-                       throw new MWException( "Unrecognized job type '{$this->type}'." );
-               }
-
-               wfProfileIn( __METHOD__ );
-               $job = $this->doPop();
-               wfProfileOut( __METHOD__ );
-
-               // Flag this job as an old duplicate based on its "root" job...
-               try {
-                       if ( $job && $this->isRootJobOldDuplicate( $job ) ) {
-                               JobQueue::incrStats( 'job-pop-duplicate', $this->type );
-                               $job = DuplicateJob::newFromJob( $job ); // convert to a no-op
-                       }
-               } catch ( MWException $e ) {
-                       // don't lose jobs over this
-               }
-
-               return $job;
-       }
-
-       /**
-        * @see JobQueue::pop()
-        * @return Job
-        */
-       abstract protected function doPop();
-
-       /**
-        * Acknowledge that a job was completed.
-        *
-        * This does nothing for certain queue classes or if "claimTTL" is not set.
-        * Outside callers should use JobQueueGroup::ack() instead of this function.
-        *
-        * @param Job $job
-        * @throws MWException
-        * @return bool
-        */
-       final public function ack( Job $job ) {
-               if ( $job->getType() !== $this->type ) {
-                       throw new MWException( "Got '{$job->getType()}' job; expected '{$this->type}'." );
-               }
-               wfProfileIn( __METHOD__ );
-               $ok = $this->doAck( $job );
-               wfProfileOut( __METHOD__ );
-
-               return $ok;
-       }
-
-       /**
-        * @see JobQueue::ack()
-        * @param Job $job
-        * @return bool
-        */
-       abstract protected function doAck( Job $job );
-
-       /**
-        * Register the "root job" of a given job into the queue for de-duplication.
-        * This should only be called right *after* all the new jobs have been inserted.
-        * This is used to turn older, duplicate, job entries into no-ops. The root job
-        * information will remain in the registry until it simply falls out of cache.
-        *
-        * This requires that $job has two special fields in the "params" array:
-        *   - rootJobSignature : hash (e.g. SHA1) that identifies the task
-        *   - rootJobTimestamp : TS_MW timestamp of this instance of the task
-        *
-        * A "root job" is a conceptual job that consist of potentially many smaller jobs
-        * that are actually inserted into the queue. For example, "refreshLinks" jobs are
-        * spawned when a template is edited. One can think of the task as "update links
-        * of pages that use template X" and an instance of that task as a "root job".
-        * However, what actually goes into the queue are range and leaf job subtypes.
-        * Since these jobs include things like page ID ranges and DB master positions,
-        * and can morph into smaller jobs recursively, simple duplicate detection
-        * for individual jobs being identical (like that of job_sha1) is not useful.
-        *
-        * In the case of "refreshLinks", if these jobs are still in the queue when the template
-        * is edited again, we want all of these old refreshLinks jobs for that template to become
-        * no-ops. This can greatly reduce server load, since refreshLinks jobs involves parsing.
-        * Essentially, the new batch of jobs belong to a new "root job" and the older ones to a
-        * previous "root job" for the same task of "update links of pages that use template X".
-        *
-        * This does nothing for certain queue classes.
-        *
-        * @param Job $job
-        * @throws MWException
-        * @return bool
-        */
-       final public function deduplicateRootJob( Job $job ) {
-               if ( $job->getType() !== $this->type ) {
-                       throw new MWException( "Got '{$job->getType()}' job; expected '{$this->type}'." );
-               }
-               wfProfileIn( __METHOD__ );
-               $ok = $this->doDeduplicateRootJob( $job );
-               wfProfileOut( __METHOD__ );
-
-               return $ok;
-       }
-
-       /**
-        * @see JobQueue::deduplicateRootJob()
-        * @param Job $job
-        * @throws MWException
-        * @return bool
-        */
-       protected function doDeduplicateRootJob( Job $job ) {
-               if ( !$job->hasRootJobParams() ) {
-                       throw new MWException( "Cannot register root job; missing parameters." );
-               }
-               $params = $job->getRootJobParams();
-
-               $key = $this->getRootJobCacheKey( $params['rootJobSignature'] );
-               // Callers should call batchInsert() and then this function so that if the insert
-               // fails, the de-duplication registration will be aborted. Since the insert is
-               // deferred till "transaction idle", do the same here, so that the ordering is
-               // maintained. Having only the de-duplication registration succeed would cause
-               // jobs to become no-ops without any actual jobs that made them redundant.
-               $timestamp = $this->dupCache->get( $key ); // current last timestamp of this job
-               if ( $timestamp && $timestamp >= $params['rootJobTimestamp'] ) {
-                       return true; // a newer version of this root job was enqueued
-               }
-
-               // Update the timestamp of the last root job started at the location...
-               return $this->dupCache->set( $key, $params['rootJobTimestamp'], JobQueueDB::ROOTJOB_TTL );
-       }
-
-       /**
-        * Check if the "root" job of a given job has been superseded by a newer one
-        *
-        * @param Job $job
-        * @throws MWException
-        * @return bool
-        */
-       final protected function isRootJobOldDuplicate( Job $job ) {
-               if ( $job->getType() !== $this->type ) {
-                       throw new MWException( "Got '{$job->getType()}' job; expected '{$this->type}'." );
-               }
-               wfProfileIn( __METHOD__ );
-               $isDuplicate = $this->doIsRootJobOldDuplicate( $job );
-               wfProfileOut( __METHOD__ );
-
-               return $isDuplicate;
-       }
-
-       /**
-        * @see JobQueue::isRootJobOldDuplicate()
-        * @param Job $job
-        * @return bool
-        */
-       protected function doIsRootJobOldDuplicate( Job $job ) {
-               if ( !$job->hasRootJobParams() ) {
-                       return false; // job has no de-deplication info
-               }
-               $params = $job->getRootJobParams();
-
-               $key = $this->getRootJobCacheKey( $params['rootJobSignature'] );
-               // Get the last time this root job was enqueued
-               $timestamp = $this->dupCache->get( $key );
-
-               // Check if a new root job was started at the location after this one's...
-               return ( $timestamp && $timestamp > $params['rootJobTimestamp'] );
-       }
-
-       /**
-        * @param string $signature Hash identifier of the root job
-        * @return string
-        */
-       protected function getRootJobCacheKey( $signature ) {
-               list( $db, $prefix ) = wfSplitWikiID( $this->wiki );
-
-               return wfForeignMemcKey( $db, $prefix, 'jobqueue', $this->type, 'rootjob', $signature );
-       }
-
-       /**
-        * Deleted all unclaimed and delayed jobs from the queue
-        *
-        * @return bool Success
-        * @throws JobQueueError
-        * @since 1.22
-        */
-       final public function delete() {
-               wfProfileIn( __METHOD__ );
-               $res = $this->doDelete();
-               wfProfileOut( __METHOD__ );
-
-               return $res;
-       }
-
-       /**
-        * @see JobQueue::delete()
-        * @throws MWException
-        * @return bool Success
-        */
-       protected function doDelete() {
-               throw new MWException( "This method is not implemented." );
-       }
-
-       /**
-        * Wait for any slaves or backup servers to catch up.
-        *
-        * This does nothing for certain queue classes.
-        *
-        * @return void
-        * @throws JobQueueError
-        */
-       final public function waitForBackups() {
-               wfProfileIn( __METHOD__ );
-               $this->doWaitForBackups();
-               wfProfileOut( __METHOD__ );
-       }
-
-       /**
-        * @see JobQueue::waitForBackups()
-        * @return void
-        */
-       protected function doWaitForBackups() {
-       }
-
-       /**
-        * Return a map of task names to task definition maps.
-        * A "task" is a fast periodic queue maintenance action.
-        * Mutually exclusive tasks must implement their own locking in the callback.
-        *
-        * Each task value is an associative array with:
-        *   - name     : the name of the task
-        *   - callback : a PHP callable that performs the task
-        *   - period   : the period in seconds corresponding to the task frequency
-        *
-        * @return array
-        */
-       final public function getPeriodicTasks() {
-               $tasks = $this->doGetPeriodicTasks();
-               foreach ( $tasks as $name => &$def ) {
-                       $def['name'] = $name;
-               }
-
-               return $tasks;
-       }
-
-       /**
-        * @see JobQueue::getPeriodicTasks()
-        * @return array
-        */
-       protected function doGetPeriodicTasks() {
-               return array();
-       }
-
-       /**
-        * Clear any process and persistent caches
-        *
-        * @return void
-        */
-       final public function flushCaches() {
-               wfProfileIn( __METHOD__ );
-               $this->doFlushCaches();
-               wfProfileOut( __METHOD__ );
-       }
-
-       /**
-        * @see JobQueue::flushCaches()
-        * @return void
-        */
-       protected function doFlushCaches() {
-       }
-
-       /**
-        * Get an iterator to traverse over all available jobs in this queue.
-        * This does not include jobs that are currently acquired or delayed.
-        * Note: results may be stale if the queue is concurrently modified.
-        *
-        * @return Iterator
-        * @throws JobQueueError
-        */
-       abstract public function getAllQueuedJobs();
-
-       /**
-        * Get an iterator to traverse over all delayed jobs in this queue.
-        * Note: results may be stale if the queue is concurrently modified.
-        *
-        * @return Iterator
-        * @throws JobQueueError
-        * @since 1.22
-        */
-       public function getAllDelayedJobs() {
-               return new ArrayIterator( array() ); // not implemented
-       }
-
-       /**
-        * Do not use this function outside of JobQueue/JobQueueGroup
-        *
-        * @return string
-        * @since 1.22
-        */
-       public function getCoalesceLocationInternal() {
-               return null;
-       }
-
-       /**
-        * Check whether each of the given queues are empty.
-        * This is used for batching checks for queues stored at the same place.
-        *
-        * @param array $types List of queues types
-        * @return array|null (list of non-empty queue types) or null if unsupported
-        * @throws MWException
-        * @since 1.22
-        */
-       final public function getSiblingQueuesWithJobs( array $types ) {
-               $section = new ProfileSection( __METHOD__ );
-
-               return $this->doGetSiblingQueuesWithJobs( $types );
-       }
-
-       /**
-        * @see JobQueue::getSiblingQueuesWithJobs()
-        * @param array $types List of queues types
-        * @return array|null (list of queue types) or null if unsupported
-        */
-       protected function doGetSiblingQueuesWithJobs( array $types ) {
-               return null; // not supported
-       }
-
-       /**
-        * Check the size of each of the given queues.
-        * For queues not served by the same store as this one, 0 is returned.
-        * This is used for batching checks for queues stored at the same place.
-        *
-        * @param array $types List of queues types
-        * @return array|null (job type => whether queue is empty) or null if unsupported
-        * @throws MWException
-        * @since 1.22
-        */
-       final public function getSiblingQueueSizes( array $types ) {
-               $section = new ProfileSection( __METHOD__ );
-
-               return $this->doGetSiblingQueueSizes( $types );
-       }
-
-       /**
-        * @see JobQueue::getSiblingQueuesSize()
-        * @param array $types List of queues types
-        * @return array|null (list of queue types) or null if unsupported
-        */
-       protected function doGetSiblingQueueSizes( array $types ) {
-               return null; // not supported
-       }
-
-       /**
-        * Call wfIncrStats() for the queue overall and for the queue type
-        *
-        * @param string $key Event type
-        * @param string $type Job type
-        * @param int $delta
-        * @since 1.22
-        */
-       public static function incrStats( $key, $type, $delta = 1 ) {
-               wfIncrStats( $key, $delta );
-               wfIncrStats( "{$key}-{$type}", $delta );
-       }
-
-       /**
-        * Namespace the queue with a key to isolate it for testing
-        *
-        * @param string $key
-        * @return void
-        * @throws MWException
-        */
-       public function setTestingPrefix( $key ) {
-               throw new MWException( "Queue namespacing not supported for this queue type." );
-       }
-}
-
-/**
- * @ingroup JobQueue
- * @since 1.22
- */
-class JobQueueError extends MWException {
-}
-
-class JobQueueConnectionError extends JobQueueError {
-}
diff --git a/includes/job/JobQueueDB.php b/includes/job/JobQueueDB.php
deleted file mode 100644 (file)
index 6097d31..0000000
+++ /dev/null
@@ -1,848 +0,0 @@
-<?php
-/**
- * Database-backed job queue code.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @author Aaron Schulz
- */
-
-/**
- * Class to handle job queues stored in the DB
- *
- * @ingroup JobQueue
- * @since 1.21
- */
-class JobQueueDB extends JobQueue {
-       const CACHE_TTL_SHORT = 30; // integer; seconds to cache info without re-validating
-       const CACHE_TTL_LONG = 300; // integer; seconds to cache info that is kept up to date
-       const MAX_AGE_PRUNE = 604800; // integer; seconds a job can live once claimed
-       const MAX_JOB_RANDOM = 2147483647; // integer; 2^31 - 1, used for job_random
-       const MAX_OFFSET = 255; // integer; maximum number of rows to skip
-
-       /** @var BagOStuff */
-       protected $cache;
-
-       /** @var bool|string Name of an external DB cluster. False if not set */
-       protected $cluster = false;
-
-       /**
-        * Additional parameters include:
-        *   - cluster : The name of an external cluster registered via LBFactory.
-        *               If not specified, the primary DB cluster for the wiki will be used.
-        *               This can be overridden with a custom cluster so that DB handles will
-        *               be retrieved via LBFactory::getExternalLB() and getConnection().
-        * @param array $params
-        */
-       protected function __construct( array $params ) {
-               global $wgMemc;
-
-               parent::__construct( $params );
-
-               $this->cluster = isset( $params['cluster'] ) ? $params['cluster'] : false;
-               // Make sure that we don't use the SQL cache, which would be harmful
-               $this->cache = ( $wgMemc instanceof SqlBagOStuff ) ? new EmptyBagOStuff() : $wgMemc;
-       }
-
-       protected function supportedOrders() {
-               return array( 'random', 'timestamp', 'fifo' );
-       }
-
-       protected function optimalOrder() {
-               return 'random';
-       }
-
-       /**
-        * @see JobQueue::doIsEmpty()
-        * @return bool
-        */
-       protected function doIsEmpty() {
-               $key = $this->getCacheKey( 'empty' );
-
-               $isEmpty = $this->cache->get( $key );
-               if ( $isEmpty === 'true' ) {
-                       return true;
-               } elseif ( $isEmpty === 'false' ) {
-                       return false;
-               }
-
-               $dbr = $this->getSlaveDB();
-               try {
-                       $found = $dbr->selectField( // unclaimed job
-                               'job', '1', array( 'job_cmd' => $this->type, 'job_token' => '' ), __METHOD__
-                       );
-               } catch ( DBError $e ) {
-                       $this->throwDBException( $e );
-               }
-               $this->cache->add( $key, $found ? 'false' : 'true', self::CACHE_TTL_LONG );
-
-               return !$found;
-       }
-
-       /**
-        * @see JobQueue::doGetSize()
-        * @return int
-        */
-       protected function doGetSize() {
-               $key = $this->getCacheKey( 'size' );
-
-               $size = $this->cache->get( $key );
-               if ( is_int( $size ) ) {
-                       return $size;
-               }
-
-               try {
-                       $dbr = $this->getSlaveDB();
-                       $size = (int)$dbr->selectField( 'job', 'COUNT(*)',
-                               array( 'job_cmd' => $this->type, 'job_token' => '' ),
-                               __METHOD__
-                       );
-               } catch ( DBError $e ) {
-                       $this->throwDBException( $e );
-               }
-               $this->cache->set( $key, $size, self::CACHE_TTL_SHORT );
-
-               return $size;
-       }
-
-       /**
-        * @see JobQueue::doGetAcquiredCount()
-        * @return int
-        */
-       protected function doGetAcquiredCount() {
-               if ( $this->claimTTL <= 0 ) {
-                       return 0; // no acknowledgements
-               }
-
-               $key = $this->getCacheKey( 'acquiredcount' );
-
-               $count = $this->cache->get( $key );
-               if ( is_int( $count ) ) {
-                       return $count;
-               }
-
-               $dbr = $this->getSlaveDB();
-               try {
-                       $count = (int)$dbr->selectField( 'job', 'COUNT(*)',
-                               array( 'job_cmd' => $this->type, "job_token != {$dbr->addQuotes( '' )}" ),
-                               __METHOD__
-                       );
-               } catch ( DBError $e ) {
-                       $this->throwDBException( $e );
-               }
-               $this->cache->set( $key, $count, self::CACHE_TTL_SHORT );
-
-               return $count;
-       }
-
-       /**
-        * @see JobQueue::doGetAbandonedCount()
-        * @return int
-        * @throws MWException
-        */
-       protected function doGetAbandonedCount() {
-               global $wgMemc;
-
-               if ( $this->claimTTL <= 0 ) {
-                       return 0; // no acknowledgements
-               }
-
-               $key = $this->getCacheKey( 'abandonedcount' );
-
-               $count = $wgMemc->get( $key );
-               if ( is_int( $count ) ) {
-                       return $count;
-               }
-
-               $dbr = $this->getSlaveDB();
-               try {
-                       $count = (int)$dbr->selectField( 'job', 'COUNT(*)',
-                               array(
-                                       'job_cmd' => $this->type,
-                                       "job_token != {$dbr->addQuotes( '' )}",
-                                       "job_attempts >= " . $dbr->addQuotes( $this->maxTries )
-                               ),
-                               __METHOD__
-                       );
-               } catch ( DBError $e ) {
-                       $this->throwDBException( $e );
-               }
-               $wgMemc->set( $key, $count, self::CACHE_TTL_SHORT );
-
-               return $count;
-       }
-
-       /**
-        * @see JobQueue::doBatchPush()
-        * @param array $jobs
-        * @param $flags
-        * @throws DBError|Exception
-        * @return bool
-        */
-       protected function doBatchPush( array $jobs, $flags ) {
-               $dbw = $this->getMasterDB();
-
-               $that = $this;
-               $method = __METHOD__;
-               $dbw->onTransactionIdle(
-                       function () use ( $dbw, $that, $jobs, $flags, $method ) {
-                               $that->doBatchPushInternal( $dbw, $jobs, $flags, $method );
-                       }
-               );
-
-               return true;
-       }
-
-       /**
-        * This function should *not* be called outside of JobQueueDB
-        *
-        * @param IDatabase $dbw
-        * @param array $jobs
-        * @param int $flags
-        * @param string $method
-        * @throws DBError
-        * @return bool
-        */
-       public function doBatchPushInternal( IDatabase $dbw, array $jobs, $flags, $method ) {
-               if ( !count( $jobs ) ) {
-                       return true;
-               }
-
-               $rowSet = array(); // (sha1 => job) map for jobs that are de-duplicated
-               $rowList = array(); // list of jobs for jobs that are are not de-duplicated
-               foreach ( $jobs as $job ) {
-                       $row = $this->insertFields( $job );
-                       if ( $job->ignoreDuplicates() ) {
-                               $rowSet[$row['job_sha1']] = $row;
-                       } else {
-                               $rowList[] = $row;
-                       }
-               }
-
-               if ( $flags & self::QOS_ATOMIC ) {
-                       $dbw->begin( $method ); // wrap all the job additions in one transaction
-               }
-               try {
-                       // Strip out any duplicate jobs that are already in the queue...
-                       if ( count( $rowSet ) ) {
-                               $res = $dbw->select( 'job', 'job_sha1',
-                                       array(
-                                               // No job_type condition since it's part of the job_sha1 hash
-                                               'job_sha1' => array_keys( $rowSet ),
-                                               'job_token' => '' // unclaimed
-                                       ),
-                                       $method
-                               );
-                               foreach ( $res as $row ) {
-                                       wfDebug( "Job with hash '{$row->job_sha1}' is a duplicate.\n" );
-                                       unset( $rowSet[$row->job_sha1] ); // already enqueued
-                               }
-                       }
-                       // Build the full list of job rows to insert
-                       $rows = array_merge( $rowList, array_values( $rowSet ) );
-                       // Insert the job rows in chunks to avoid slave lag...
-                       foreach ( array_chunk( $rows, 50 ) as $rowBatch ) {
-                               $dbw->insert( 'job', $rowBatch, $method );
-                       }
-                       JobQueue::incrStats( 'job-insert', $this->type, count( $rows ) );
-                       JobQueue::incrStats(
-                               'job-insert-duplicate',
-                               $this->type,
-                               count( $rowSet ) + count( $rowList ) - count( $rows )
-                       );
-               } catch ( DBError $e ) {
-                       if ( $flags & self::QOS_ATOMIC ) {
-                               $dbw->rollback( $method );
-                       }
-                       throw $e;
-               }
-               if ( $flags & self::QOS_ATOMIC ) {
-                       $dbw->commit( $method );
-               }
-
-               $this->cache->set( $this->getCacheKey( 'empty' ), 'false', JobQueueDB::CACHE_TTL_LONG );
-
-               return true;
-       }
-
-       /**
-        * @see JobQueue::doPop()
-        * @return Job|bool
-        */
-       protected function doPop() {
-               if ( $this->cache->get( $this->getCacheKey( 'empty' ) ) === 'true' ) {
-                       return false; // queue is empty
-               }
-
-               $dbw = $this->getMasterDB();
-               try {
-                       $dbw->commit( __METHOD__, 'flush' ); // flush existing transaction
-                       $autoTrx = $dbw->getFlag( DBO_TRX ); // get current setting
-                       $dbw->clearFlag( DBO_TRX ); // make each query its own transaction
-                       $scopedReset = new ScopedCallback( function () use ( $dbw, $autoTrx ) {
-                               $dbw->setFlag( $autoTrx ? DBO_TRX : 0 ); // restore old setting
-                       } );
-
-                       $uuid = wfRandomString( 32 ); // pop attempt
-                       $job = false; // job popped off
-                       do { // retry when our row is invalid or deleted as a duplicate
-                               // Try to reserve a row in the DB...
-                               if ( in_array( $this->order, array( 'fifo', 'timestamp' ) ) ) {
-                                       $row = $this->claimOldest( $uuid );
-                               } else { // random first
-                                       $rand = mt_rand( 0, self::MAX_JOB_RANDOM ); // encourage concurrent UPDATEs
-                                       $gte = (bool)mt_rand( 0, 1 ); // find rows with rand before/after $rand
-                                       $row = $this->claimRandom( $uuid, $rand, $gte );
-                               }
-                               // Check if we found a row to reserve...
-                               if ( !$row ) {
-                                       $this->cache->set( $this->getCacheKey( 'empty' ), 'true', self::CACHE_TTL_LONG );
-                                       break; // nothing to do
-                               }
-                               JobQueue::incrStats( 'job-pop', $this->type );
-                               // Get the job object from the row...
-                               $title = Title::makeTitleSafe( $row->job_namespace, $row->job_title );
-                               if ( !$title ) {
-                                       $dbw->delete( 'job', array( 'job_id' => $row->job_id ), __METHOD__ );
-                                       wfDebug( "Row has invalid title '{$row->job_title}'." );
-                                       continue; // try again
-                               }
-                               $job = Job::factory( $row->job_cmd, $title,
-                                       self::extractBlob( $row->job_params ), $row->job_id );
-                               $job->metadata['id'] = $row->job_id;
-                               break; // done
-                       } while ( true );
-               } catch ( DBError $e ) {
-                       $this->throwDBException( $e );
-               }
-
-               return $job;
-       }
-
-       /**
-        * Reserve a row with a single UPDATE without holding row locks over RTTs...
-        *
-        * @param string $uuid 32 char hex string
-        * @param $rand integer Random unsigned integer (31 bits)
-        * @param bool $gte Search for job_random >= $random (otherwise job_random <= $random)
-        * @return stdClass|bool Row|false
-        */
-       protected function claimRandom( $uuid, $rand, $gte ) {
-               $dbw = $this->getMasterDB();
-               // Check cache to see if the queue has <= OFFSET items
-               $tinyQueue = $this->cache->get( $this->getCacheKey( 'small' ) );
-
-               $row = false; // the row acquired
-               $invertedDirection = false; // whether one job_random direction was already scanned
-               // This uses a replication safe method for acquiring jobs. One could use UPDATE+LIMIT
-               // instead, but that either uses ORDER BY (in which case it deadlocks in MySQL) or is
-               // not replication safe. Due to http://bugs.mysql.com/bug.php?id=6980, subqueries cannot
-               // be used here with MySQL.
-               do {
-                       if ( $tinyQueue ) { // queue has <= MAX_OFFSET rows
-                               // For small queues, using OFFSET will overshoot and return no rows more often.
-                               // Instead, this uses job_random to pick a row (possibly checking both directions).
-                               $ineq = $gte ? '>=' : '<=';
-                               $dir = $gte ? 'ASC' : 'DESC';
-                               $row = $dbw->selectRow( 'job', self::selectFields(), // find a random job
-                                       array(
-                                               'job_cmd' => $this->type,
-                                               'job_token' => '', // unclaimed
-                                               "job_random {$ineq} {$dbw->addQuotes( $rand )}" ),
-                                       __METHOD__,
-                                       array( 'ORDER BY' => "job_random {$dir}" )
-                               );
-                               if ( !$row && !$invertedDirection ) {
-                                       $gte = !$gte;
-                                       $invertedDirection = true;
-                                       continue; // try the other direction
-                               }
-                       } else { // table *may* have >= MAX_OFFSET rows
-                               // Bug 42614: "ORDER BY job_random" with a job_random inequality causes high CPU
-                               // in MySQL if there are many rows for some reason. This uses a small OFFSET
-                               // instead of job_random for reducing excess claim retries.
-                               $row = $dbw->selectRow( 'job', self::selectFields(), // find a random job
-                                       array(
-                                               'job_cmd' => $this->type,
-                                               'job_token' => '', // unclaimed
-                                       ),
-                                       __METHOD__,
-                                       array( 'OFFSET' => mt_rand( 0, self::MAX_OFFSET ) )
-                               );
-                               if ( !$row ) {
-                                       $tinyQueue = true; // we know the queue must have <= MAX_OFFSET rows
-                                       $this->cache->set( $this->getCacheKey( 'small' ), 1, 30 );
-                                       continue; // use job_random
-                               }
-                       }
-
-                       if ( $row ) { // claim the job
-                               $dbw->update( 'job', // update by PK
-                                       array(
-                                               'job_token' => $uuid,
-                                               'job_token_timestamp' => $dbw->timestamp(),
-                                               'job_attempts = job_attempts+1' ),
-                                       array( 'job_cmd' => $this->type, 'job_id' => $row->job_id, 'job_token' => '' ),
-                                       __METHOD__
-                               );
-                               // This might get raced out by another runner when claiming the previously
-                               // selected row. The use of job_random should minimize this problem, however.
-                               if ( !$dbw->affectedRows() ) {
-                                       $row = false; // raced out
-                               }
-                       } else {
-                               break; // nothing to do
-                       }
-               } while ( !$row );
-
-               return $row;
-       }
-
-       /**
-        * Reserve a row with a single UPDATE without holding row locks over RTTs...
-        *
-        * @param string $uuid 32 char hex string
-        * @return stdClass|bool Row|false
-        */
-       protected function claimOldest( $uuid ) {
-               $dbw = $this->getMasterDB();
-
-               $row = false; // the row acquired
-               do {
-                       if ( $dbw->getType() === 'mysql' ) {
-                               // Per http://bugs.mysql.com/bug.php?id=6980, we can't use subqueries on the
-                               // same table being changed in an UPDATE query in MySQL (gives Error: 1093).
-                               // Oracle and Postgre have no such limitation. However, MySQL offers an
-                               // alternative here by supporting ORDER BY + LIMIT for UPDATE queries.
-                               $dbw->query( "UPDATE {$dbw->tableName( 'job' )} " .
-                                       "SET " .
-                                               "job_token = {$dbw->addQuotes( $uuid ) }, " .
-                                               "job_token_timestamp = {$dbw->addQuotes( $dbw->timestamp() )}, " .
-                                               "job_attempts = job_attempts+1 " .
-                                       "WHERE ( " .
-                                               "job_cmd = {$dbw->addQuotes( $this->type )} " .
-                                               "AND job_token = {$dbw->addQuotes( '' )} " .
-                                       ") ORDER BY job_id ASC LIMIT 1",
-                                       __METHOD__
-                               );
-                       } else {
-                               // Use a subquery to find the job, within an UPDATE to claim it.
-                               // This uses as much of the DB wrapper functions as possible.
-                               $dbw->update( 'job',
-                                       array(
-                                               'job_token' => $uuid,
-                                               'job_token_timestamp' => $dbw->timestamp(),
-                                               'job_attempts = job_attempts+1' ),
-                                       array( 'job_id = (' .
-                                               $dbw->selectSQLText( 'job', 'job_id',
-                                                       array( 'job_cmd' => $this->type, 'job_token' => '' ),
-                                                       __METHOD__,
-                                                       array( 'ORDER BY' => 'job_id ASC', 'LIMIT' => 1 ) ) .
-                                               ')'
-                                       ),
-                                       __METHOD__
-                               );
-                       }
-                       // Fetch any row that we just reserved...
-                       if ( $dbw->affectedRows() ) {
-                               $row = $dbw->selectRow( 'job', self::selectFields(),
-                                       array( 'job_cmd' => $this->type, 'job_token' => $uuid ), __METHOD__
-                               );
-                               if ( !$row ) { // raced out by duplicate job removal
-                                       wfDebug( "Row deleted as duplicate by another process." );
-                               }
-                       } else {
-                               break; // nothing to do
-                       }
-               } while ( !$row );
-
-               return $row;
-       }
-
-       /**
-        * @see JobQueue::doAck()
-        * @param Job $job
-        * @throws MWException
-        * @return Job|bool
-        */
-       protected function doAck( Job $job ) {
-               if ( !isset( $job->metadata['id'] ) ) {
-                       throw new MWException( "Job of type '{$job->getType()}' has no ID." );
-               }
-
-               $dbw = $this->getMasterDB();
-               try {
-                       $dbw->commit( __METHOD__, 'flush' ); // flush existing transaction
-                       $autoTrx = $dbw->getFlag( DBO_TRX ); // get current setting
-                       $dbw->clearFlag( DBO_TRX ); // make each query its own transaction
-                       $scopedReset = new ScopedCallback( function () use ( $dbw, $autoTrx ) {
-                               $dbw->setFlag( $autoTrx ? DBO_TRX : 0 ); // restore old setting
-                       } );
-
-                       // Delete a row with a single DELETE without holding row locks over RTTs...
-                       $dbw->delete( 'job',
-                               array( 'job_cmd' => $this->type, 'job_id' => $job->metadata['id'] ), __METHOD__ );
-               } catch ( DBError $e ) {
-                       $this->throwDBException( $e );
-               }
-
-               return true;
-       }
-
-       /**
-        * @see JobQueue::doDeduplicateRootJob()
-        * @param Job $job
-        * @throws MWException
-        * @return bool
-        */
-       protected function doDeduplicateRootJob( Job $job ) {
-               $params = $job->getParams();
-               if ( !isset( $params['rootJobSignature'] ) ) {
-                       throw new MWException( "Cannot register root job; missing 'rootJobSignature'." );
-               } elseif ( !isset( $params['rootJobTimestamp'] ) ) {
-                       throw new MWException( "Cannot register root job; missing 'rootJobTimestamp'." );
-               }
-               $key = $this->getRootJobCacheKey( $params['rootJobSignature'] );
-               // Callers should call batchInsert() and then this function so that if the insert
-               // fails, the de-duplication registration will be aborted. Since the insert is
-               // deferred till "transaction idle", do the same here, so that the ordering is
-               // maintained. Having only the de-duplication registration succeed would cause
-               // jobs to become no-ops without any actual jobs that made them redundant.
-               $dbw = $this->getMasterDB();
-               $cache = $this->dupCache;
-               $dbw->onTransactionIdle( function () use ( $cache, $params, $key, $dbw ) {
-                       $timestamp = $cache->get( $key ); // current last timestamp of this job
-                       if ( $timestamp && $timestamp >= $params['rootJobTimestamp'] ) {
-                               return true; // a newer version of this root job was enqueued
-                       }
-
-                       // Update the timestamp of the last root job started at the location...
-                       return $cache->set( $key, $params['rootJobTimestamp'], JobQueueDB::ROOTJOB_TTL );
-               } );
-
-               return true;
-       }
-
-       /**
-        * @see JobQueue::doDelete()
-        * @return bool
-        */
-       protected function doDelete() {
-               $dbw = $this->getMasterDB();
-               try {
-                       $dbw->delete( 'job', array( 'job_cmd' => $this->type ) );
-               } catch ( DBError $e ) {
-                       $this->throwDBException( $e );
-               }
-
-               return true;
-       }
-
-       /**
-        * @see JobQueue::doWaitForBackups()
-        * @return void
-        */
-       protected function doWaitForBackups() {
-               wfWaitForSlaves();
-       }
-
-       /**
-        * @return array
-        */
-       protected function doGetPeriodicTasks() {
-               return array(
-                       'recycleAndDeleteStaleJobs' => array(
-                               'callback' => array( $this, 'recycleAndDeleteStaleJobs' ),
-                               'period' => ceil( $this->claimTTL / 2 )
-                       )
-               );
-       }
-
-       /**
-        * @return void
-        */
-       protected function doFlushCaches() {
-               foreach ( array( 'empty', 'size', 'acquiredcount' ) as $type ) {
-                       $this->cache->delete( $this->getCacheKey( $type ) );
-               }
-       }
-
-       /**
-        * @see JobQueue::getAllQueuedJobs()
-        * @return Iterator
-        */
-       public function getAllQueuedJobs() {
-               $dbr = $this->getSlaveDB();
-               try {
-                       return new MappedIterator(
-                               $dbr->select( 'job', self::selectFields(),
-                                       array( 'job_cmd' => $this->getType(), 'job_token' => '' ) ),
-                               function ( $row ) use ( $dbr ) {
-                                       $job = Job::factory(
-                                               $row->job_cmd,
-                                               Title::makeTitle( $row->job_namespace, $row->job_title ),
-                                               strlen( $row->job_params ) ? unserialize( $row->job_params ) : false
-                                       );
-                                       $job->metadata['id'] = $row->job_id;
-                                       return $job;
-                               }
-                       );
-               } catch ( DBError $e ) {
-                       $this->throwDBException( $e );
-               }
-       }
-
-       public function getCoalesceLocationInternal() {
-               return $this->cluster
-                       ? "DBCluster:{$this->cluster}:{$this->wiki}"
-                       : "LBFactory:{$this->wiki}";
-       }
-
-       protected function doGetSiblingQueuesWithJobs( array $types ) {
-               $dbr = $this->getSlaveDB();
-               $res = $dbr->select( 'job', 'DISTINCT job_cmd',
-                       array( 'job_cmd' => $types ), __METHOD__ );
-
-               $types = array();
-               foreach ( $res as $row ) {
-                       $types[] = $row->job_cmd;
-               }
-
-               return $types;
-       }
-
-       protected function doGetSiblingQueueSizes( array $types ) {
-               $dbr = $this->getSlaveDB();
-               $res = $dbr->select( 'job', array( 'job_cmd', 'COUNT(*) AS count' ),
-                       array( 'job_cmd' => $types ), __METHOD__, array( 'GROUP BY' => 'job_cmd' ) );
-
-               $sizes = array();
-               foreach ( $res as $row ) {
-                       $sizes[$row->job_cmd] = (int)$row->count;
-               }
-
-               return $sizes;
-       }
-
-       /**
-        * Recycle or destroy any jobs that have been claimed for too long
-        *
-        * @return int Number of jobs recycled/deleted
-        */
-       public function recycleAndDeleteStaleJobs() {
-               $now = time();
-               $count = 0; // affected rows
-               $dbw = $this->getMasterDB();
-
-               try {
-                       if ( !$dbw->lock( "jobqueue-recycle-{$this->type}", __METHOD__, 1 ) ) {
-                               return $count; // already in progress
-                       }
-
-                       // Remove claims on jobs acquired for too long if enabled...
-                       if ( $this->claimTTL > 0 ) {
-                               $claimCutoff = $dbw->timestamp( $now - $this->claimTTL );
-                               // Get the IDs of jobs that have be claimed but not finished after too long.
-                               // These jobs can be recycled into the queue by expiring the claim. Selecting
-                               // the IDs first means that the UPDATE can be done by primary key (less deadlocks).
-                               $res = $dbw->select( 'job', 'job_id',
-                                       array(
-                                               'job_cmd' => $this->type,
-                                               "job_token != {$dbw->addQuotes( '' )}", // was acquired
-                                               "job_token_timestamp < {$dbw->addQuotes( $claimCutoff )}", // stale
-                                               "job_attempts < {$dbw->addQuotes( $this->maxTries )}" ), // retries left
-                                       __METHOD__
-                               );
-                               $ids = array_map(
-                                       function ( $o ) {
-                                               return $o->job_id;
-                                       }, iterator_to_array( $res )
-                               );
-                               if ( count( $ids ) ) {
-                                       // Reset job_token for these jobs so that other runners will pick them up.
-                                       // Set the timestamp to the current time, as it is useful to now that the job
-                                       // was already tried before (the timestamp becomes the "released" time).
-                                       $dbw->update( 'job',
-                                               array(
-                                                       'job_token' => '',
-                                                       'job_token_timestamp' => $dbw->timestamp( $now ) ), // time of release
-                                               array(
-                                                       'job_id' => $ids ),
-                                               __METHOD__
-                                       );
-                                       $count += $dbw->affectedRows();
-                                       JobQueue::incrStats( 'job-recycle', $this->type, $dbw->affectedRows() );
-                                       $this->cache->set( $this->getCacheKey( 'empty' ), 'false', self::CACHE_TTL_LONG );
-                               }
-                       }
-
-                       // Just destroy any stale jobs...
-                       $pruneCutoff = $dbw->timestamp( $now - self::MAX_AGE_PRUNE );
-                       $conds = array(
-                               'job_cmd' => $this->type,
-                               "job_token != {$dbw->addQuotes( '' )}", // was acquired
-                               "job_token_timestamp < {$dbw->addQuotes( $pruneCutoff )}" // stale
-                       );
-                       if ( $this->claimTTL > 0 ) { // only prune jobs attempted too many times...
-                               $conds[] = "job_attempts >= {$dbw->addQuotes( $this->maxTries )}";
-                       }
-                       // Get the IDs of jobs that are considered stale and should be removed. Selecting
-                       // the IDs first means that the UPDATE can be done by primary key (less deadlocks).
-                       $res = $dbw->select( 'job', 'job_id', $conds, __METHOD__ );
-                       $ids = array_map(
-                               function ( $o ) {
-                                       return $o->job_id;
-                               }, iterator_to_array( $res )
-                       );
-                       if ( count( $ids ) ) {
-                               $dbw->delete( 'job', array( 'job_id' => $ids ), __METHOD__ );
-                               $count += $dbw->affectedRows();
-                               JobQueue::incrStats( 'job-abandon', $this->type, $dbw->affectedRows() );
-                       }
-
-                       $dbw->unlock( "jobqueue-recycle-{$this->type}", __METHOD__ );
-               } catch ( DBError $e ) {
-                       $this->throwDBException( $e );
-               }
-
-               return $count;
-       }
-
-       /**
-        * @param IJobSpecification $job
-        * @return array
-        */
-       protected function insertFields( IJobSpecification $job ) {
-               $dbw = $this->getMasterDB();
-
-               return array(
-                       // Fields that describe the nature of the job
-                       'job_cmd' => $job->getType(),
-                       'job_namespace' => $job->getTitle()->getNamespace(),
-                       'job_title' => $job->getTitle()->getDBkey(),
-                       'job_params' => self::makeBlob( $job->getParams() ),
-                       // Additional job metadata
-                       'job_id' => $dbw->nextSequenceValue( 'job_job_id_seq' ),
-                       'job_timestamp' => $dbw->timestamp(),
-                       'job_sha1' => wfBaseConvert(
-                               sha1( serialize( $job->getDeduplicationInfo() ) ),
-                               16, 36, 31
-                       ),
-                       'job_random' => mt_rand( 0, self::MAX_JOB_RANDOM )
-               );
-       }
-
-       /**
-        * @throws JobQueueConnectionError
-        * @return DBConnRef
-        */
-       protected function getSlaveDB() {
-               try {
-                       return $this->getDB( DB_SLAVE );
-               } catch ( DBConnectionError $e ) {
-                       throw new JobQueueConnectionError( "DBConnectionError:" . $e->getMessage() );
-               }
-       }
-
-       /**
-        * @throws JobQueueConnectionError
-        * @return DBConnRef
-        */
-       protected function getMasterDB() {
-               try {
-                       return $this->getDB( DB_MASTER );
-               } catch ( DBConnectionError $e ) {
-                       throw new JobQueueConnectionError( "DBConnectionError:" . $e->getMessage() );
-               }
-       }
-
-       /**
-        * @param $index integer (DB_SLAVE/DB_MASTER)
-        * @return DBConnRef
-        */
-       protected function getDB( $index ) {
-               $lb = ( $this->cluster !== false )
-                       ? wfGetLBFactory()->getExternalLB( $this->cluster, $this->wiki )
-                       : wfGetLB( $this->wiki );
-
-               return $lb->getConnectionRef( $index, array(), $this->wiki );
-       }
-
-       /**
-        * @param $property
-        * @return string
-        */
-       private function getCacheKey( $property ) {
-               list( $db, $prefix ) = wfSplitWikiID( $this->wiki );
-               $cluster = is_string( $this->cluster ) ? $this->cluster : 'main';
-
-               return wfForeignMemcKey( $db, $prefix, 'jobqueue', $cluster, $this->type, $property );
-       }
-
-       /**
-        * @param $params
-        * @return string
-        */
-       protected static function makeBlob( $params ) {
-               if ( $params !== false ) {
-                       return serialize( $params );
-               } else {
-                       return '';
-               }
-       }
-
-       /**
-        * @param $blob
-        * @return bool|mixed
-        */
-       protected static function extractBlob( $blob ) {
-               if ( (string)$blob !== '' ) {
-                       return unserialize( $blob );
-               } else {
-                       return false;
-               }
-       }
-
-       /**
-        * @param DBError $e
-        * @throws JobQueueError
-        */
-       protected function throwDBException( DBError $e ) {
-               throw new JobQueueError( get_class( $e ) . ": " . $e->getMessage() );
-       }
-
-       /**
-        * Return the list of job fields that should be selected.
-        * @since 1.23
-        * @return array
-        */
-       public static function selectFields() {
-               return array(
-                       'job_id',
-                       'job_cmd',
-                       'job_namespace',
-                       'job_title',
-                       'job_timestamp',
-                       'job_params',
-                       'job_random',
-                       'job_attempts',
-                       'job_token',
-                       'job_token_timestamp',
-                       'job_sha1',
-               );
-       }
-}
diff --git a/includes/job/JobQueueFederated.php b/includes/job/JobQueueFederated.php
deleted file mode 100644 (file)
index 9502148..0000000
+++ /dev/null
@@ -1,553 +0,0 @@
-<?php
-/**
- * Job queue code for federated queues.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @author Aaron Schulz
- */
-
-/**
- * Class to handle enqueueing and running of background jobs for federated queues
- *
- * This class allows for queues to be partitioned into smaller queues.
- * A partition is defined by the configuration for a JobQueue instance.
- * For example, one can set $wgJobTypeConf['refreshLinks'] to point to a
- * JobQueueFederated instance, which itself would consist of three JobQueueRedis
- * instances, each using their own redis server. This would allow for the jobs
- * to be split (evenly or based on weights) accross multiple servers if a single
- * server becomes impractical or expensive. Different JobQueue classes can be mixed.
- *
- * The basic queue configuration (e.g. "order", "claimTTL") of a federated queue
- * is inherited by the partition queues. Additional configuration defines what
- * section each wiki is in, what partition queues each section uses (and their weight),
- * and the JobQueue configuration for each partition. Some sections might only need a
- * single queue partition, like the sections for groups of small wikis.
- *
- * If used for performance, then $wgMainCacheType should be set to memcached/redis.
- * Note that "fifo" cannot be used for the ordering, since the data is distributed.
- * One can still use "timestamp" instead, as in "roughly timestamp ordered". Also,
- * queue classes used by this should ignore down servers (with TTL) to avoid slowness.
- *
- * @ingroup JobQueue
- * @since 1.22
- */
-class JobQueueFederated extends JobQueue {
-       /** @var array (partition name => weight) reverse sorted by weight */
-       protected $partitionMap = array();
-
-       /** @var array (partition name => JobQueue) reverse sorted by weight */
-       protected $partitionQueues = array();
-
-       /** @var HashRing */
-       protected $partitionPushRing;
-
-       /** @var BagOStuff */
-       protected $cache;
-
-       /** @var int Maximum number of partitions to try */
-       protected $maxPartitionsTry;
-
-       const CACHE_TTL_SHORT = 30; // integer; seconds to cache info without re-validating
-       const CACHE_TTL_LONG = 300; // integer; seconds to cache info that is kept up to date
-
-       /**
-        * @params include:
-        *  - sectionsByWiki      : A map of wiki IDs to section names.
-        *                          Wikis will default to using the section "default".
-        *  - partitionsBySection : Map of section names to maps of (partition name => weight).
-        *                          A section called 'default' must be defined if not all wikis
-        *                          have explicitly defined sections.
-        *  - configByPartition   : Map of queue partition names to configuration arrays.
-        *                          These configuration arrays are passed to JobQueue::factory().
-        *                          The options set here are overriden by those passed to this
-        *                          the federated queue itself (e.g. 'order' and 'claimTTL').
-        *  - partitionsNoPush    : List of partition names that can handle pop() but not push().
-        *                          This can be used to migrate away from a certain partition.
-        *  - maxPartitionsTry    : Maximum number of times to attempt job insertion using
-        *                          different partition queues. This improves availability
-        *                          during failure, at the cost of added latency and somewhat
-        *                          less reliable job de-duplication mechanisms.
-        * @param array $params
-        * @throws MWException
-        */
-       protected function __construct( array $params ) {
-               parent::__construct( $params );
-               $section = isset( $params['sectionsByWiki'][$this->wiki] )
-                       ? $params['sectionsByWiki'][$this->wiki]
-                       : 'default';
-               if ( !isset( $params['partitionsBySection'][$section] ) ) {
-                       throw new MWException( "No configuration for section '$section'." );
-               }
-               $this->maxPartitionsTry = isset( $params['maxPartitionsTry'] )
-                       ? $params['maxPartitionsTry']
-                       : 2;
-               // Get the full partition map
-               $this->partitionMap = $params['partitionsBySection'][$section];
-               arsort( $this->partitionMap, SORT_NUMERIC );
-               // Get the partitions jobs can actually be pushed to
-               $partitionPushMap = $this->partitionMap;
-               if ( isset( $params['partitionsNoPush'] ) ) {
-                       foreach ( $params['partitionsNoPush'] as $partition ) {
-                               unset( $partitionPushMap[$partition] );
-                       }
-               }
-               // Get the config to pass to merge into each partition queue config
-               $baseConfig = $params;
-               foreach ( array( 'class', 'sectionsByWiki', 'maxPartitionsTry',
-                       'partitionsBySection', 'configByPartition', 'partitionsNoPush' ) as $o
-               ) {
-                       unset( $baseConfig[$o] ); // partition queue doesn't care about this
-               }
-               // Get the partition queue objects
-               foreach ( $this->partitionMap as $partition => $w ) {
-                       if ( !isset( $params['configByPartition'][$partition] ) ) {
-                               throw new MWException( "No configuration for partition '$partition'." );
-                       }
-                       $this->partitionQueues[$partition] = JobQueue::factory(
-                               $baseConfig + $params['configByPartition'][$partition] );
-               }
-               // Get the ring of partitions to push jobs into
-               $this->partitionPushRing = new HashRing( $partitionPushMap );
-               // Aggregate cache some per-queue values if there are multiple partition queues
-               $this->cache = count( $this->partitionMap ) > 1 ? wfGetMainCache() : new EmptyBagOStuff();
-       }
-
-       protected function supportedOrders() {
-               // No FIFO due to partitioning, though "rough timestamp order" is supported
-               return array( 'undefined', 'random', 'timestamp' );
-       }
-
-       protected function optimalOrder() {
-               return 'undefined'; // defer to the partitions
-       }
-
-       protected function supportsDelayedJobs() {
-               return true; // defer checks to the partitions
-       }
-
-       protected function doIsEmpty() {
-               $key = $this->getCacheKey( 'empty' );
-
-               $isEmpty = $this->cache->get( $key );
-               if ( $isEmpty === 'true' ) {
-                       return true;
-               } elseif ( $isEmpty === 'false' ) {
-                       return false;
-               }
-
-               $empty = true;
-               $failed = 0;
-               foreach ( $this->partitionQueues as $queue ) {
-                       try {
-                               $empty = $empty && $queue->doIsEmpty();
-                       } catch ( JobQueueError $e ) {
-                               ++$failed;
-                               MWExceptionHandler::logException( $e );
-                       }
-               }
-               $this->throwErrorIfAllPartitionsDown( $failed );
-
-               $this->cache->add( $key, $empty ? 'true' : 'false', self::CACHE_TTL_LONG );
-               return $empty;
-       }
-
-       protected function doGetSize() {
-               return $this->getCrossPartitionSum( 'size', 'doGetSize' );
-       }
-
-       protected function doGetAcquiredCount() {
-               return $this->getCrossPartitionSum( 'acquiredcount', 'doGetAcquiredCount' );
-       }
-
-       protected function doGetDelayedCount() {
-               return $this->getCrossPartitionSum( 'delayedcount', 'doGetDelayedCount' );
-       }
-
-       protected function doGetAbandonedCount() {
-               return $this->getCrossPartitionSum( 'abandonedcount', 'doGetAbandonedCount' );
-       }
-
-       /**
-        * @param string $type
-        * @param string $method
-        * @return int
-        */
-       protected function getCrossPartitionSum( $type, $method ) {
-               $key = $this->getCacheKey( $type );
-
-               $count = $this->cache->get( $key );
-               if ( is_int( $count ) ) {
-                       return $count;
-               }
-
-               $failed = 0;
-               foreach ( $this->partitionQueues as $queue ) {
-                       try {
-                               $count += $queue->$method();
-                       } catch ( JobQueueError $e ) {
-                               ++$failed;
-                               MWExceptionHandler::logException( $e );
-                       }
-               }
-               $this->throwErrorIfAllPartitionsDown( $failed );
-
-               $this->cache->set( $key, $count, self::CACHE_TTL_SHORT );
-
-               return $count;
-       }
-
-       protected function doBatchPush( array $jobs, $flags ) {
-               // Local ring variable that may be changed to point to a new ring on failure
-               $partitionRing = $this->partitionPushRing;
-               // Try to insert the jobs and update $partitionsTry on any failures.
-               // Retry to insert any remaning jobs again, ignoring the bad partitions.
-               $jobsLeft = $jobs;
-               for ( $i = $this->maxPartitionsTry; $i > 0 && count( $jobsLeft ); --$i ) {
-                       $jobsLeft = $this->tryJobInsertions( $jobsLeft, $partitionRing, $flags );
-               }
-               if ( count( $jobsLeft ) ) {
-                       throw new JobQueueError(
-                               "Could not insert job(s), {$this->maxPartitionsTry} partitions tried." );
-               }
-
-               return true;
-       }
-
-       /**
-        * @param array $jobs
-        * @param HashRing $partitionRing
-        * @param int $flags
-        * @throws JobQueueError
-        * @return array List of Job object that could not be inserted
-        */
-       protected function tryJobInsertions( array $jobs, HashRing &$partitionRing, $flags ) {
-               $jobsLeft = array();
-
-               // Because jobs are spread across partitions, per-job de-duplication needs
-               // to use a consistent hash to avoid allowing duplicate jobs per partition.
-               // When inserting a batch of de-duplicated jobs, QOS_ATOMIC is disregarded.
-               $uJobsByPartition = array(); // (partition name => job list)
-               /** @var Job $job */
-               foreach ( $jobs as $key => $job ) {
-                       if ( $job->ignoreDuplicates() ) {
-                               $sha1 = sha1( serialize( $job->getDeduplicationInfo() ) );
-                               $uJobsByPartition[$partitionRing->getLocation( $sha1 )][] = $job;
-                               unset( $jobs[$key] );
-                       }
-               }
-               // Get the batches of jobs that are not de-duplicated
-               if ( $flags & self::QOS_ATOMIC ) {
-                       $nuJobBatches = array( $jobs ); // all or nothing
-               } else {
-                       // Split the jobs into batches and spread them out over servers if there
-                       // are many jobs. This helps keep the partitions even. Otherwise, send all
-                       // the jobs to a single partition queue to avoids the extra connections.
-                       $nuJobBatches = array_chunk( $jobs, 300 );
-               }
-
-               // Insert the de-duplicated jobs into the queues...
-               foreach ( $uJobsByPartition as $partition => $jobBatch ) {
-                       /** @var JobQueue $queue */
-                       $queue = $this->partitionQueues[$partition];
-                       try {
-                               $ok = $queue->doBatchPush( $jobBatch, $flags | self::QOS_ATOMIC );
-                       } catch ( JobQueueError $e ) {
-                               $ok = false;
-                               MWExceptionHandler::logException( $e );
-                       }
-                       if ( $ok ) {
-                               $key = $this->getCacheKey( 'empty' );
-                               $this->cache->set( $key, 'false', JobQueueDB::CACHE_TTL_LONG );
-                       } else {
-                               $partitionRing = $partitionRing->newWithoutLocation( $partition ); // blacklist
-                               if ( !$partitionRing ) {
-                                       throw new JobQueueError( "Could not insert job(s), no partitions available." );
-                               }
-                               $jobsLeft = array_merge( $jobsLeft, $jobBatch ); // not inserted
-                       }
-               }
-
-               // Insert the jobs that are not de-duplicated into the queues...
-               foreach ( $nuJobBatches as $jobBatch ) {
-                       $partition = ArrayUtils::pickRandom( $partitionRing->getLocationWeights() );
-                       $queue = $this->partitionQueues[$partition];
-                       try {
-                               $ok = $queue->doBatchPush( $jobBatch, $flags | self::QOS_ATOMIC );
-                       } catch ( JobQueueError $e ) {
-                               $ok = false;
-                               MWExceptionHandler::logException( $e );
-                       }
-                       if ( $ok ) {
-                               $key = $this->getCacheKey( 'empty' );
-                               $this->cache->set( $key, 'false', JobQueueDB::CACHE_TTL_LONG );
-                       } else {
-                               $partitionRing = $partitionRing->newWithoutLocation( $partition ); // blacklist
-                               if ( !$partitionRing ) {
-                                       throw new JobQueueError( "Could not insert job(s), no partitions available." );
-                               }
-                               $jobsLeft = array_merge( $jobsLeft, $jobBatch ); // not inserted
-                       }
-               }
-
-               return $jobsLeft;
-       }
-
-       protected function doPop() {
-               $key = $this->getCacheKey( 'empty' );
-
-               $isEmpty = $this->cache->get( $key );
-               if ( $isEmpty === 'true' ) {
-                       return false;
-               }
-
-               $partitionsTry = $this->partitionMap; // (partition => weight)
-
-               $failed = 0;
-               while ( count( $partitionsTry ) ) {
-                       $partition = ArrayUtils::pickRandom( $partitionsTry );
-                       if ( $partition === false ) {
-                               break; // all partitions at 0 weight
-                       }
-
-                       /** @var JobQueue $queue */
-                       $queue = $this->partitionQueues[$partition];
-                       try {
-                               $job = $queue->pop();
-                       } catch ( JobQueueError $e ) {
-                               ++$failed;
-                               MWExceptionHandler::logException( $e );
-                               $job = false;
-                       }
-                       if ( $job ) {
-                               $job->metadata['QueuePartition'] = $partition;
-
-                               return $job;
-                       } else {
-                               unset( $partitionsTry[$partition] ); // blacklist partition
-                       }
-               }
-               $this->throwErrorIfAllPartitionsDown( $failed );
-
-               $this->cache->set( $key, 'true', JobQueueDB::CACHE_TTL_LONG );
-
-               return false;
-       }
-
-       protected function doAck( Job $job ) {
-               if ( !isset( $job->metadata['QueuePartition'] ) ) {
-                       throw new MWException( "The given job has no defined partition name." );
-               }
-
-               return $this->partitionQueues[$job->metadata['QueuePartition']]->ack( $job );
-       }
-
-       protected function doIsRootJobOldDuplicate( Job $job ) {
-               $params = $job->getRootJobParams();
-               $partitions = $this->partitionPushRing->getLocations( $params['rootJobSignature'], 2 );
-               try {
-                       return $this->partitionQueues[$partitions[0]]->doIsRootJobOldDuplicate( $job );
-               } catch ( JobQueueError $e ) {
-                       if ( isset( $partitions[1] ) ) { // check fallback partition
-                               return $this->partitionQueues[$partitions[1]]->doIsRootJobOldDuplicate( $job );
-                       }
-               }
-
-               return false;
-       }
-
-       protected function doDeduplicateRootJob( Job $job ) {
-               $params = $job->getRootJobParams();
-               $partitions = $this->partitionPushRing->getLocations( $params['rootJobSignature'], 2 );
-               try {
-                       return $this->partitionQueues[$partitions[0]]->doDeduplicateRootJob( $job );
-               } catch ( JobQueueError $e ) {
-                       if ( isset( $partitions[1] ) ) { // check fallback partition
-                               return $this->partitionQueues[$partitions[1]]->doDeduplicateRootJob( $job );
-                       }
-               }
-
-               return false;
-       }
-
-       protected function doDelete() {
-               $failed = 0;
-               /** @var JobQueue $queue */
-               foreach ( $this->partitionQueues as $queue ) {
-                       try {
-                               $queue->doDelete();
-                       } catch ( JobQueueError $e ) {
-                               ++$failed;
-                               MWExceptionHandler::logException( $e );
-                       }
-               }
-               $this->throwErrorIfAllPartitionsDown( $failed );
-               return true;
-       }
-
-       protected function doWaitForBackups() {
-               $failed = 0;
-               /** @var JobQueue $queue */
-               foreach ( $this->partitionQueues as $queue ) {
-                       try {
-                               $queue->waitForBackups();
-                       } catch ( JobQueueError $e ) {
-                               ++$failed;
-                               MWExceptionHandler::logException( $e );
-                       }
-               }
-               $this->throwErrorIfAllPartitionsDown( $failed );
-       }
-
-       protected function doGetPeriodicTasks() {
-               $tasks = array();
-               /** @var JobQueue $queue */
-               foreach ( $this->partitionQueues as $partition => $queue ) {
-                       foreach ( $queue->getPeriodicTasks() as $task => $def ) {
-                               $tasks["{$partition}:{$task}"] = $def;
-                       }
-               }
-
-               return $tasks;
-       }
-
-       protected function doFlushCaches() {
-               static $types = array(
-                       'empty',
-                       'size',
-                       'acquiredcount',
-                       'delayedcount',
-                       'abandonedcount'
-               );
-
-               foreach ( $types as $type ) {
-                       $this->cache->delete( $this->getCacheKey( $type ) );
-               }
-
-               /** @var JobQueue $queue */
-               foreach ( $this->partitionQueues as $queue ) {
-                       $queue->doFlushCaches();
-               }
-       }
-
-       public function getAllQueuedJobs() {
-               $iterator = new AppendIterator();
-
-               /** @var JobQueue $queue */
-               foreach ( $this->partitionQueues as $queue ) {
-                       $iterator->append( $queue->getAllQueuedJobs() );
-               }
-
-               return $iterator;
-       }
-
-       public function getAllDelayedJobs() {
-               $iterator = new AppendIterator();
-
-               /** @var JobQueue $queue */
-               foreach ( $this->partitionQueues as $queue ) {
-                       $iterator->append( $queue->getAllDelayedJobs() );
-               }
-
-               return $iterator;
-       }
-
-       public function getCoalesceLocationInternal() {
-               return "JobQueueFederated:wiki:{$this->wiki}" .
-                       sha1( serialize( array_keys( $this->partitionMap ) ) );
-       }
-
-       protected function doGetSiblingQueuesWithJobs( array $types ) {
-               $result = array();
-
-               $failed = 0;
-               /** @var JobQueue $queue */
-               foreach ( $this->partitionQueues as $queue ) {
-                       try {
-                               $nonEmpty = $queue->doGetSiblingQueuesWithJobs( $types );
-                               if ( is_array( $nonEmpty ) ) {
-                                       $result = array_unique( array_merge( $result, $nonEmpty ) );
-                               } else {
-                                       return null; // not supported on all partitions; bail
-                               }
-                               if ( count( $result ) == count( $types ) ) {
-                                       break; // short-circuit
-                               }
-                       } catch ( JobQueueError $e ) {
-                               ++$failed;
-                               MWExceptionHandler::logException( $e );
-                       }
-               }
-               $this->throwErrorIfAllPartitionsDown( $failed );
-
-               return array_values( $result );
-       }
-
-       protected function doGetSiblingQueueSizes( array $types ) {
-               $result = array();
-               $failed = 0;
-               /** @var JobQueue $queue */
-               foreach ( $this->partitionQueues as $queue ) {
-                       try {
-                               $sizes = $queue->doGetSiblingQueueSizes( $types );
-                               if ( is_array( $sizes ) ) {
-                                       foreach ( $sizes as $type => $size ) {
-                                               $result[$type] = isset( $result[$type] ) ? $result[$type] + $size : $size;
-                                       }
-                               } else {
-                                       return null; // not supported on all partitions; bail
-                               }
-                       } catch ( JobQueueError $e ) {
-                               ++$failed;
-                               MWExceptionHandler::logException( $e );
-                       }
-               }
-               $this->throwErrorIfAllPartitionsDown( $failed );
-
-               return $result;
-       }
-
-       /**
-        * Throw an error if no partitions available
-        *
-        * @param int $down The number of up partitions down
-        * @return void
-        * @throws JobQueueError
-        */
-       protected function throwErrorIfAllPartitionsDown( $down ) {
-               if ( $down >= count( $this->partitionQueues ) ) {
-                       throw new JobQueueError( 'No queue partitions available.' );
-               }
-       }
-
-       public function setTestingPrefix( $key ) {
-               /** @var JobQueue $queue */
-               foreach ( $this->partitionQueues as $queue ) {
-                       $queue->setTestingPrefix( $key );
-               }
-       }
-
-       /**
-        * @param $property
-        * @return string
-        */
-       private function getCacheKey( $property ) {
-               list( $db, $prefix ) = wfSplitWikiID( $this->wiki );
-
-               return wfForeignMemcKey( $db, $prefix, 'jobqueue', $this->type, $property );
-       }
-}
diff --git a/includes/job/JobQueueGroup.php b/includes/job/JobQueueGroup.php
deleted file mode 100644 (file)
index 90742ce..0000000
+++ /dev/null
@@ -1,417 +0,0 @@
-<?php
-/**
- * Job queue base code.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @author Aaron Schulz
- */
-
-/**
- * Class to handle enqueueing of background jobs
- *
- * @ingroup JobQueue
- * @since 1.21
- */
-class JobQueueGroup {
-       /** @var array */
-       protected static $instances = array();
-
-       /** @var ProcessCacheLRU */
-       protected $cache;
-
-       /** @var string Wiki ID */
-       protected $wiki;
-
-       /** @var array Map of (bucket => (queue => JobQueue, types => list of types) */
-       protected $coalescedQueues;
-
-       const TYPE_DEFAULT = 1; // integer; jobs popped by default
-       const TYPE_ANY = 2; // integer; any job
-
-       const USE_CACHE = 1; // integer; use process or persistent cache
-
-       const PROC_CACHE_TTL = 15; // integer; seconds
-
-       const CACHE_VERSION = 1; // integer; cache version
-
-       /**
-        * @param string $wiki Wiki ID
-        */
-       protected function __construct( $wiki ) {
-               $this->wiki = $wiki;
-               $this->cache = new ProcessCacheLRU( 10 );
-       }
-
-       /**
-        * @param bool|string $wiki Wiki ID
-        * @return JobQueueGroup
-        */
-       public static function singleton( $wiki = false ) {
-               $wiki = ( $wiki === false ) ? wfWikiID() : $wiki;
-               if ( !isset( self::$instances[$wiki] ) ) {
-                       self::$instances[$wiki] = new self( $wiki );
-               }
-
-               return self::$instances[$wiki];
-       }
-
-       /**
-        * Destroy the singleton instances
-        *
-        * @return void
-        */
-       public static function destroySingletons() {
-               self::$instances = array();
-       }
-
-       /**
-        * Get the job queue object for a given queue type
-        *
-        * @param string $type
-        * @return JobQueue
-        */
-       public function get( $type ) {
-               global $wgJobTypeConf;
-
-               $conf = array( 'wiki' => $this->wiki, 'type' => $type );
-               if ( isset( $wgJobTypeConf[$type] ) ) {
-                       $conf = $conf + $wgJobTypeConf[$type];
-               } else {
-                       $conf = $conf + $wgJobTypeConf['default'];
-               }
-
-               return JobQueue::factory( $conf );
-       }
-
-       /**
-        * Insert jobs into the respective queues of with the belong.
-        *
-        * This inserts the jobs into the queue specified by $wgJobTypeConf
-        * and updates the aggregate job queue information cache as needed.
-        *
-        * @param Job|array $jobs A single Job or a list of Jobs
-        * @throws MWException
-        * @return bool
-        */
-       public function push( $jobs ) {
-               $jobs = is_array( $jobs ) ? $jobs : array( $jobs );
-               if ( !count( $jobs ) ) {
-                       return true;
-               }
-
-               $jobsByType = array(); // (job type => list of jobs)
-               foreach ( $jobs as $job ) {
-                       if ( $job instanceof IJobSpecification ) {
-                               $jobsByType[$job->getType()][] = $job;
-                       } else {
-                               throw new MWException( "Attempted to push a non-Job object into a queue." );
-                       }
-               }
-
-               $ok = true;
-               foreach ( $jobsByType as $type => $jobs ) {
-                       if ( $this->get( $type )->push( $jobs ) ) {
-                               JobQueueAggregator::singleton()->notifyQueueNonEmpty( $this->wiki, $type );
-                       } else {
-                               $ok = false;
-                       }
-               }
-
-               if ( $this->cache->has( 'queues-ready', 'list' ) ) {
-                       $list = $this->cache->get( 'queues-ready', 'list' );
-                       if ( count( array_diff( array_keys( $jobsByType ), $list ) ) ) {
-                               $this->cache->clear( 'queues-ready' );
-                       }
-               }
-
-               return $ok;
-       }
-
-       /**
-        * Pop a job off one of the job queues
-        *
-        * This pops a job off a queue as specified by $wgJobTypeConf and
-        * updates the aggregate job queue information cache as needed.
-        *
-        * @param int|string $qtype JobQueueGroup::TYPE_* constant or job type string
-        * @param int $flags Bitfield of JobQueueGroup::USE_* constants
-        * @param array $blacklist List of job types to ignore
-        * @return Job|bool Returns false on failure
-        */
-       public function pop( $qtype = self::TYPE_DEFAULT, $flags = 0, array $blacklist = array() ) {
-               $job = false;
-
-               if ( is_string( $qtype ) ) { // specific job type
-                       if ( !in_array( $qtype, $blacklist ) ) {
-                               $job = $this->get( $qtype )->pop();
-                               if ( !$job ) {
-                                       JobQueueAggregator::singleton()->notifyQueueEmpty( $this->wiki, $qtype );
-                               }
-                       }
-               } else { // any job in the "default" jobs types
-                       if ( $flags & self::USE_CACHE ) {
-                               if ( !$this->cache->has( 'queues-ready', 'list', self::PROC_CACHE_TTL ) ) {
-                                       $this->cache->set( 'queues-ready', 'list', $this->getQueuesWithJobs() );
-                               }
-                               $types = $this->cache->get( 'queues-ready', 'list' );
-                       } else {
-                               $types = $this->getQueuesWithJobs();
-                       }
-
-                       if ( $qtype == self::TYPE_DEFAULT ) {
-                               $types = array_intersect( $types, $this->getDefaultQueueTypes() );
-                       }
-
-                       $types = array_diff( $types, $blacklist ); // avoid selected types
-                       shuffle( $types ); // avoid starvation
-
-                       foreach ( $types as $type ) { // for each queue...
-                               $job = $this->get( $type )->pop();
-                               if ( $job ) { // found
-                                       break;
-                               } else { // not found
-                                       JobQueueAggregator::singleton()->notifyQueueEmpty( $this->wiki, $type );
-                                       $this->cache->clear( 'queues-ready' );
-                               }
-                       }
-               }
-
-               return $job;
-       }
-
-       /**
-        * Acknowledge that a job was completed
-        *
-        * @param Job $job
-        * @return bool
-        */
-       public function ack( Job $job ) {
-               return $this->get( $job->getType() )->ack( $job );
-       }
-
-       /**
-        * Register the "root job" of a given job into the queue for de-duplication.
-        * This should only be called right *after* all the new jobs have been inserted.
-        *
-        * @param Job $job
-        * @return bool
-        */
-       public function deduplicateRootJob( Job $job ) {
-               return $this->get( $job->getType() )->deduplicateRootJob( $job );
-       }
-
-       /**
-        * Wait for any slaves or backup queue servers to catch up.
-        *
-        * This does nothing for certain queue classes.
-        *
-        * @return void
-        * @throws MWException
-        */
-       public function waitForBackups() {
-               global $wgJobTypeConf;
-
-               wfProfileIn( __METHOD__ );
-               // Try to avoid doing this more than once per queue storage medium
-               foreach ( $wgJobTypeConf as $type => $conf ) {
-                       $this->get( $type )->waitForBackups();
-               }
-               wfProfileOut( __METHOD__ );
-       }
-
-       /**
-        * Get the list of queue types
-        *
-        * @return array List of strings
-        */
-       public function getQueueTypes() {
-               return array_keys( $this->getCachedConfigVar( 'wgJobClasses' ) );
-       }
-
-       /**
-        * Get the list of default queue types
-        *
-        * @return array List of strings
-        */
-       public function getDefaultQueueTypes() {
-               global $wgJobTypesExcludedFromDefaultQueue;
-
-               return array_diff( $this->getQueueTypes(), $wgJobTypesExcludedFromDefaultQueue );
-       }
-
-       /**
-        * Get the list of job types that have non-empty queues
-        *
-        * @return array List of job types that have non-empty queues
-        */
-       public function getQueuesWithJobs() {
-               $types = array();
-               foreach ( $this->getCoalescedQueues() as $info ) {
-                       $nonEmpty = $info['queue']->getSiblingQueuesWithJobs( $this->getQueueTypes() );
-                       if ( is_array( $nonEmpty ) ) { // batching features supported
-                               $types = array_merge( $types, $nonEmpty );
-                       } else { // we have to go through the queues in the bucket one-by-one
-                               foreach ( $info['types'] as $type ) {
-                                       if ( !$this->get( $type )->isEmpty() ) {
-                                               $types[] = $type;
-                                       }
-                               }
-                       }
-               }
-
-               return $types;
-       }
-
-       /**
-        * Get the size of the queus for a list of job types
-        *
-        * @return array Map of (job type => size)
-        */
-       public function getQueueSizes() {
-               $sizeMap = array();
-               foreach ( $this->getCoalescedQueues() as $info ) {
-                       $sizes = $info['queue']->getSiblingQueueSizes( $this->getQueueTypes() );
-                       if ( is_array( $sizes ) ) { // batching features supported
-                               $sizeMap = $sizeMap + $sizes;
-                       } else { // we have to go through the queues in the bucket one-by-one
-                               foreach ( $info['types'] as $type ) {
-                                       $sizeMap[$type] = $this->get( $type )->getSize();
-                               }
-                       }
-               }
-
-               return $sizeMap;
-       }
-
-       /**
-        * @return array
-        */
-       protected function getCoalescedQueues() {
-               global $wgJobTypeConf;
-
-               if ( $this->coalescedQueues === null ) {
-                       $this->coalescedQueues = array();
-                       foreach ( $wgJobTypeConf as $type => $conf ) {
-                               $queue = JobQueue::factory(
-                                       array( 'wiki' => $this->wiki, 'type' => 'null' ) + $conf );
-                               $loc = $queue->getCoalesceLocationInternal();
-                               if ( !isset( $this->coalescedQueues[$loc] ) ) {
-                                       $this->coalescedQueues[$loc]['queue'] = $queue;
-                                       $this->coalescedQueues[$loc]['types'] = array();
-                               }
-                               if ( $type === 'default' ) {
-                                       $this->coalescedQueues[$loc]['types'] = array_merge(
-                                               $this->coalescedQueues[$loc]['types'],
-                                               array_diff( $this->getQueueTypes(), array_keys( $wgJobTypeConf ) )
-                                       );
-                               } else {
-                                       $this->coalescedQueues[$loc]['types'][] = $type;
-                               }
-                       }
-               }
-
-               return $this->coalescedQueues;
-       }
-
-       /**
-        * Execute any due periodic queue maintenance tasks for all queues.
-        *
-        * A task is "due" if the time ellapsed since the last run is greater than
-        * the defined run period. Concurrent calls to this function will cause tasks
-        * to be attempted twice, so they may need their own methods of mutual exclusion.
-        *
-        * @return int Number of tasks run
-        */
-       public function executeReadyPeriodicTasks() {
-               global $wgMemc;
-
-               list( $db, $prefix ) = wfSplitWikiID( $this->wiki );
-               $key = wfForeignMemcKey( $db, $prefix, 'jobqueuegroup', 'taskruns', 'v1' );
-               $lastRuns = $wgMemc->get( $key ); // (queue => task => UNIX timestamp)
-
-               $count = 0;
-               $tasksRun = array(); // (queue => task => UNIX timestamp)
-               foreach ( $this->getQueueTypes() as $type ) {
-                       $queue = $this->get( $type );
-                       foreach ( $queue->getPeriodicTasks() as $task => $definition ) {
-                               if ( $definition['period'] <= 0 ) {
-                                       continue; // disabled
-                               } elseif ( !isset( $lastRuns[$type][$task] )
-                                       || $lastRuns[$type][$task] < ( time() - $definition['period'] )
-                               ) {
-                                       try {
-                                               if ( call_user_func( $definition['callback'] ) !== null ) {
-                                                       $tasksRun[$type][$task] = time();
-                                                       ++$count;
-                                               }
-                                       } catch ( JobQueueError $e ) {
-                                               MWExceptionHandler::logException( $e );
-                                       }
-                               }
-                       }
-                       // The tasks may have recycled jobs or release delayed jobs into the queue
-                       if ( isset( $tasksRun[$type] ) && !$queue->isEmpty() ) {
-                               JobQueueAggregator::singleton()->notifyQueueNonEmpty( $this->wiki, $type );
-                       }
-               }
-
-               $wgMemc->merge( $key, function ( $cache, $key, $lastRuns ) use ( $tasksRun ) {
-                       if ( is_array( $lastRuns ) ) {
-                               foreach ( $tasksRun as $type => $tasks ) {
-                                       foreach ( $tasks as $task => $timestamp ) {
-                                               if ( !isset( $lastRuns[$type][$task] )
-                                                       || $timestamp > $lastRuns[$type][$task]
-                                               ) {
-                                                       $lastRuns[$type][$task] = $timestamp;
-                                               }
-                                       }
-                               }
-                       } else {
-                               $lastRuns = $tasksRun;
-                       }
-
-                       return $lastRuns;
-               } );
-
-               return $count;
-       }
-
-       /**
-        * @param $name string
-        * @return mixed
-        */
-       private function getCachedConfigVar( $name ) {
-               global $wgConf, $wgMemc;
-
-               if ( $this->wiki === wfWikiID() ) {
-                       return $GLOBALS[$name]; // common case
-               } else {
-                       list( $db, $prefix ) = wfSplitWikiID( $this->wiki );
-                       $key = wfForeignMemcKey( $db, $prefix, 'configvalue', $name );
-                       $value = $wgMemc->get( $key ); // ('v' => ...) or false
-                       if ( is_array( $value ) ) {
-                               return $value['v'];
-                       } else {
-                               $value = $wgConf->getConfig( $this->wiki, $name );
-                               $wgMemc->set( $key, array( 'v' => $value ), 86400 + mt_rand( 0, 86400 ) );
-
-                               return $value;
-                       }
-               }
-       }
-}
diff --git a/includes/job/JobQueueRedis.php b/includes/job/JobQueueRedis.php
deleted file mode 100644 (file)
index c785cb2..0000000
+++ /dev/null
@@ -1,874 +0,0 @@
-<?php
-/**
- * Redis-backed job queue code.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @author Aaron Schulz
- */
-
-/**
- * Class to handle job queues stored in Redis
- *
- * This is faster, less resource intensive, queue that JobQueueDB.
- * All data for a queue using this class is placed into one redis server.
- *
- * There are eight main redis keys used to track jobs:
- *   - l-unclaimed  : A list of job IDs used for ready unclaimed jobs
- *   - z-claimed    : A sorted set of (job ID, UNIX timestamp as score) used for job retries
- *   - z-abandoned  : A sorted set of (job ID, UNIX timestamp as score) used for broken jobs
- *   - z-delayed    : A sorted set of (job ID, UNIX timestamp as score) used for delayed jobs
- *   - h-idBySha1   : A hash of (SHA1 => job ID) for unclaimed jobs used for de-duplication
- *   - h-sha1ById   : A hash of (job ID => SHA1) for unclaimed jobs used for de-duplication
- *   - h-attempts   : A hash of (job ID => attempt count) used for job claiming/retries
- *   - h-data       : A hash of (job ID => serialized blobs) for job storage
- * A job ID can be in only one of z-delayed, l-unclaimed, z-claimed, and z-abandoned.
- * If an ID appears in any of those lists, it should have a h-data entry for its ID.
- * If a job has a SHA1 de-duplication value and its ID is in l-unclaimed or z-delayed, then
- * there should be no other such jobs with that SHA1. Every h-idBySha1 entry has an h-sha1ById
- * entry and every h-sha1ById must refer to an ID that is l-unclaimed. If a job has its
- * ID in z-claimed or z-abandoned, then it must also have an h-attempts entry for its ID.
- *
- * Additionally, "rootjob:* keys track "root jobs" used for additional de-duplication.
- * Aside from root job keys, all keys have no expiry, and are only removed when jobs are run.
- * All the keys are prefixed with the relevant wiki ID information.
- *
- * This class requires Redis 2.6 as it makes use Lua scripts for fast atomic operations.
- * Additionally, it should be noted that redis has different persistence modes, such
- * as rdb snapshots, journaling, and no persistent. Appropriate configuration should be
- * made on the servers based on what queues are using it and what tolerance they have.
- *
- * @ingroup JobQueue
- * @ingroup Redis
- * @since 1.22
- */
-class JobQueueRedis extends JobQueue {
-       /** @var RedisConnectionPool */
-       protected $redisPool;
-
-       /** @var string Server address */
-       protected $server;
-
-       /** @var string Compression method to use */
-       protected $compression;
-
-       const MAX_AGE_PRUNE = 604800; // integer; seconds a job can live once claimed (7 days)
-
-       /** @var string Key to prefix the queue keys with (used for testing) */
-       protected $key;
-
-       /**
-        * @var null|int maximum seconds between execution of periodic tasks.  Used to speed up
-        * testing but should otherwise be left unset.
-        */
-       protected $maximumPeriodicTaskSeconds;
-
-       /**
-        * @params include:
-        *   - redisConfig : An array of parameters to RedisConnectionPool::__construct().
-        *                   Note that the serializer option is ignored as "none" is always used.
-        *   - redisServer : A hostname/port combination or the absolute path of a UNIX socket.
-        *                   If a hostname is specified but no port, the standard port number
-        *                   6379 will be used. Required.
-        *   - compression : The type of compression to use; one of (none,gzip).
-        *   - maximumPeriodicTaskSeconds : Maximum seconds between check periodic tasks.  Set to
-        *                   force faster execution of periodic tasks for inegration tests that
-        *                   rely on checkDelay.  Without this the integration tests are very very
-        *                   slow.  This really shouldn't be set in production.
-        * @param array $params
-        */
-       public function __construct( array $params ) {
-               parent::__construct( $params );
-               $params['redisConfig']['serializer'] = 'none'; // make it easy to use Lua
-               $this->server = $params['redisServer'];
-               $this->compression = isset( $params['compression'] ) ? $params['compression'] : 'none';
-               $this->redisPool = RedisConnectionPool::singleton( $params['redisConfig'] );
-               $this->maximumPeriodicTaskSeconds = isset( $params['maximumPeriodicTaskSeconds'] ) ?
-                       $params['maximumPeriodicTaskSeconds'] : null;
-       }
-
-       protected function supportedOrders() {
-               return array( 'timestamp', 'fifo' );
-       }
-
-       protected function optimalOrder() {
-               return 'fifo';
-       }
-
-       protected function supportsDelayedJobs() {
-               return true;
-       }
-
-       /**
-        * @see JobQueue::doIsEmpty()
-        * @return bool
-        * @throws MWException
-        */
-       protected function doIsEmpty() {
-               return $this->doGetSize() == 0;
-       }
-
-       /**
-        * @see JobQueue::doGetSize()
-        * @return int
-        * @throws MWException
-        */
-       protected function doGetSize() {
-               $conn = $this->getConnection();
-               try {
-                       return $conn->lSize( $this->getQueueKey( 'l-unclaimed' ) );
-               } catch ( RedisException $e ) {
-                       $this->throwRedisException( $conn, $e );
-               }
-       }
-
-       /**
-        * @see JobQueue::doGetAcquiredCount()
-        * @return int
-        * @throws JobQueueError
-        */
-       protected function doGetAcquiredCount() {
-               if ( $this->claimTTL <= 0 ) {
-                       return 0; // no acknowledgements
-               }
-               $conn = $this->getConnection();
-               try {
-                       $conn->multi( Redis::PIPELINE );
-                       $conn->zSize( $this->getQueueKey( 'z-claimed' ) );
-                       $conn->zSize( $this->getQueueKey( 'z-abandoned' ) );
-
-                       return array_sum( $conn->exec() );
-               } catch ( RedisException $e ) {
-                       $this->throwRedisException( $conn, $e );
-               }
-       }
-
-       /**
-        * @see JobQueue::doGetDelayedCount()
-        * @return int
-        * @throws JobQueueError
-        */
-       protected function doGetDelayedCount() {
-               if ( !$this->checkDelay ) {
-                       return 0; // no delayed jobs
-               }
-               $conn = $this->getConnection();
-               try {
-                       return $conn->zSize( $this->getQueueKey( 'z-delayed' ) );
-               } catch ( RedisException $e ) {
-                       $this->throwRedisException( $conn, $e );
-               }
-       }
-
-       /**
-        * @see JobQueue::doGetAbandonedCount()
-        * @return int
-        * @throws JobQueueError
-        */
-       protected function doGetAbandonedCount() {
-               if ( $this->claimTTL <= 0 ) {
-                       return 0; // no acknowledgements
-               }
-               $conn = $this->getConnection();
-               try {
-                       return $conn->zSize( $this->getQueueKey( 'z-abandoned' ) );
-               } catch ( RedisException $e ) {
-                       $this->throwRedisException( $conn, $e );
-               }
-       }
-
-       /**
-        * @see JobQueue::doBatchPush()
-        * @param array $jobs
-        * @param $flags
-        * @return bool
-        * @throws JobQueueError
-        */
-       protected function doBatchPush( array $jobs, $flags ) {
-               // Convert the jobs into field maps (de-duplicated against each other)
-               $items = array(); // (job ID => job fields map)
-               foreach ( $jobs as $job ) {
-                       $item = $this->getNewJobFields( $job );
-                       if ( strlen( $item['sha1'] ) ) { // hash identifier => de-duplicate
-                               $items[$item['sha1']] = $item;
-                       } else {
-                               $items[$item['uuid']] = $item;
-                       }
-               }
-
-               if ( !count( $items ) ) {
-                       return true; // nothing to do
-               }
-
-               $conn = $this->getConnection();
-               try {
-                       // Actually push the non-duplicate jobs into the queue...
-                       if ( $flags & self::QOS_ATOMIC ) {
-                               $batches = array( $items ); // all or nothing
-                       } else {
-                               $batches = array_chunk( $items, 500 ); // avoid tying up the server
-                       }
-                       $failed = 0;
-                       $pushed = 0;
-                       foreach ( $batches as $itemBatch ) {
-                               $added = $this->pushBlobs( $conn, $itemBatch );
-                               if ( is_int( $added ) ) {
-                                       $pushed += $added;
-                               } else {
-                                       $failed += count( $itemBatch );
-                               }
-                       }
-                       if ( $failed > 0 ) {
-                               wfDebugLog( 'JobQueueRedis', "Could not insert {$failed} {$this->type} job(s)." );
-
-                               return false;
-                       }
-                       JobQueue::incrStats( 'job-insert', $this->type, count( $items ) );
-                       JobQueue::incrStats( 'job-insert-duplicate', $this->type,
-                               count( $items ) - $failed - $pushed );
-               } catch ( RedisException $e ) {
-                       $this->throwRedisException( $conn, $e );
-               }
-
-               return true;
-       }
-
-       /**
-        * @param RedisConnRef $conn
-        * @param array $items List of results from JobQueueRedis::getNewJobFields()
-        * @return int Number of jobs inserted (duplicates are ignored)
-        * @throws RedisException
-        */
-       protected function pushBlobs( RedisConnRef $conn, array $items ) {
-               $args = array(); // ([id, sha1, rtime, blob [, id, sha1, rtime, blob ... ] ] )
-               foreach ( $items as $item ) {
-                       $args[] = (string)$item['uuid'];
-                       $args[] = (string)$item['sha1'];
-                       $args[] = (string)$item['rtimestamp'];
-                       $args[] = (string)$this->serialize( $item );
-               }
-               static $script =
-<<<LUA
-               local kUnclaimed, kSha1ById, kIdBySha1, kDelayed, kData = unpack(KEYS)
-               if #ARGV % 4 ~= 0 then return redis.error_reply('Unmatched arguments') end
-               local pushed = 0
-               for i = 1,#ARGV,4 do
-                       local id,sha1,rtimestamp,blob = ARGV[i],ARGV[i+1],ARGV[i+2],ARGV[i+3]
-                       if sha1 == '' or redis.call('hExists',kIdBySha1,sha1) == 0 then
-                               if 1*rtimestamp > 0 then
-                                       -- Insert into delayed queue (release time as score)
-                                       redis.call('zAdd',kDelayed,rtimestamp,id)
-                               else
-                                       -- Insert into unclaimed queue
-                                       redis.call('lPush',kUnclaimed,id)
-                               end
-                               if sha1 ~= '' then
-                                       redis.call('hSet',kSha1ById,id,sha1)
-                                       redis.call('hSet',kIdBySha1,sha1,id)
-                               end
-                               redis.call('hSet',kData,id,blob)
-                               pushed = pushed + 1
-                       end
-               end
-               return pushed
-LUA;
-               return $conn->luaEval( $script,
-                       array_merge(
-                               array(
-                                       $this->getQueueKey( 'l-unclaimed' ), # KEYS[1]
-                                       $this->getQueueKey( 'h-sha1ById' ), # KEYS[2]
-                                       $this->getQueueKey( 'h-idBySha1' ), # KEYS[3]
-                                       $this->getQueueKey( 'z-delayed' ), # KEYS[4]
-                                       $this->getQueueKey( 'h-data' ), # KEYS[5]
-                               ),
-                               $args
-                       ),
-                       5 # number of first argument(s) that are keys
-               );
-       }
-
-       /**
-        * @see JobQueue::doPop()
-        * @return Job|bool
-        * @throws JobQueueError
-        */
-       protected function doPop() {
-               $job = false;
-
-               // Push ready delayed jobs into the queue every 10 jobs to spread the load.
-               // This is also done as a periodic task, but we don't want too much done at once.
-               if ( $this->checkDelay && mt_rand( 0, 9 ) == 0 ) {
-                       $this->recyclePruneAndUndelayJobs();
-               }
-
-               $conn = $this->getConnection();
-               try {
-                       do {
-                               if ( $this->claimTTL > 0 ) {
-                                       // Keep the claimed job list down for high-traffic queues
-                                       if ( mt_rand( 0, 99 ) == 0 ) {
-                                               $this->recyclePruneAndUndelayJobs();
-                                       }
-                                       $blob = $this->popAndAcquireBlob( $conn );
-                               } else {
-                                       $blob = $this->popAndDeleteBlob( $conn );
-                               }
-                               if ( $blob === false ) {
-                                       break; // no jobs; nothing to do
-                               }
-
-                               JobQueue::incrStats( 'job-pop', $this->type );
-                               $item = $this->unserialize( $blob );
-                               if ( $item === false ) {
-                                       wfDebugLog( 'JobQueueRedis', "Could not unserialize {$this->type} job." );
-                                       continue;
-                               }
-
-                               // If $item is invalid, recyclePruneAndUndelayJobs() will cleanup as needed
-                               $job = $this->getJobFromFields( $item ); // may be false
-                       } while ( !$job ); // job may be false if invalid
-               } catch ( RedisException $e ) {
-                       $this->throwRedisException( $conn, $e );
-               }
-
-               return $job;
-       }
-
-       /**
-        * @param RedisConnRef $conn
-        * @return array serialized string or false
-        * @throws RedisException
-        */
-       protected function popAndDeleteBlob( RedisConnRef $conn ) {
-               static $script =
-<<<LUA
-               local kUnclaimed, kSha1ById, kIdBySha1, kData = unpack(KEYS)
-               -- Pop an item off the queue
-               local id = redis.call('rpop',kUnclaimed)
-               if not id then return false end
-               -- Get the job data and remove it
-               local item = redis.call('hGet',kData,id)
-               redis.call('hDel',kData,id)
-               -- Allow new duplicates of this job
-               local sha1 = redis.call('hGet',kSha1ById,id)
-               if sha1 then redis.call('hDel',kIdBySha1,sha1) end
-               redis.call('hDel',kSha1ById,id)
-               -- Return the job data
-               return item
-LUA;
-               return $conn->luaEval( $script,
-                       array(
-                               $this->getQueueKey( 'l-unclaimed' ), # KEYS[1]
-                               $this->getQueueKey( 'h-sha1ById' ), # KEYS[2]
-                               $this->getQueueKey( 'h-idBySha1' ), # KEYS[3]
-                               $this->getQueueKey( 'h-data' ), # KEYS[4]
-                       ),
-                       4 # number of first argument(s) that are keys
-               );
-       }
-
-       /**
-        * @param RedisConnRef $conn
-        * @return array serialized string or false
-        * @throws RedisException
-        */
-       protected function popAndAcquireBlob( RedisConnRef $conn ) {
-               static $script =
-<<<LUA
-               local kUnclaimed, kSha1ById, kIdBySha1, kClaimed, kAttempts, kData = unpack(KEYS)
-               -- Pop an item off the queue
-               local id = redis.call('rPop',kUnclaimed)
-               if not id then return false end
-               -- Allow new duplicates of this job
-               local sha1 = redis.call('hGet',kSha1ById,id)
-               if sha1 then redis.call('hDel',kIdBySha1,sha1) end
-               redis.call('hDel',kSha1ById,id)
-               -- Mark the jobs as claimed and return it
-               redis.call('zAdd',kClaimed,ARGV[1],id)
-               redis.call('hIncrBy',kAttempts,id,1)
-               return redis.call('hGet',kData,id)
-LUA;
-               return $conn->luaEval( $script,
-                       array(
-                               $this->getQueueKey( 'l-unclaimed' ), # KEYS[1]
-                               $this->getQueueKey( 'h-sha1ById' ), # KEYS[2]
-                               $this->getQueueKey( 'h-idBySha1' ), # KEYS[3]
-                               $this->getQueueKey( 'z-claimed' ), # KEYS[4]
-                               $this->getQueueKey( 'h-attempts' ), # KEYS[5]
-                               $this->getQueueKey( 'h-data' ), # KEYS[6]
-                               time(), # ARGV[1] (injected to be replication-safe)
-                       ),
-                       6 # number of first argument(s) that are keys
-               );
-       }
-
-       /**
-        * @see JobQueue::doAck()
-        * @param Job $job
-        * @return Job|bool
-        * @throws MWException|JobQueueError
-        */
-       protected function doAck( Job $job ) {
-               if ( !isset( $job->metadata['uuid'] ) ) {
-                       throw new MWException( "Job of type '{$job->getType()}' has no UUID." );
-               }
-               if ( $this->claimTTL > 0 ) {
-                       $conn = $this->getConnection();
-                       try {
-                               static $script =
-<<<LUA
-                               local kClaimed, kAttempts, kData = unpack(KEYS)
-                               -- Unmark the job as claimed
-                               redis.call('zRem',kClaimed,ARGV[1])
-                               redis.call('hDel',kAttempts,ARGV[1])
-                               -- Delete the job data itself
-                               return redis.call('hDel',kData,ARGV[1])
-LUA;
-                               $res = $conn->luaEval( $script,
-                                       array(
-                                               $this->getQueueKey( 'z-claimed' ), # KEYS[1]
-                                               $this->getQueueKey( 'h-attempts' ), # KEYS[2]
-                                               $this->getQueueKey( 'h-data' ), # KEYS[3]
-                                               $job->metadata['uuid'] # ARGV[1]
-                                       ),
-                                       3 # number of first argument(s) that are keys
-                               );
-
-                               if ( !$res ) {
-                                       wfDebugLog( 'JobQueueRedis', "Could not acknowledge {$this->type} job." );
-
-                                       return false;
-                               }
-                       } catch ( RedisException $e ) {
-                               $this->throwRedisException( $conn, $e );
-                       }
-               }
-
-               return true;
-       }
-
-       /**
-        * @see JobQueue::doDeduplicateRootJob()
-        * @param Job $job
-        * @return bool
-        * @throws MWException|JobQueueError
-        */
-       protected function doDeduplicateRootJob( Job $job ) {
-               if ( !$job->hasRootJobParams() ) {
-                       throw new MWException( "Cannot register root job; missing parameters." );
-               }
-               $params = $job->getRootJobParams();
-
-               $key = $this->getRootJobCacheKey( $params['rootJobSignature'] );
-
-               $conn = $this->getConnection();
-               try {
-                       $timestamp = $conn->get( $key ); // current last timestamp of this job
-                       if ( $timestamp && $timestamp >= $params['rootJobTimestamp'] ) {
-                               return true; // a newer version of this root job was enqueued
-                       }
-
-                       // Update the timestamp of the last root job started at the location...
-                       return $conn->set( $key, $params['rootJobTimestamp'], self::ROOTJOB_TTL ); // 2 weeks
-               } catch ( RedisException $e ) {
-                       $this->throwRedisException( $conn, $e );
-               }
-       }
-
-       /**
-        * @see JobQueue::doIsRootJobOldDuplicate()
-        * @param Job $job
-        * @return bool
-        * @throws JobQueueError
-        */
-       protected function doIsRootJobOldDuplicate( Job $job ) {
-               if ( !$job->hasRootJobParams() ) {
-                       return false; // job has no de-deplication info
-               }
-               $params = $job->getRootJobParams();
-
-               $conn = $this->getConnection();
-               try {
-                       // Get the last time this root job was enqueued
-                       $timestamp = $conn->get( $this->getRootJobCacheKey( $params['rootJobSignature'] ) );
-               } catch ( RedisException $e ) {
-                       $this->throwRedisException( $conn, $e );
-               }
-
-               // Check if a new root job was started at the location after this one's...
-               return ( $timestamp && $timestamp > $params['rootJobTimestamp'] );
-       }
-
-       /**
-        * @see JobQueue::doDelete()
-        * @return bool
-        * @throws JobQueueError
-        */
-       protected function doDelete() {
-               static $props = array( 'l-unclaimed', 'z-claimed', 'z-abandoned',
-                       'z-delayed', 'h-idBySha1', 'h-sha1ById', 'h-attempts', 'h-data' );
-
-               $conn = $this->getConnection();
-               try {
-                       $keys = array();
-                       foreach ( $props as $prop ) {
-                               $keys[] = $this->getQueueKey( $prop );
-                       }
-
-                       return ( $conn->delete( $keys ) !== false );
-               } catch ( RedisException $e ) {
-                       $this->throwRedisException( $conn, $e );
-               }
-       }
-
-       /**
-        * @see JobQueue::getAllQueuedJobs()
-        * @return Iterator
-        */
-       public function getAllQueuedJobs() {
-               $conn = $this->getConnection();
-               try {
-                       $that = $this;
-
-                       return new MappedIterator(
-                               $conn->lRange( $this->getQueueKey( 'l-unclaimed' ), 0, -1 ),
-                               function ( $uid ) use ( $that, $conn ) {
-                                       return $that->getJobFromUidInternal( $uid, $conn );
-                               },
-                               array( 'accept' => function ( $job ) {
-                                       return is_object( $job );
-                               } )
-                       );
-               } catch ( RedisException $e ) {
-                       $this->throwRedisException( $conn, $e );
-               }
-       }
-
-       /**
-        * @see JobQueue::getAllQueuedJobs()
-        * @return Iterator
-        */
-       public function getAllDelayedJobs() {
-               $conn = $this->getConnection();
-               try {
-                       $that = $this;
-
-                       return new MappedIterator( // delayed jobs
-                               $conn->zRange( $this->getQueueKey( 'z-delayed' ), 0, -1 ),
-                               function ( $uid ) use ( $that, $conn ) {
-                                       return $that->getJobFromUidInternal( $uid, $conn );
-                               },
-                               array( 'accept' => function ( $job ) {
-                                       return is_object( $job );
-                               } )
-                       );
-               } catch ( RedisException $e ) {
-                       $this->throwRedisException( $conn, $e );
-               }
-       }
-
-       public function getCoalesceLocationInternal() {
-               return "RedisServer:" . $this->server;
-       }
-
-       protected function doGetSiblingQueuesWithJobs( array $types ) {
-               return array_keys( array_filter( $this->doGetSiblingQueueSizes( $types ) ) );
-       }
-
-       protected function doGetSiblingQueueSizes( array $types ) {
-               $sizes = array(); // (type => size)
-               $types = array_values( $types ); // reindex
-               $conn = $this->getConnection();
-               try {
-                       $conn->multi( Redis::PIPELINE );
-                       foreach ( $types as $type ) {
-                               $conn->lSize( $this->getQueueKey( 'l-unclaimed', $type ) );
-                       }
-                       $res = $conn->exec();
-                       if ( is_array( $res ) ) {
-                               foreach ( $res as $i => $size ) {
-                                       $sizes[$types[$i]] = $size;
-                               }
-                       }
-               } catch ( RedisException $e ) {
-                       $this->throwRedisException( $conn, $e );
-               }
-
-               return $sizes;
-       }
-
-       /**
-        * This function should not be called outside JobQueueRedis
-        *
-        * @param $uid string
-        * @param $conn RedisConnRef
-        * @return Job|bool Returns false if the job does not exist
-        * @throws MWException|JobQueueError
-        */
-       public function getJobFromUidInternal( $uid, RedisConnRef $conn ) {
-               try {
-                       $data = $conn->hGet( $this->getQueueKey( 'h-data' ), $uid );
-                       if ( $data === false ) {
-                               return false; // not found
-                       }
-                       $item = $this->unserialize( $conn->hGet( $this->getQueueKey( 'h-data' ), $uid ) );
-                       if ( !is_array( $item ) ) { // this shouldn't happen
-                               throw new MWException( "Could not find job with ID '$uid'." );
-                       }
-                       $title = Title::makeTitle( $item['namespace'], $item['title'] );
-                       $job = Job::factory( $item['type'], $title, $item['params'] );
-                       $job->metadata['uuid'] = $item['uuid'];
-
-                       return $job;
-               } catch ( RedisException $e ) {
-                       $this->throwRedisException( $conn, $e );
-               }
-       }
-
-       /**
-        * Recycle or destroy any jobs that have been claimed for too long
-        * and release any ready delayed jobs into the queue
-        *
-        * @return int Number of jobs recycled/deleted/undelayed
-        * @throws MWException|JobQueueError
-        */
-       public function recyclePruneAndUndelayJobs() {
-               $count = 0;
-               // For each job item that can be retried, we need to add it back to the
-               // main queue and remove it from the list of currenty claimed job items.
-               // For those that cannot, they are marked as dead and kept around for
-               // investigation and manual job restoration but are eventually deleted.
-               $conn = $this->getConnection();
-               try {
-                       $now = time();
-                       static $script =
-<<<LUA
-                       local kClaimed, kAttempts, kUnclaimed, kData, kAbandoned, kDelayed = unpack(KEYS)
-                       local released,abandoned,pruned,undelayed = 0,0,0,0
-                       -- Get all non-dead jobs that have an expired claim on them.
-                       -- The score for each item is the last claim timestamp (UNIX).
-                       local staleClaims = redis.call('zRangeByScore',kClaimed,0,ARGV[1])
-                       for k,id in ipairs(staleClaims) do
-                               local timestamp = redis.call('zScore',kClaimed,id)
-                               local attempts = redis.call('hGet',kAttempts,id)
-                               if attempts < ARGV[3] then
-                                       -- Claim expired and retries left: re-enqueue the job
-                                       redis.call('lPush',kUnclaimed,id)
-                                       redis.call('hIncrBy',kAttempts,id,1)
-                                       released = released + 1
-                               else
-                                       -- Claim expired and no retries left: mark the job as dead
-                                       redis.call('zAdd',kAbandoned,timestamp,id)
-                                       abandoned = abandoned + 1
-                               end
-                               redis.call('zRem',kClaimed,id)
-                       end
-                       -- Get all of the dead jobs that have been marked as dead for too long.
-                       -- The score for each item is the last claim timestamp (UNIX).
-                       local deadClaims = redis.call('zRangeByScore',kAbandoned,0,ARGV[2])
-                       for k,id in ipairs(deadClaims) do
-                               -- Stale and out of retries: remove any traces of the job
-                               redis.call('zRem',kAbandoned,id)
-                               redis.call('hDel',kAttempts,id)
-                               redis.call('hDel',kData,id)
-                               pruned = pruned + 1
-                       end
-                       -- Get the list of ready delayed jobs, sorted by readiness (UNIX timestamp)
-                       local ids = redis.call('zRangeByScore',kDelayed,0,ARGV[4])
-                       -- Migrate the jobs from the "delayed" set to the "unclaimed" list
-                       for k,id in ipairs(ids) do
-                               redis.call('lPush',kUnclaimed,id)
-                               redis.call('zRem',kDelayed,id)
-                       end
-                       undelayed = #ids
-                       return {released,abandoned,pruned,undelayed}
-LUA;
-                       $res = $conn->luaEval( $script,
-                               array(
-                                       $this->getQueueKey( 'z-claimed' ), # KEYS[1]
-                                       $this->getQueueKey( 'h-attempts' ), # KEYS[2]
-                                       $this->getQueueKey( 'l-unclaimed' ), # KEYS[3]
-                                       $this->getQueueKey( 'h-data' ), # KEYS[4]
-                                       $this->getQueueKey( 'z-abandoned' ), # KEYS[5]
-                                       $this->getQueueKey( 'z-delayed' ), # KEYS[6]
-                                       $now - $this->claimTTL, # ARGV[1]
-                                       $now - self::MAX_AGE_PRUNE, # ARGV[2]
-                                       $this->maxTries, # ARGV[3]
-                                       $now # ARGV[4]
-                               ),
-                               6 # number of first argument(s) that are keys
-                       );
-                       if ( $res ) {
-                               list( $released, $abandoned, $pruned, $undelayed ) = $res;
-                               $count += $released + $pruned + $undelayed;
-                               JobQueue::incrStats( 'job-recycle', $this->type, $released );
-                               JobQueue::incrStats( 'job-abandon', $this->type, $abandoned );
-                       }
-               } catch ( RedisException $e ) {
-                       $this->throwRedisException( $conn, $e );
-               }
-
-               return $count;
-       }
-
-       /**
-        * @return array
-        */
-       protected function doGetPeriodicTasks() {
-               $periods = array( 3600 ); // standard cleanup (useful on config change)
-               if ( $this->claimTTL > 0 ) {
-                       $periods[] = ceil( $this->claimTTL / 2 ); // avoid bad timing
-               }
-               if ( $this->checkDelay ) {
-                       $periods[] = 300; // 5 minutes
-               }
-               $period = min( $periods );
-               $period = max( $period, 30 ); // sanity
-               // Support override for faster testing
-               if ( $this->maximumPeriodicTaskSeconds !== null ) {
-                       $period = min( $period, $this->maximumPeriodicTaskSeconds );
-               }
-               return array(
-                       'recyclePruneAndUndelayJobs' => array(
-                               'callback' => array( $this, 'recyclePruneAndUndelayJobs' ),
-                               'period'   => $period,
-                       )
-               );
-       }
-
-       /**
-        * @param IJobSpecification $job
-        * @return array
-        */
-       protected function getNewJobFields( IJobSpecification $job ) {
-               return array(
-                       // Fields that describe the nature of the job
-                       'type' => $job->getType(),
-                       'namespace' => $job->getTitle()->getNamespace(),
-                       'title' => $job->getTitle()->getDBkey(),
-                       'params' => $job->getParams(),
-                       // Some jobs cannot run until a "release timestamp"
-                       'rtimestamp' => $job->getReleaseTimestamp() ?: 0,
-                       // Additional job metadata
-                       'uuid' => UIDGenerator::newRawUUIDv4( UIDGenerator::QUICK_RAND ),
-                       'sha1' => $job->ignoreDuplicates()
-                               ? wfBaseConvert( sha1( serialize( $job->getDeduplicationInfo() ) ), 16, 36, 31 )
-                               : '',
-                       'timestamp' => time() // UNIX timestamp
-               );
-       }
-
-       /**
-        * @param $fields array
-        * @return Job|bool
-        */
-       protected function getJobFromFields( array $fields ) {
-               $title = Title::makeTitleSafe( $fields['namespace'], $fields['title'] );
-               if ( $title ) {
-                       $job = Job::factory( $fields['type'], $title, $fields['params'] );
-                       $job->metadata['uuid'] = $fields['uuid'];
-
-                       return $job;
-               }
-
-               return false;
-       }
-
-       /**
-        * @param array $fields
-        * @return string Serialized and possibly compressed version of $fields
-        */
-       protected function serialize( array $fields ) {
-               $blob = serialize( $fields );
-               if ( $this->compression === 'gzip'
-                       && strlen( $blob ) >= 1024
-                       && function_exists( 'gzdeflate' )
-               ) {
-                       $object = (object)array( 'blob' => gzdeflate( $blob ), 'enc' => 'gzip' );
-                       $blobz = serialize( $object );
-
-                       return ( strlen( $blobz ) < strlen( $blob ) ) ? $blobz : $blob;
-               } else {
-                       return $blob;
-               }
-       }
-
-       /**
-        * @param string $blob
-        * @return array|bool Unserialized version of $blob or false
-        */
-       protected function unserialize( $blob ) {
-               $fields = unserialize( $blob );
-               if ( is_object( $fields ) ) {
-                       if ( $fields->enc === 'gzip' && function_exists( 'gzinflate' ) ) {
-                               $fields = unserialize( gzinflate( $fields->blob ) );
-                       } else {
-                               $fields = false;
-                       }
-               }
-
-               return is_array( $fields ) ? $fields : false;
-       }
-
-       /**
-        * Get a connection to the server that handles all sub-queues for this queue
-        *
-        * @return RedisConnRef
-        * @throws JobQueueConnectionError
-        */
-       protected function getConnection() {
-               $conn = $this->redisPool->getConnection( $this->server );
-               if ( !$conn ) {
-                       throw new JobQueueConnectionError( "Unable to connect to redis server." );
-               }
-
-               return $conn;
-       }
-
-       /**
-        * @param $conn RedisConnRef
-        * @param $e RedisException
-        * @throws JobQueueError
-        */
-       protected function throwRedisException( RedisConnRef $conn, $e ) {
-               $this->redisPool->handleError( $conn, $e );
-               throw new JobQueueError( "Redis server error: {$e->getMessage()}\n" );
-       }
-
-       /**
-        * @param $prop string
-        * @param $type string|null
-        * @return string
-        */
-       private function getQueueKey( $prop, $type = null ) {
-               $type = is_string( $type ) ? $type : $this->type;
-               list( $db, $prefix ) = wfSplitWikiID( $this->wiki );
-               if ( strlen( $this->key ) ) { // namespaced queue (for testing)
-                       return wfForeignMemcKey( $db, $prefix, 'jobqueue', $type, $this->key, $prop );
-               } else {
-                       return wfForeignMemcKey( $db, $prefix, 'jobqueue', $type, $prop );
-               }
-       }
-
-       /**
-        * @param $key string
-        * @return void
-        */
-       public function setTestingPrefix( $key ) {
-               $this->key = $key;
-       }
-}
diff --git a/includes/job/JobSpecification.php b/includes/job/JobSpecification.php
deleted file mode 100644 (file)
index e074e5c..0000000
+++ /dev/null
@@ -1,189 +0,0 @@
-<?php
-/**
- * Job queue task description base code.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @ingroup JobQueue
- */
-
-/**
- * Job queue task description interface
- *
- * @ingroup JobQueue
- * @since 1.23
- */
-interface IJobSpecification {
-       /**
-        * @return string Job type
-        */
-       public function getType();
-
-       /**
-        * @return array
-        */
-       public function getParams();
-
-       /**
-        * @return int|null UNIX timestamp to delay running this job until, otherwise null
-        */
-       public function getReleaseTimestamp();
-
-       /**
-        * @return bool Whether only one of each identical set of jobs should be run
-        */
-       public function ignoreDuplicates();
-
-       /**
-        * Subclasses may need to override this to make duplication detection work.
-        * The resulting map conveys everything that makes the job unique. This is
-        * only checked if ignoreDuplicates() returns true, meaning that duplicate
-        * jobs are supposed to be ignored.
-        *
-        * @return array Map of key/values
-        */
-       public function getDeduplicationInfo();
-
-       /**
-        * @return Title Descriptive title (this can simply be informative)
-        */
-       public function getTitle();
-}
-
-/**
- * Job queue task description base code
- *
- * Example usage:
- * <code>
- * $job = new JobSpecification(
- *             'null',
- *             array( 'lives' => 1, 'usleep' => 100, 'pi' => 3.141569 ),
- *             array( 'removeDuplicates' => 1 ),
- *             Title::makeTitle( NS_SPECIAL, 'nullity' )
- * );
- * JobQueueGroup::singleton()->push( $job )
- * </code>
- *
- * @ingroup JobQueue
- * @since 1.23
- */
-class JobSpecification implements IJobSpecification {
-       /** @var string */
-       protected $type;
-
-       /** @var array Array of job parameters or false if none */
-       protected $params;
-
-       /** @var Title */
-       protected $title;
-
-       /** @var bool Expensive jobs may set this to true */
-       protected $ignoreDuplicates;
-
-       /**
-        * @param string $type
-        * @param array $params Map of key/values
-        * @param array $opts Map of key/values
-        * @param Title $title Optional descriptive title
-        */
-       public function __construct(
-               $type, array $params, array $opts = array(), Title $title = null
-       ) {
-               $this->validateParams( $params );
-
-               $this->type = $type;
-               $this->params = $params;
-               $this->title = $title ?: Title::newMainPage();
-               $this->ignoreDuplicates = !empty( $opts['removeDuplicates'] );
-       }
-
-       /**
-        * @param array $params
-        */
-       protected function validateParams( array $params ) {
-               foreach ( $params as $p => $v ) {
-                       if ( is_array( $v ) ) {
-                               $this->validateParams( $v );
-                       } elseif ( !is_scalar( $v ) && $v !== null ) {
-                               throw new UnexpectedValueException( 'Job parameters are not JSON serializable.' );
-                       }
-               }
-       }
-
-       /**
-        * @return string
-        */
-       public function getType() {
-               return $this->type;
-       }
-
-       /**
-        * @return Title
-        */
-       public function getTitle() {
-               return $this->title;
-       }
-
-       /**
-        * @return array
-        */
-       public function getParams() {
-               return $this->params;
-       }
-
-       /**
-        * @return int|null UNIX timestamp to delay running this job until, otherwise null
-        */
-       public function getReleaseTimestamp() {
-               return isset( $this->params['jobReleaseTimestamp'] )
-                       ? wfTimestampOrNull( TS_UNIX, $this->params['jobReleaseTimestamp'] )
-                       : null;
-       }
-
-       /**
-        * @return bool Whether only one of each identical set of jobs should be run
-        */
-       public function ignoreDuplicates() {
-               return $this->ignoreDuplicates;
-       }
-
-       /**
-        * Subclasses may need to override this to make duplication detection work.
-        * The resulting map conveys everything that makes the job unique. This is
-        * only checked if ignoreDuplicates() returns true, meaning that duplicate
-        * jobs are supposed to be ignored.
-        *
-        * @return array Map of key/values
-        */
-       public function getDeduplicationInfo() {
-               $info = array(
-                       'type' => $this->getType(),
-                       'namespace' => $this->getTitle()->getNamespace(),
-                       'title' => $this->getTitle()->getDBkey(),
-                       'params' => $this->getParams()
-               );
-               if ( is_array( $info['params'] ) ) {
-                       // Identical jobs with different "root" jobs should count as duplicates
-                       unset( $info['params']['rootJobSignature'] );
-                       unset( $info['params']['rootJobTimestamp'] );
-                       // Likewise for jobs with different delay times
-                       unset( $info['params']['jobReleaseTimestamp'] );
-               }
-
-               return $info;
-       }
-}
diff --git a/includes/job/README b/includes/job/README
deleted file mode 100644 (file)
index c11d5a7..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-/*!
-\ingroup JobQueue
-\page jobqueue_design Job queue design
-
-Notes on the Job queuing system architecture.
-
-\section intro Introduction
-
-The data model consist of the following main components:
-* The Job object represents a particular deferred task that happens in the
-  background. All jobs subclass the Job object and put the main logic in the
-  function called run().
-* The JobQueue object represents a particular queue of jobs of a certain type.
-  For example there may be a queue for email jobs and a queue for squid purge
-  jobs.
-
-\section jobqueue Job queues
-
-Each job type has its own queue and is associated to a storage medium. One
-queue might save its jobs in redis while another one uses would use a database.
-
-Storage medium are defined in a queue class. Before using it, you must
-define in $wgJobTypeConf a mapping of the job type to a queue class.
-
-The factory class JobQueueGroup provides helper functions:
-- getting the queue for a given job
-- route new job insertions to the proper queue
-
-The following queue classes are available:
-* JobQueueDB (stores jobs in the `job` table in a database)
-* JobQueueRedis (stores jobs in a redis server)
-
-All queue classes support some basic operations (though some may be no-ops):
-* enqueueing a batch of jobs
-* dequeueing a single job
-* acknowledging a job is completed
-* checking if the queue is empty
-
-Some queue classes (like JobQueueDB) may dequeue jobs in random order while other
-queues might dequeue jobs in exact FIFO order. Callers should thus not assume jobs
-are executed in FIFO order.
-
-Also note that not all queue classes will have the same reliability guarantees.
-In-memory queues may lose data when restarted depending on snapshot and journal
-settings (including journal fsync() frequency).  Some queue types may totally remove
-jobs when dequeued while leaving the ack() function as a no-op; if a job is
-dequeued by a job runner, which crashes before completion, the job will be
-lost. Some jobs, like purging squid caches after a template change, may not
-require durable queues, whereas other jobs might be more important.
-
-\section aggregator Job queue aggregator
-
-The aggregators are used by nextJobDB.php, which is a script that will return a
-random ready queue (on any wiki in the farm) that can be used with runJobs.php.
-This can be used in conjunction with any scripts that handle wiki farm job queues.
-Note that $wgLocalDatabases defines what wikis are in the wiki farm.
-
-Since each job type has its own queue, and wiki-farms may have many wikis,
-there might be a large number of queues to keep track of. To avoid wasting
-large amounts of time polling empty queues, aggregators exists to keep track
-of which queues are ready.
-
-The following queue aggregator classes are available:
-* JobQueueAggregatorMemc (uses $wgMemc to track ready queues)
-* JobQueueAggregatorRedis (uses a redis server to track ready queues)
-
-Some aggregators cache data for a few minutes while others may be always up to date.
-This can be an important factor for jobs that need a low pickup time (or latency).
-
-\section jobs Jobs
-
-Callers should also try to make jobs maintain correctness when executed twice.
-This is useful for queues that actually implement ack(), since they may recycle
-dequeued but un-acknowledged jobs back into the queue to be attempted again. If
-a runner dequeues a job, runs it, but then crashes before calling ack(), the
-job may be returned to the queue and run a second time. Jobs like cache purging can
-happen several times without any correctness problems. However, a pathological case
-would be if a bug causes the problem to systematically keep repeating. For example,
-a job may always throw a DB error at the end of run(). This problem is trickier to
-solve and more obnoxious for things like email jobs, for example. For such jobs,
-it might be useful to use a queue that does not retry jobs.
diff --git a/includes/job/aggregator/JobQueueAggregator.php b/includes/job/aggregator/JobQueueAggregator.php
deleted file mode 100644 (file)
index 8600eed..0000000
+++ /dev/null
@@ -1,162 +0,0 @@
-<?php
-/**
- * Job queue aggregator code.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @author Aaron Schulz
- */
-
-/**
- * Class to handle tracking information about all queues
- *
- * @ingroup JobQueue
- * @since 1.21
- */
-abstract class JobQueueAggregator {
-       /** @var JobQueueAggregator */
-       protected static $instance = null;
-
-       /**
-        * @param array $params
-        */
-       protected function __construct( array $params ) {
-       }
-
-       /**
-        * @throws MWException
-        * @return JobQueueAggregator
-        */
-       final public static function singleton() {
-               global $wgJobQueueAggregator;
-
-               if ( !isset( self::$instance ) ) {
-                       $class = $wgJobQueueAggregator['class'];
-                       $obj = new $class( $wgJobQueueAggregator );
-                       if ( !( $obj instanceof JobQueueAggregator ) ) {
-                               throw new MWException( "Class '$class' is not a JobQueueAggregator class." );
-                       }
-                       self::$instance = $obj;
-               }
-
-               return self::$instance;
-       }
-
-       /**
-        * Destroy the singleton instance
-        *
-        * @return void
-        */
-       final public static function destroySingleton() {
-               self::$instance = null;
-       }
-
-       /**
-        * Mark a queue as being empty
-        *
-        * @param string $wiki
-        * @param string $type
-        * @return bool Success
-        */
-       final public function notifyQueueEmpty( $wiki, $type ) {
-               wfProfileIn( __METHOD__ );
-               $ok = $this->doNotifyQueueEmpty( $wiki, $type );
-               wfProfileOut( __METHOD__ );
-
-               return $ok;
-       }
-
-       /**
-        * @see JobQueueAggregator::notifyQueueEmpty()
-        */
-       abstract protected function doNotifyQueueEmpty( $wiki, $type );
-
-       /**
-        * Mark a queue as being non-empty
-        *
-        * @param string $wiki
-        * @param string $type
-        * @return bool Success
-        */
-       final public function notifyQueueNonEmpty( $wiki, $type ) {
-               wfProfileIn( __METHOD__ );
-               $ok = $this->doNotifyQueueNonEmpty( $wiki, $type );
-               wfProfileOut( __METHOD__ );
-
-               return $ok;
-       }
-
-       /**
-        * @see JobQueueAggregator::notifyQueueNonEmpty()
-        */
-       abstract protected function doNotifyQueueNonEmpty( $wiki, $type );
-
-       /**
-        * Get the list of all of the queues with jobs
-        *
-        * @return array (job type => (list of wiki IDs))
-        */
-       final public function getAllReadyWikiQueues() {
-               wfProfileIn( __METHOD__ );
-               $res = $this->doGetAllReadyWikiQueues();
-               wfProfileOut( __METHOD__ );
-
-               return $res;
-       }
-
-       /**
-        * @see JobQueueAggregator::getAllReadyWikiQueues()
-        */
-       abstract protected function doGetAllReadyWikiQueues();
-
-       /**
-        * Purge all of the aggregator information
-        *
-        * @return bool Success
-        */
-       final public function purge() {
-               wfProfileIn( __METHOD__ );
-               $res = $this->doPurge();
-               wfProfileOut( __METHOD__ );
-
-               return $res;
-       }
-
-       /**
-        * @see JobQueueAggregator::purge()
-        */
-       abstract protected function doPurge();
-
-       /**
-        * Get all databases that have a pending job.
-        * This poll all the queues and is this expensive.
-        *
-        * @return array (job type => (list of wiki IDs))
-        */
-       protected function findPendingWikiQueues() {
-               global $wgLocalDatabases;
-
-               $pendingDBs = array(); // (job type => (db list))
-               foreach ( $wgLocalDatabases as $db ) {
-                       foreach ( JobQueueGroup::singleton( $db )->getQueuesWithJobs() as $type ) {
-                               $pendingDBs[$type][] = $db;
-                       }
-               }
-
-               return $pendingDBs;
-       }
-}
diff --git a/includes/job/aggregator/JobQueueAggregatorMemc.php b/includes/job/aggregator/JobQueueAggregatorMemc.php
deleted file mode 100644 (file)
index d733a42..0000000
+++ /dev/null
@@ -1,126 +0,0 @@
-<?php
-/**
- * Job queue aggregator code that uses BagOStuff.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @author Aaron Schulz
- */
-
-/**
- * Class to handle tracking information about all queues using BagOStuff
- *
- * @ingroup JobQueue
- * @since 1.21
- */
-class JobQueueAggregatorMemc extends JobQueueAggregator {
-       /** @var BagOStuff */
-       protected $cache;
-
-       protected $cacheTTL; // integer; seconds
-
-       /**
-        * @params include:
-        *   - objectCache : Name of an object cache registered in $wgObjectCaches.
-        *                   This defaults to the one specified by $wgMainCacheType.
-        *   - cacheTTL    : Seconds to cache the aggregate data before regenerating.
-        * @param array $params
-        */
-       protected function __construct( array $params ) {
-               parent::__construct( $params );
-               $this->cache = isset( $params['objectCache'] )
-                       ? wfGetCache( $params['objectCache'] )
-                       : wfGetMainCache();
-               $this->cacheTTL = isset( $params['cacheTTL'] ) ? $params['cacheTTL'] : 180; // 3 min
-       }
-
-       /**
-        * @see JobQueueAggregator::doNotifyQueueEmpty()
-        */
-       protected function doNotifyQueueEmpty( $wiki, $type ) {
-               $key = $this->getReadyQueueCacheKey();
-               // Delist the queue from the "ready queue" list
-               if ( $this->cache->add( "$key:lock", 1, 60 ) ) { // lock
-                       $curInfo = $this->cache->get( $key );
-                       if ( is_array( $curInfo ) && isset( $curInfo['pendingDBs'][$type] ) ) {
-                               if ( in_array( $wiki, $curInfo['pendingDBs'][$type] ) ) {
-                                       $curInfo['pendingDBs'][$type] = array_diff(
-                                               $curInfo['pendingDBs'][$type], array( $wiki ) );
-                                       $this->cache->set( $key, $curInfo );
-                               }
-                       }
-                       $this->cache->delete( "$key:lock" ); // unlock
-               }
-
-               return true;
-       }
-
-       /**
-        * @see JobQueueAggregator::doNotifyQueueNonEmpty()
-        */
-       protected function doNotifyQueueNonEmpty( $wiki, $type ) {
-               return true; // updated periodically
-       }
-
-       /**
-        * @see JobQueueAggregator::doAllGetReadyWikiQueues()
-        */
-       protected function doGetAllReadyWikiQueues() {
-               $key = $this->getReadyQueueCacheKey();
-               // If the cache entry wasn't present, is stale, or in .1% of cases otherwise,
-               // regenerate the cache. Use any available stale cache if another process is
-               // currently regenerating the pending DB information.
-               $pendingDbInfo = $this->cache->get( $key );
-               if ( !is_array( $pendingDbInfo )
-                       || ( time() - $pendingDbInfo['timestamp'] ) > $this->cacheTTL
-                       || mt_rand( 0, 999 ) == 0
-               ) {
-                       if ( $this->cache->add( "$key:rebuild", 1, 1800 ) ) { // lock
-                               $pendingDbInfo = array(
-                                       'pendingDBs' => $this->findPendingWikiQueues(),
-                                       'timestamp' => time()
-                               );
-                               for ( $attempts = 1; $attempts <= 25; ++$attempts ) {
-                                       if ( $this->cache->add( "$key:lock", 1, 60 ) ) { // lock
-                                               $this->cache->set( $key, $pendingDbInfo );
-                                               $this->cache->delete( "$key:lock" ); // unlock
-                                               break;
-                                       }
-                               }
-                               $this->cache->delete( "$key:rebuild" ); // unlock
-                       }
-               }
-
-               return is_array( $pendingDbInfo )
-                       ? $pendingDbInfo['pendingDBs']
-                       : array(); // cache is both empty and locked
-       }
-
-       /**
-        * @see JobQueueAggregator::doPurge()
-        */
-       protected function doPurge() {
-               return $this->cache->delete( $this->getReadyQueueCacheKey() );
-       }
-
-       /**
-        * @return string
-        */
-       private function getReadyQueueCacheKey() {
-               return "jobqueue:aggregator:ready-queues:v1"; // global
-       }
-}
diff --git a/includes/job/aggregator/JobQueueAggregatorRedis.php b/includes/job/aggregator/JobQueueAggregatorRedis.php
deleted file mode 100644 (file)
index 2aec3c9..0000000
+++ /dev/null
@@ -1,206 +0,0 @@
-<?php
-/**
- * Job queue aggregator code that uses PhpRedis.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @author Aaron Schulz
- */
-
-/**
- * Class to handle tracking information about all queues using PhpRedis
- *
- * @ingroup JobQueue
- * @ingroup Redis
- * @since 1.21
- */
-class JobQueueAggregatorRedis extends JobQueueAggregator {
-       /** @var RedisConnectionPool */
-       protected $redisPool;
-
-       /** @var array List of Redis server addresses */
-       protected $servers;
-
-       /**
-        * @params include:
-        *   - redisConfig  : An array of parameters to RedisConnectionPool::__construct().
-        *   - redisServers : Array of server entries, the first being the primary and the
-        *                    others being fallback servers. Each entry is either a hostname/port
-        *                    combination or the absolute path of a UNIX socket.
-        *                    If a hostname is specified but no port, the standard port number
-        *                    6379 will be used. Required.
-        * @param array $params
-        */
-       protected function __construct( array $params ) {
-               parent::__construct( $params );
-               $this->servers = isset( $params['redisServers'] )
-                       ? $params['redisServers']
-                       : array( $params['redisServer'] ); // b/c
-               $this->redisPool = RedisConnectionPool::singleton( $params['redisConfig'] );
-       }
-
-       protected function doNotifyQueueEmpty( $wiki, $type ) {
-               $conn = $this->getConnection();
-               if ( !$conn ) {
-                       return false;
-               }
-               try {
-                       $conn->hDel( $this->getReadyQueueKey(), $this->encQueueName( $type, $wiki ) );
-
-                       return true;
-               } catch ( RedisException $e ) {
-                       $this->handleException( $conn, $e );
-
-                       return false;
-               }
-       }
-
-       protected function doNotifyQueueNonEmpty( $wiki, $type ) {
-               $conn = $this->getConnection();
-               if ( !$conn ) {
-                       return false;
-               }
-               try {
-                       $conn->hSet( $this->getReadyQueueKey(), $this->encQueueName( $type, $wiki ), time() );
-
-                       return true;
-               } catch ( RedisException $e ) {
-                       $this->handleException( $conn, $e );
-
-                       return false;
-               }
-       }
-
-       protected function doGetAllReadyWikiQueues() {
-               $conn = $this->getConnection();
-               if ( !$conn ) {
-                       return array();
-               }
-               try {
-                       $conn->multi( Redis::PIPELINE );
-                       $conn->exists( $this->getReadyQueueKey() );
-                       $conn->hGetAll( $this->getReadyQueueKey() );
-                       list( $exists, $map ) = $conn->exec();
-
-                       if ( $exists ) { // cache hit
-                               $pendingDBs = array(); // (type => list of wikis)
-                               foreach ( $map as $key => $time ) {
-                                       list( $type, $wiki ) = $this->dencQueueName( $key );
-                                       $pendingDBs[$type][] = $wiki;
-                               }
-                       } else { // cache miss
-                               // Avoid duplicated effort
-                               $rand = wfRandomString( 32 );
-                               $conn->multi( Redis::MULTI );
-                               $conn->setex( "{$rand}:lock", 3600, 1 );
-                               $conn->renamenx( "{$rand}:lock", $this->getReadyQueueKey() . ":lock" );
-                               if ( $conn->exec() !== array( true, true ) ) { // lock
-                                       $conn->delete( "{$rand}:lock" );
-                                       return array(); // already in progress
-                               }
-
-                               $pendingDBs = $this->findPendingWikiQueues(); // (type => list of wikis)
-
-                               $conn->delete( $this->getReadyQueueKey() . ":lock" ); // unlock
-
-                               $now = time();
-                               $map = array();
-                               foreach ( $pendingDBs as $type => $wikis ) {
-                                       foreach ( $wikis as $wiki ) {
-                                               $map[$this->encQueueName( $type, $wiki )] = $now;
-                                       }
-                               }
-                               $conn->hMSet( $this->getReadyQueueKey(), $map );
-                       }
-
-                       return $pendingDBs;
-               } catch ( RedisException $e ) {
-                       $this->handleException( $conn, $e );
-
-                       return array();
-               }
-       }
-
-       protected function doPurge() {
-               $conn = $this->getConnection();
-               if ( !$conn ) {
-                       return false;
-               }
-               try {
-                       $conn->delete( $this->getReadyQueueKey() );
-               } catch ( RedisException $e ) {
-                       $this->handleException( $conn, $e );
-
-                       return false;
-               }
-
-               return true;
-       }
-
-       /**
-        * Get a connection to the server that handles all sub-queues for this queue
-        *
-        * @return RedisConnRef|bool Returns false on failure
-        * @throws MWException
-        */
-       protected function getConnection() {
-               $conn = false;
-               foreach ( $this->servers as $server ) {
-                       $conn = $this->redisPool->getConnection( $server );
-                       if ( $conn ) {
-                               break;
-                       }
-               }
-
-               return $conn;
-       }
-
-       /**
-        * @param RedisConnRef $conn
-        * @param RedisException $e
-        * @return void
-        */
-       protected function handleException( RedisConnRef $conn, $e ) {
-               $this->redisPool->handleError( $conn, $e );
-       }
-
-       /**
-        * @return string
-        */
-       private function getReadyQueueKey() {
-               return "jobqueue:aggregator:h-ready-queues:v1"; // global
-       }
-
-       /**
-        * @param string $type
-        * @param string $wiki
-        * @return string
-        */
-       private function encQueueName( $type, $wiki ) {
-               return rawurlencode( $type ) . '/' . rawurlencode( $wiki );
-       }
-
-       /**
-        * @param string $name
-        * @return string
-        */
-       private function dencQueueName( $name ) {
-               list( $type, $wiki ) = explode( '/', $name, 2 );
-
-               return array( rawurldecode( $type ), rawurldecode( $wiki ) );
-       }
-}
diff --git a/includes/job/jobs/AssembleUploadChunksJob.php b/includes/job/jobs/AssembleUploadChunksJob.php
deleted file mode 100644 (file)
index 19b0558..0000000
+++ /dev/null
@@ -1,134 +0,0 @@
-<?php
-/**
- * Assemble the segments of a chunked upload.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @ingroup Upload
- */
-
-/**
- * Assemble the segments of a chunked upload.
- *
- * @ingroup Upload
- */
-class AssembleUploadChunksJob extends Job {
-       public function __construct( $title, $params ) {
-               parent::__construct( 'AssembleUploadChunks', $title, $params );
-               $this->removeDuplicates = true;
-       }
-
-       public function run() {
-               $scope = RequestContext::importScopedSession( $this->params['session'] );
-               $context = RequestContext::getMain();
-               try {
-                       $user = $context->getUser();
-                       if ( !$user->isLoggedIn() ) {
-                               $this->setLastError( "Could not load the author user from session." );
-
-                               return false;
-                       }
-
-                       if ( count( $_SESSION ) === 0 ) {
-                               // Empty session probably indicates that we didn't associate
-                               // with the session correctly. Note that being able to load
-                               // the user does not necessarily mean the session was loaded.
-                               // Most likely cause by suhosin.session.encrypt = On.
-                               $this->setLastError( "Error associating with user session. " .
-                                       "Try setting suhosin.session.encrypt = Off" );
-
-                               return false;
-                       }
-
-                       UploadBase::setSessionStatus(
-                               $this->params['filekey'],
-                               array( 'result' => 'Poll', 'stage' => 'assembling', 'status' => Status::newGood() )
-                       );
-
-                       $upload = new UploadFromChunks( $user );
-                       $upload->continueChunks(
-                               $this->params['filename'],
-                               $this->params['filekey'],
-                               $context->getRequest()
-                       );
-
-                       // Combine all of the chunks into a local file and upload that to a new stash file
-                       $status = $upload->concatenateChunks();
-                       if ( !$status->isGood() ) {
-                               UploadBase::setSessionStatus(
-                                       $this->params['filekey'],
-                                       array( 'result' => 'Failure', 'stage' => 'assembling', 'status' => $status )
-                               );
-                               $this->setLastError( $status->getWikiText() );
-
-                               return false;
-                       }
-
-                       // We have a new filekey for the fully concatenated file
-                       $newFileKey = $upload->getLocalFile()->getFileKey();
-
-                       // Remove the old stash file row and first chunk file
-                       $upload->stash->removeFileNoAuth( $this->params['filekey'] );
-
-                       // Build the image info array while we have the local reference handy
-                       $apiMain = new ApiMain(); // dummy object (XXX)
-                       $imageInfo = $upload->getImageInfo( $apiMain->getResult() );
-
-                       // Cleanup any temporary local file
-                       $upload->cleanupTempFile();
-
-                       // Cache the info so the user doesn't have to wait forever to get the final info
-                       UploadBase::setSessionStatus(
-                               $this->params['filekey'],
-                               array(
-                                       'result' => 'Success',
-                                       'stage' => 'assembling',
-                                       'filekey' => $newFileKey,
-                                       'imageinfo' => $imageInfo,
-                                       'status' => Status::newGood()
-                               )
-                       );
-               } catch ( MWException $e ) {
-                       UploadBase::setSessionStatus(
-                               $this->params['filekey'],
-                               array(
-                                       'result' => 'Failure',
-                                       'stage' => 'assembling',
-                                       'status' => Status::newFatal( 'api-error-stashfailed' )
-                               )
-                       );
-                       $this->setLastError( get_class( $e ) . ": " . $e->getText() );
-
-                       return false;
-               }
-
-               return true;
-       }
-
-       public function getDeduplicationInfo() {
-               $info = parent::getDeduplicationInfo();
-               if ( is_array( $info['params'] ) ) {
-                       $info['params'] = array( 'filekey' => $info['params']['filekey'] );
-               }
-
-               return $info;
-       }
-
-       public function allowRetries() {
-               return false;
-       }
-}
diff --git a/includes/job/jobs/DoubleRedirectJob.php b/includes/job/jobs/DoubleRedirectJob.php
deleted file mode 100644 (file)
index 94b56ef..0000000
+++ /dev/null
@@ -1,251 +0,0 @@
-<?php
-/**
- * Job to fix double redirects after moving a page.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @ingroup JobQueue
- */
-
-/**
- * Job to fix double redirects after moving a page
- *
- * @ingroup JobQueue
- */
-class DoubleRedirectJob extends Job {
-       /** @var string Reason for the change, 'maintenance' or 'move'. Suffix fo
-        *    message key 'double-redirect-fixed-'.
-        */
-       private $reason;
-
-       /** @var Title The title which has changed, redirects pointing to this
-        *    title are fixed
-        */
-       private $redirTitle;
-
-       /** @var User */
-       private static $user;
-
-       /**
-        * Insert jobs into the job queue to fix redirects to the given title
-        * @param string $reason the reason for the fix, see message
-        *   "double-redirect-fixed-<reason>"
-        * @param $redirTitle Title: the title which has changed, redirects
-        *   pointing to this title are fixed
-        * @param bool $destTitle Not used
-        */
-       public static function fixRedirects( $reason, $redirTitle, $destTitle = false ) {
-               # Need to use the master to get the redirect table updated in the same transaction
-               $dbw = wfGetDB( DB_MASTER );
-               $res = $dbw->select(
-                       array( 'redirect', 'page' ),
-                       array( 'page_namespace', 'page_title' ),
-                       array(
-                               'page_id = rd_from',
-                               'rd_namespace' => $redirTitle->getNamespace(),
-                               'rd_title' => $redirTitle->getDBkey()
-                       ), __METHOD__ );
-               if ( !$res->numRows() ) {
-                       return;
-               }
-               $jobs = array();
-               foreach ( $res as $row ) {
-                       $title = Title::makeTitle( $row->page_namespace, $row->page_title );
-                       if ( !$title ) {
-                               continue;
-                       }
-
-                       $jobs[] = new self( $title, array(
-                               'reason' => $reason,
-                               'redirTitle' => $redirTitle->getPrefixedDBkey() ) );
-                       # Avoid excessive memory usage
-                       if ( count( $jobs ) > 10000 ) {
-                               JobQueueGroup::singleton()->push( $jobs );
-                               $jobs = array();
-                       }
-               }
-               JobQueueGroup::singleton()->push( $jobs );
-       }
-
-       /**
-        * @param Title $title
-        * @param array|bool $params
-        * @param int $id
-        */
-       function __construct( $title, $params = false ) {
-               parent::__construct( 'fixDoubleRedirect', $title, $params );
-               $this->reason = $params['reason'];
-               $this->redirTitle = Title::newFromText( $params['redirTitle'] );
-       }
-
-       /**
-        * @return bool
-        */
-       function run() {
-               if ( !$this->redirTitle ) {
-                       $this->setLastError( 'Invalid title' );
-
-                       return false;
-               }
-
-               $targetRev = Revision::newFromTitle( $this->title, false, Revision::READ_LATEST );
-               if ( !$targetRev ) {
-                       wfDebug( __METHOD__ . ": target redirect already deleted, ignoring\n" );
-
-                       return true;
-               }
-               $content = $targetRev->getContent();
-               $currentDest = $content ? $content->getRedirectTarget() : null;
-               if ( !$currentDest || !$currentDest->equals( $this->redirTitle ) ) {
-                       wfDebug( __METHOD__ . ": Redirect has changed since the job was queued\n" );
-
-                       return true;
-               }
-
-               // Check for a suppression tag (used e.g. in periodically archived discussions)
-               $mw = MagicWord::get( 'staticredirect' );
-               if ( $content->matchMagicWord( $mw ) ) {
-                       wfDebug( __METHOD__ . ": skipping: suppressed with __STATICREDIRECT__\n" );
-
-                       return true;
-               }
-
-               // Find the current final destination
-               $newTitle = self::getFinalDestination( $this->redirTitle );
-               if ( !$newTitle ) {
-                       wfDebug( __METHOD__ .
-                               ": skipping: single redirect, circular redirect or invalid redirect destination\n" );
-
-                       return true;
-               }
-               if ( $newTitle->equals( $this->redirTitle ) ) {
-                       // The redirect is already right, no need to change it
-                       // This can happen if the page was moved back (say after vandalism)
-                       wfDebug( __METHOD__ . " : skipping, already good\n" );
-               }
-
-               // Preserve fragment (bug 14904)
-               $newTitle = Title::makeTitle( $newTitle->getNamespace(), $newTitle->getDBkey(),
-                       $currentDest->getFragment(), $newTitle->getInterwiki() );
-
-               // Fix the text
-               $newContent = $content->updateRedirect( $newTitle );
-
-               if ( $newContent->equals( $content ) ) {
-                       $this->setLastError( 'Content unchanged???' );
-
-                       return false;
-               }
-
-               $user = $this->getUser();
-               if ( !$user ) {
-                       $this->setLastError( 'Invalid user' );
-
-                       return false;
-               }
-
-               // Save it
-               global $wgUser;
-               $oldUser = $wgUser;
-               $wgUser = $user;
-               $article = WikiPage::factory( $this->title );
-
-               // Messages: double-redirect-fixed-move, double-redirect-fixed-maintenance
-               $reason = wfMessage( 'double-redirect-fixed-' . $this->reason,
-                       $this->redirTitle->getPrefixedText(), $newTitle->getPrefixedText()
-               )->inContentLanguage()->text();
-               $article->doEditContent( $newContent, $reason, EDIT_UPDATE | EDIT_SUPPRESS_RC, false, $user );
-               $wgUser = $oldUser;
-
-               return true;
-       }
-
-       /**
-        * Get the final destination of a redirect
-        *
-        * @param $title Title
-        *
-        * @return bool if the specified title is not a redirect, or if it is a circular redirect
-        */
-       public static function getFinalDestination( $title ) {
-               $dbw = wfGetDB( DB_MASTER );
-
-               // Circular redirect check
-               $seenTitles = array();
-               $dest = false;
-
-               while ( true ) {
-                       $titleText = $title->getPrefixedDBkey();
-                       if ( isset( $seenTitles[$titleText] ) ) {
-                               wfDebug( __METHOD__, "Circular redirect detected, aborting\n" );
-
-                               return false;
-                       }
-                       $seenTitles[$titleText] = true;
-
-                       if ( $title->isExternal() ) {
-                               // If the target is interwiki, we have to break early (bug 40352).
-                               // Otherwise it will look up a row in the local page table
-                               // with the namespace/page of the interwiki target which can cause
-                               // unexpected results (e.g. X -> foo:Bar -> Bar -> .. )
-                               break;
-                       }
-
-                       $row = $dbw->selectRow(
-                               array( 'redirect', 'page' ),
-                               array( 'rd_namespace', 'rd_title', 'rd_interwiki' ),
-                               array(
-                                       'rd_from=page_id',
-                                       'page_namespace' => $title->getNamespace(),
-                                       'page_title' => $title->getDBkey()
-                               ), __METHOD__ );
-                       if ( !$row ) {
-                               # No redirect from here, chain terminates
-                               break;
-                       } else {
-                               $dest = $title = Title::makeTitle(
-                                       $row->rd_namespace,
-                                       $row->rd_title,
-                                       '',
-                                       $row->rd_interwiki
-                               );
-                       }
-               }
-
-               return $dest;
-       }
-
-       /**
-        * Get a user object for doing edits, from a request-lifetime cache
-        * False will be returned if the user name specified in the
-        * 'double-redirect-fixer' message is invalid.
-        *
-        * @return User|bool
-        */
-       function getUser() {
-               if ( !self::$user ) {
-                       $username = wfMessage( 'double-redirect-fixer' )->inContentLanguage()->text();
-                       self::$user = User::newFromName( $username );
-                       # User::newFromName() can return false on a badly configured wiki.
-                       if ( self::$user && !self::$user->isLoggedIn() ) {
-                               self::$user->addToDatabase();
-                       }
-               }
-
-               return self::$user;
-       }
-}
diff --git a/includes/job/jobs/DuplicateJob.php b/includes/job/jobs/DuplicateJob.php
deleted file mode 100644 (file)
index b0a6ef7..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-<?php
-/**
- * No-op job that does nothing.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @ingroup Cache
- */
-
-/**
- * No-op job that does nothing. Used to represent duplicates.
- *
- * @ingroup JobQueue
- */
-final class DuplicateJob extends Job {
-       /**
-        * Callers should use DuplicateJob::newFromJob() instead
-        *
-        * @param Title $title
-        * @param array $params job parameters
-        */
-       function __construct( $title, $params ) {
-               parent::__construct( 'duplicate', $title, $params );
-       }
-
-       /**
-        * Get a duplicate no-op version of a job
-        *
-        * @param Job $job
-        * @return Job
-        */
-       public static function newFromJob( Job $job ) {
-               $djob = new self( $job->getTitle(), $job->getParams() );
-               $djob->command = $job->getType();
-               $djob->params = is_array( $djob->params ) ? $djob->params : array();
-               $djob->params = array( 'isDuplicate' => true ) + $djob->params;
-               $djob->metadata = $job->metadata;
-
-               return $djob;
-       }
-
-       public function run() {
-               return true;
-       }
-}
diff --git a/includes/job/jobs/EmaillingJob.php b/includes/job/jobs/EmaillingJob.php
deleted file mode 100644 (file)
index df8ae63..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-<?php
-/**
- * Old job for notification emails.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @ingroup JobQueue
- */
-
-/**
- * Old job used for sending single notification emails;
- * kept for backwards-compatibility
- *
- * @ingroup JobQueue
- */
-class EmaillingJob extends Job {
-       function __construct( $title, $params ) {
-               parent::__construct( 'sendMail', Title::newMainPage(), $params );
-       }
-
-       function run() {
-               $status = UserMailer::send(
-                       $this->params['to'],
-                       $this->params['from'],
-                       $this->params['subj'],
-                       $this->params['body'],
-                       $this->params['replyto']
-               );
-
-               return $status->isOK();
-       }
-}
diff --git a/includes/job/jobs/EnotifNotifyJob.php b/includes/job/jobs/EnotifNotifyJob.php
deleted file mode 100644 (file)
index 1ed99a5..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-<?php
-/**
- * Job for notification emails.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @ingroup JobQueue
- */
-
-/**
- * Job for email notification mails
- *
- * @ingroup JobQueue
- */
-class EnotifNotifyJob extends Job {
-       function __construct( $title, $params ) {
-               parent::__construct( 'enotifNotify', $title, $params );
-       }
-
-       function run() {
-               $enotif = new EmailNotification();
-               // Get the user from ID (rename safe). Anons are 0, so defer to name.
-               if ( isset( $this->params['editorID'] ) && $this->params['editorID'] ) {
-                       $editor = User::newFromId( $this->params['editorID'] );
-               // B/C, only the name might be given.
-               } else {
-                       # @todo FIXME: newFromName could return false on a badly configured wiki.
-                       $editor = User::newFromName( $this->params['editor'], false );
-               }
-               $enotif->actuallyNotifyOnPageChange(
-                       $editor,
-                       $this->title,
-                       $this->params['timestamp'],
-                       $this->params['summary'],
-                       $this->params['minorEdit'],
-                       $this->params['oldid'],
-                       $this->params['watchers'],
-                       $this->params['pageStatus']
-               );
-
-               return true;
-       }
-}
diff --git a/includes/job/jobs/HTMLCacheUpdateJob.php b/includes/job/jobs/HTMLCacheUpdateJob.php
deleted file mode 100644 (file)
index a7c5dc0..0000000
+++ /dev/null
@@ -1,170 +0,0 @@
-<?php
-/**
- * HTML cache invalidation of all pages linking to a given title.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @ingroup Cache
- */
-
-/**
- * Job to purge the cache for all pages that link to or use another page or file
- *
- * This job comes in a few variants:
- *   - a) Recursive jobs to purge caches for backlink pages for a given title.
- *        These jobs have have (recursive:true,table:<table>) set.
- *   - b) Jobs to purge caches for a set of titles (the job title is ignored).
- *           These jobs have have (pages:(<page ID>:(<namespace>,<title>),...) set.
- *
- * @ingroup JobQueue
- */
-class HTMLCacheUpdateJob extends Job {
-       function __construct( $title, $params = '' ) {
-               parent::__construct( 'htmlCacheUpdate', $title, $params );
-               // Base backlink purge jobs can be de-duplicated
-               $this->removeDuplicates = ( !isset( $params['range'] ) && !isset( $params['pages'] ) );
-       }
-
-       function run() {
-               global $wgUpdateRowsPerJob, $wgUpdateRowsPerQuery, $wgMaxBacklinksInvalidate;
-
-               static $expected = array( 'recursive', 'pages' ); // new jobs have one of these
-
-               $oldRangeJob = false;
-               if ( !array_intersect( array_keys( $this->params ), $expected ) ) {
-                       // B/C for older job params formats that lack these fields:
-                       // a) base jobs with just ("table") and b) range jobs with ("table","start","end")
-                       if ( isset( $this->params['start'] ) && isset( $this->params['end'] ) ) {
-                               $oldRangeJob = true;
-                       } else {
-                               $this->params['recursive'] = true; // base job
-                       }
-               }
-
-               // Job to purge all (or a range of) backlink pages for a page
-               if ( !empty( $this->params['recursive'] ) ) {
-                       // @TODO: try to use delayed jobs if possible?
-                       if ( !isset( $this->params['range'] ) && $wgMaxBacklinksInvalidate !== false ) {
-                               $numRows = $this->title->getBacklinkCache()->getNumLinks(
-                                       $this->params['table'], $wgMaxBacklinksInvalidate );
-                               if ( $numRows > $wgMaxBacklinksInvalidate ) {
-                                       return true;
-                               }
-                       }
-                       // Convert this into no more than $wgUpdateRowsPerJob HTMLCacheUpdateJob per-title
-                       // jobs and possibly a recursive HTMLCacheUpdateJob job for the rest of the backlinks
-                       $jobs = BacklinkJobUtils::partitionBacklinkJob(
-                               $this,
-                               $wgUpdateRowsPerJob,
-                               $wgUpdateRowsPerQuery, // jobs-per-title
-                               // Carry over information for de-duplication
-                               array( 'params' => $this->getRootJobParams() )
-                       );
-                       JobQueueGroup::singleton()->push( $jobs );
-               // Job to purge pages for for a set of titles
-               } elseif ( isset( $this->params['pages'] ) ) {
-                       $this->invalidateTitles( $this->params['pages'] );
-               // B/C for job to purge a range of backlink pages for a given page
-               } elseif ( $oldRangeJob ) {
-                       $titleArray = $this->title->getBacklinkCache()->getLinks(
-                               $this->params['table'], $this->params['start'], $this->params['end'] );
-
-                       $pages = array(); // same format BacklinkJobUtils uses
-                       foreach ( $titleArray as $tl ) {
-                               $pages[$tl->getArticleId()] = array( $tl->getNamespace(), $tl->getDbKey() );
-                       }
-
-                       $jobs = array();
-                       foreach ( array_chunk( $pages, $wgUpdateRowsPerJob ) as $pageChunk ) {
-                               $jobs[] = new HTMLCacheUpdateJob( $this->title,
-                                       array(
-                                               'table' => $this->params['table'],
-                                               'pages' => $pageChunk
-                                       ) + $this->getRootJobParams() // carry over information for de-duplication
-                               );
-                       }
-                       JobQueueGroup::singleton()->push( $jobs );
-               }
-
-               return true;
-       }
-
-       /**
-        * @param array $pages Map of (page ID => (namespace, DB key)) entries
-        */
-       protected function invalidateTitles( array $pages ) {
-               global $wgUpdateRowsPerQuery, $wgUseFileCache, $wgUseSquid;
-
-               // Get all page IDs in this query into an array
-               $pageIds = array_keys( $pages );
-               if ( !$pageIds ) {
-                       return;
-               }
-
-               $dbw = wfGetDB( DB_MASTER );
-
-               // The page_touched field will need to be bumped for these pages.
-               // Only bump it to the present time if no "rootJobTimestamp" was known.
-               // If it is known, it can be used instead, which avoids invalidating output
-               // that was in fact generated *after* the relevant dependency change time
-               // (e.g. template edit). This is particularily useful since refreshLinks jobs
-               // save back parser output and usually run along side htmlCacheUpdate jobs;
-               // their saved output would be invalidated by using the current timestamp.
-               if ( isset( $this->params['rootJobTimestamp'] ) ) {
-                       $touchTimestamp = $this->params['rootJobTimestamp'];
-               } else {
-                       $touchTimestamp = wfTimestampNow();
-               }
-
-               // Update page_touched (skipping pages already touched since the root job).
-               // Check $wgUpdateRowsPerQuery for sanity; batch jobs are sized by that already.
-               foreach ( array_chunk( $pageIds, $wgUpdateRowsPerQuery ) as $batch ) {
-                       $dbw->update( 'page',
-                               array( 'page_touched' => $dbw->timestamp( $touchTimestamp ) ),
-                               array( 'page_id' => $batch,
-                                       // don't invalidated pages that were already invalidated
-                                       "page_touched < " . $dbw->addQuotes( $dbw->timestamp( $touchTimestamp ) )
-                               ),
-                               __METHOD__
-                       );
-               }
-               // Get the list of affected pages (races only mean something else did the purge)
-               $titleArray = TitleArray::newFromResult( $dbw->select(
-                       'page',
-                       array( 'page_namespace', 'page_title' ),
-                       array( 'page_id' => $pageIds, 'page_touched' => $dbw->timestamp( $touchTimestamp ) ),
-                       __METHOD__
-               ) );
-
-               // Update squid
-               if ( $wgUseSquid ) {
-                       $u = SquidUpdate::newFromTitles( $titleArray );
-                       $u->doUpdate();
-               }
-
-               // Update file cache
-               if ( $wgUseFileCache ) {
-                       foreach ( $titleArray as $title ) {
-                               HTMLFileCache::clearFileCache( $title );
-                       }
-               }
-       }
-
-       public function workItemCount() {
-               return isset( $this->params['pages'] ) ? count( $this->params['pages'] ) : 1;
-       }
-}
diff --git a/includes/job/jobs/NullJob.php b/includes/job/jobs/NullJob.php
deleted file mode 100644 (file)
index b2d6a9a..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-<?php
-/**
- * Degenerate job that does nothing.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @ingroup Cache
- */
-
-/**
- * Degenerate job that does nothing, but can optionally replace itself
- * in the queue and/or sleep for a brief time period. These can be used
- * to represent "no-op" jobs or test lock contention and performance.
- *
- * @par Example:
- * Inserting a null job in the configured job queue:
- * @code
- * $ php maintenance/eval.php
- * > $queue = JobQueueGroup::singleton();
- * > $job = new NullJob( Title::newMainPage(), array( 'lives' => 10 ) );
- * > $queue->push( $job );
- * @endcode
- * You can then confirm the job has been enqueued by using the showJobs.php
- * maintenance utility:
- * @code
- * $ php maintenance/showJobs.php --group
- * null: 1 queue; 0 claimed (0 active, 0 abandoned)
- * $
- * @endcode
- *
- * @ingroup JobQueue
- */
-class NullJob extends Job {
-       /**
-        * @param Title $title
-        * @param array $params job parameters (lives, usleep)
-        */
-       function __construct( $title, $params ) {
-               parent::__construct( 'null', $title, $params );
-               if ( !isset( $this->params['lives'] ) ) {
-                       $this->params['lives'] = 1;
-               }
-               if ( !isset( $this->params['usleep'] ) ) {
-                       $this->params['usleep'] = 0;
-               }
-               $this->removeDuplicates = !empty( $this->params['removeDuplicates'] );
-       }
-
-       public function run() {
-               if ( $this->params['usleep'] > 0 ) {
-                       usleep( $this->params['usleep'] );
-               }
-               if ( $this->params['lives'] > 1 ) {
-                       $params = $this->params;
-                       $params['lives']--;
-                       $job = new self( $this->title, $params );
-                       JobQueueGroup::singleton()->push( $job );
-               }
-
-               return true;
-       }
-}
diff --git a/includes/job/jobs/PublishStashedFileJob.php b/includes/job/jobs/PublishStashedFileJob.php
deleted file mode 100644 (file)
index d7667f3..0000000
+++ /dev/null
@@ -1,147 +0,0 @@
-<?php
-/**
- * Upload a file from the upload stash into the local file repo.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @ingroup Upload
- */
-
-/**
- * Upload a file from the upload stash into the local file repo.
- *
- * @ingroup Upload
- */
-class PublishStashedFileJob extends Job {
-       public function __construct( $title, $params ) {
-               parent::__construct( 'PublishStashedFile', $title, $params );
-               $this->removeDuplicates = true;
-       }
-
-       public function run() {
-               $scope = RequestContext::importScopedSession( $this->params['session'] );
-               $context = RequestContext::getMain();
-               try {
-                       $user = $context->getUser();
-                       if ( !$user->isLoggedIn() ) {
-                               $this->setLastError( "Could not load the author user from session." );
-
-                               return false;
-                       }
-
-                       if ( count( $_SESSION ) === 0 ) {
-                               // Empty session probably indicates that we didn't associate
-                               // with the session correctly. Note that being able to load
-                               // the user does not necessarily mean the session was loaded.
-                               // Most likely cause by suhosin.session.encrypt = On.
-                               $this->setLastError( "Error associating with user session. " .
-                                       "Try setting suhosin.session.encrypt = Off" );
-
-                               return false;
-                       }
-
-                       UploadBase::setSessionStatus(
-                               $this->params['filekey'],
-                               array( 'result' => 'Poll', 'stage' => 'publish', 'status' => Status::newGood() )
-                       );
-
-                       $upload = new UploadFromStash( $user );
-                       // @todo initialize() causes a GET, ideally we could frontload the antivirus
-                       // checks and anything else to the stash stage (which includes concatenation and
-                       // the local file is thus already there). That way, instead of GET+PUT, there could
-                       // just be a COPY operation from the stash to the public zone.
-                       $upload->initialize( $this->params['filekey'], $this->params['filename'] );
-
-                       // Check if the local file checks out (this is generally a no-op)
-                       $verification = $upload->verifyUpload();
-                       if ( $verification['status'] !== UploadBase::OK ) {
-                               $status = Status::newFatal( 'verification-error' );
-                               $status->value = array( 'verification' => $verification );
-                               UploadBase::setSessionStatus(
-                                       $this->params['filekey'],
-                                       array( 'result' => 'Failure', 'stage' => 'publish', 'status' => $status )
-                               );
-                               $this->setLastError( "Could not verify upload." );
-
-                               return false;
-                       }
-
-                       // Upload the stashed file to a permanent location
-                       $status = $upload->performUpload(
-                               $this->params['comment'],
-                               $this->params['text'],
-                               $this->params['watch'],
-                               $user
-                       );
-                       if ( !$status->isGood() ) {
-                               UploadBase::setSessionStatus(
-                                       $this->params['filekey'],
-                                       array( 'result' => 'Failure', 'stage' => 'publish', 'status' => $status )
-                               );
-                               $this->setLastError( $status->getWikiText() );
-
-                               return false;
-                       }
-
-                       // Build the image info array while we have the local reference handy
-                       $apiMain = new ApiMain(); // dummy object (XXX)
-                       $imageInfo = $upload->getImageInfo( $apiMain->getResult() );
-
-                       // Cleanup any temporary local file
-                       $upload->cleanupTempFile();
-
-                       // Cache the info so the user doesn't have to wait forever to get the final info
-                       UploadBase::setSessionStatus(
-                               $this->params['filekey'],
-                               array(
-                                       'result' => 'Success',
-                                       'stage' => 'publish',
-                                       'filename' => $upload->getLocalFile()->getName(),
-                                       'imageinfo' => $imageInfo,
-                                       'status' => Status::newGood()
-                               )
-                       );
-               } catch ( MWException $e ) {
-                       UploadBase::setSessionStatus(
-                               $this->params['filekey'],
-                               array(
-                                       'result' => 'Failure',
-                                       'stage' => 'publish',
-                                       'status' => Status::newFatal( 'api-error-publishfailed' )
-                               )
-                       );
-                       $this->setLastError( get_class( $e ) . ": " . $e->getText() );
-
-                       return false;
-               }
-
-               return true;
-       }
-
-       public function getDeduplicationInfo() {
-               $info = parent::getDeduplicationInfo();
-               if ( is_array( $info['params'] ) ) {
-                       $info['params'] = array( 'filekey' => $info['params']['filekey'] );
-               }
-
-               return $info;
-       }
-
-       public function allowRetries() {
-               return false;
-       }
-}
diff --git a/includes/job/jobs/RefreshLinksJob.php b/includes/job/jobs/RefreshLinksJob.php
deleted file mode 100644 (file)
index 3bcb4fc..0000000
+++ /dev/null
@@ -1,197 +0,0 @@
-<?php
-/**
- * Job to update link tables for pages
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @ingroup JobQueue
- */
-
-/**
- * Job to update link tables for pages
- *
- * This job comes in a few variants:
- *   - a) Recursive jobs to update links for backlink pages for a given title.
- *        These jobs have have (recursive:true,table:<table>) set.
- *   - b) Jobs to update links for a set of pages (the job title is ignored).
- *           These jobs have have (pages:(<page ID>:(<namespace>,<title>),...) set.
- *   - c) Jobs to update links for a single page (the job title)
- *        These jobs need no extra fields set.
- *
- * @ingroup JobQueue
- */
-class RefreshLinksJob extends Job {
-       const PARSE_THRESHOLD_SEC = 1.0;
-
-       function __construct( $title, $params = '' ) {
-               parent::__construct( 'refreshLinks', $title, $params );
-               // Base backlink update jobs and per-title update jobs can be de-duplicated.
-               // If template A changes twice before any jobs run, a clean queue will have:
-               //              (A base, A base)
-               // The second job is ignored by the queue on insertion.
-               // Suppose, many pages use template A, and that template itself uses template B.
-               // An edit to both will first create two base jobs. A clean FIFO queue will have:
-               //              (A base, B base)
-               // When these jobs run, the queue will have per-title and remnant partition jobs:
-               //              (titleX,titleY,titleZ,...,A remnant,titleM,titleN,titleO,...,B remnant)
-               // Some these jobs will be the same, and will automatically be ignored by
-               // the queue upon insertion. Some title jobs will run before the duplicate is
-               // inserted, so the work will still be done twice in those cases. More titles
-               // can be de-duplicated as the remnant jobs continue to be broken down. This
-               // works best when $wgUpdateRowsPerJob, and either the pages have few backlinks
-               // and/or the backlink sets for pages A and B are almost identical.
-               $this->removeDuplicates = !isset( $params['range'] )
-                       && ( !isset( $params['pages'] ) || count( $params['pages'] ) == 1 );
-       }
-
-       function run() {
-               global $wgUpdateRowsPerJob;
-
-               // Job to update all (or a range of) backlink pages for a page
-               if ( !empty( $this->params['recursive'] ) ) {
-                       // Carry over information for de-duplication
-                       $extraParams = $this->getRootJobParams();
-                       // Avoid slave lag when fetching templates.
-                       // When the outermost job is run, we know that the caller that enqueued it must have
-                       // committed the relevant changes to the DB by now. At that point, record the master
-                       // position and pass it along as the job recursively breaks into smaller range jobs.
-                       // Hopefully, when leaf jobs are popped, the slaves will have reached that position.
-                       if ( isset( $this->params['masterPos'] ) ) {
-                               $extraParams['masterPos'] = $this->params['masterPos'];
-                       } elseif ( wfGetLB()->getServerCount() > 1 ) {
-                               $extraParams['masterPos'] = wfGetLB()->getMasterPos();
-                       } else {
-                               $extraParams['masterPos'] = false;
-                       }
-                       // Convert this into no more than $wgUpdateRowsPerJob RefreshLinks per-title
-                       // jobs and possibly a recursive RefreshLinks job for the rest of the backlinks
-                       $jobs = BacklinkJobUtils::partitionBacklinkJob(
-                               $this,
-                               $wgUpdateRowsPerJob,
-                               1, // job-per-title
-                               array( 'params' => $extraParams )
-                       );
-                       JobQueueGroup::singleton()->push( $jobs );
-               // Job to update link tables for for a set of titles
-               } elseif ( isset( $this->params['pages'] ) ) {
-                       foreach ( $this->params['pages'] as $pageId => $nsAndKey ) {
-                               list( $ns, $dbKey ) = $nsAndKey;
-                               $this->runForTitle( Title::makeTitleSafe( $ns, $dbKey ) );
-                       }
-               // Job to update link tables for a given title
-               } else {
-                       $this->runForTitle( $this->title );
-               }
-
-               return true;
-       }
-
-       protected function runForTitle( Title $title = null ) {
-               $linkCache = LinkCache::singleton();
-               $linkCache->clear();
-
-               if ( is_null( $title ) ) {
-                       $this->setLastError( "refreshLinks: Invalid title" );
-                       return false;
-               }
-
-               // Wait for the DB of the current/next slave DB handle to catch up to the master.
-               // This way, we get the correct page_latest for templates or files that just changed
-               // milliseconds ago, having triggered this job to begin with.
-               if ( isset( $this->params['masterPos'] ) && $this->params['masterPos'] !== false ) {
-                       wfGetLB()->waitFor( $this->params['masterPos'] );
-               }
-
-               $page = WikiPage::factory( $title );
-
-               // Fetch the current revision...
-               $revision = Revision::newFromTitle( $title, false, Revision::READ_NORMAL );
-               if ( !$revision ) {
-                       $this->setLastError( "refreshLinks: Article not found {$title->getPrefixedDBkey()}" );
-                       return false; // XXX: what if it was just deleted?
-               }
-               $content = $revision->getContent( Revision::RAW );
-               if ( !$content ) {
-                       // If there is no content, pretend the content is empty
-                       $content = $revision->getContentHandler()->makeEmptyContent();
-               }
-
-               $parserOutput = false;
-               $parserOptions = $page->makeParserOptions( 'canonical' );
-               // If page_touched changed after this root job (with a good slave lag skew factor),
-               // then it is likely that any views of the pages already resulted in re-parses which
-               // are now in cache. This can be reused to avoid expensive parsing in some cases.
-               if ( isset( $this->params['rootJobTimestamp'] ) ) {
-                       $skewedTimestamp = wfTimestamp( TS_UNIX, $this->params['rootJobTimestamp'] ) + 5;
-                       if ( $page->getLinksTimestamp() > wfTimestamp( TS_MW, $skewedTimestamp ) ) {
-                               // Something already updated the backlinks since this job was made
-                               return true;
-                       }
-                       if ( $page->getTouched() > wfTimestamp( TS_MW, $skewedTimestamp ) ) {
-                               $parserOutput = ParserCache::singleton()->getDirty( $page, $parserOptions );
-                               if ( $parserOutput && $parserOutput->getCacheTime() <= $skewedTimestamp ) {
-                                       $parserOutput = false; // too stale
-                               }
-                       }
-               }
-               // Fetch the current revision and parse it if necessary...
-               if ( $parserOutput == false ) {
-                       $start = microtime( true );
-                       // Revision ID must be passed to the parser output to get revision variables correct
-                       $parserOutput = $content->getParserOutput(
-                               $title, $revision->getId(), $parserOptions, false );
-                       $ellapsed = microtime( true ) - $start;
-                       // If it took a long time to render, then save this back to the cache to avoid
-                       // wasted CPU by other apaches or job runners. We don't want to always save to
-                       // cache as this cause cause high cache I/O and LRU churn when a template changes.
-                       if ( $ellapsed >= self::PARSE_THRESHOLD_SEC
-                               && $page->isParserCacheUsed( $parserOptions, $revision->getId() )
-                               && $parserOutput->isCacheable()
-                       ) {
-                               $ctime = wfTimestamp( TS_MW, (int)$start ); // cache time
-                               ParserCache::singleton()->save( $parserOutput, $page, $parserOptions, $ctime );
-                       }
-               }
-
-               $updates = $content->getSecondaryDataUpdates( $title, null, false, $parserOutput );
-               DataUpdate::runUpdates( $updates );
-
-               InfoAction::invalidateCache( $title );
-
-               return true;
-       }
-
-       public function getDeduplicationInfo() {
-               $info = parent::getDeduplicationInfo();
-               if ( is_array( $info['params'] ) ) {
-                       // Don't let highly unique "masterPos" values ruin duplicate detection
-                       unset( $info['params']['masterPos'] );
-                       // For per-pages jobs, the job title is that of the template that changed
-                       // (or similar), so remove that since it ruins duplicate detection
-                       if ( isset( $info['pages'] ) ) {
-                               unset( $info['namespace'] );
-                               unset( $info['title'] );
-                       }
-               }
-
-               return $info;
-       }
-
-       public function workItemCount() {
-               return isset( $this->params['pages'] ) ? count( $this->params['pages'] ) : 1;
-       }
-}
diff --git a/includes/job/jobs/RefreshLinksJob2.php b/includes/job/jobs/RefreshLinksJob2.php
deleted file mode 100644 (file)
index 77e3b3f..0000000
+++ /dev/null
@@ -1,141 +0,0 @@
-<?php
-/**
- * Job to update links for a given title.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @ingroup JobQueue
- */
-
-/**
- * Background job to update links for titles in certain backlink range by page ID.
- * Newer version for high use templates. This is deprecated by RefreshLinksPartitionJob.
- *
- * @ingroup JobQueue
- * @deprecated 1.23
- */
-class RefreshLinksJob2 extends Job {
-       function __construct( $title, $params ) {
-               parent::__construct( 'refreshLinks2', $title, $params );
-               // Base jobs for large templates can easily be de-duplicated
-               $this->removeDuplicates = !isset( $params['start'] ) && !isset( $params['end'] );
-       }
-
-       /**
-        * Run a refreshLinks2 job
-        * @return boolean success
-        */
-       function run() {
-               global $wgUpdateRowsPerJob;
-
-               $linkCache = LinkCache::singleton();
-               $linkCache->clear();
-
-               if ( is_null( $this->title ) ) {
-                       $this->error = "refreshLinks2: Invalid title";
-                       return false;
-               }
-
-               // Back compat for pre-r94435 jobs
-               $table = isset( $this->params['table'] ) ? $this->params['table'] : 'templatelinks';
-
-               // Avoid slave lag when fetching templates.
-               // When the outermost job is run, we know that the caller that enqueued it must have
-               // committed the relevant changes to the DB by now. At that point, record the master
-               // position and pass it along as the job recursively breaks into smaller range jobs.
-               // Hopefully, when leaf jobs are popped, the slaves will have reached that position.
-               if ( isset( $this->params['masterPos'] ) ) {
-                       $masterPos = $this->params['masterPos'];
-               } elseif ( wfGetLB()->getServerCount() > 1 ) {
-                       $masterPos = wfGetLB()->getMasterPos();
-               } else {
-                       $masterPos = false;
-               }
-
-               $tbc = $this->title->getBacklinkCache();
-
-               $jobs = array(); // jobs to insert
-               if ( isset( $this->params['start'] ) && isset( $this->params['end'] ) ) {
-                       # This is a partition job to trigger the insertion of leaf jobs...
-                       $jobs = array_merge( $jobs, $this->getSingleTitleJobs( $table, $masterPos ) );
-               } else {
-                       # This is a base job to trigger the insertion of partitioned jobs...
-                       if ( $tbc->getNumLinks( $table, $wgUpdateRowsPerJob + 1 ) <= $wgUpdateRowsPerJob ) {
-                               # Just directly insert the single per-title jobs
-                               $jobs = array_merge( $jobs, $this->getSingleTitleJobs( $table, $masterPos ) );
-                       } else {
-                               # Insert the partition jobs to make per-title jobs
-                               foreach ( $tbc->partition( $table, $wgUpdateRowsPerJob ) as $batch ) {
-                                       list( $start, $end ) = $batch;
-                                       $jobs[] = new RefreshLinksJob2( $this->title,
-                                               array(
-                                                       'table' => $table,
-                                                       'start' => $start,
-                                                       'end' => $end,
-                                                       'masterPos' => $masterPos,
-                                               ) + $this->getRootJobParams() // carry over information for de-duplication
-                                       );
-                               }
-                       }
-               }
-
-               if ( count( $jobs ) ) {
-                       JobQueueGroup::singleton()->push( $jobs );
-               }
-
-               return true;
-       }
-
-       /**
-        * @param $table string
-        * @param $masterPos mixed
-        * @return Array
-        */
-       protected function getSingleTitleJobs( $table, $masterPos ) {
-               # The "start"/"end" fields are not set for the base jobs
-               $start = isset( $this->params['start'] ) ? $this->params['start'] : false;
-               $end = isset( $this->params['end'] ) ? $this->params['end'] : false;
-               $titles = $this->title->getBacklinkCache()->getLinks( $table, $start, $end );
-               # Convert into single page refresh links jobs.
-               # This handles well when in sapi mode and is useful in any case for job
-               # de-duplication. If many pages use template A, and that template itself
-               # uses template B, then an edit to both will create many duplicate jobs.
-               # Roughly speaking, for each page, one of the "RefreshLinksJob" jobs will
-               # get run first, and when it does, it will remove the duplicates. Of course,
-               # one page could have its job popped when the other page's job is still
-               # buried within the logic of a refreshLinks2 job.
-               $jobs = array();
-               foreach ( $titles as $title ) {
-                       $jobs[] = new RefreshLinksJob( $title,
-                               array( 'masterPos' => $masterPos ) + $this->getRootJobParams()
-                       ); // carry over information for de-duplication
-               }
-               return $jobs;
-       }
-
-       /**
-        * @return Array
-        */
-       public function getDeduplicationInfo() {
-               $info = parent::getDeduplicationInfo();
-               // Don't let highly unique "masterPos" values ruin duplicate detection
-               if ( is_array( $info['params'] ) ) {
-                       unset( $info['params']['masterPos'] );
-               }
-               return $info;
-       }
-}
diff --git a/includes/job/jobs/UploadFromUrlJob.php b/includes/job/jobs/UploadFromUrlJob.php
deleted file mode 100644 (file)
index 2cdac57..0000000
+++ /dev/null
@@ -1,187 +0,0 @@
-<?php
-/**
- * Job for asynchronous upload-by-url.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @ingroup JobQueue
- */
-
-/**
- * Job for asynchronous upload-by-url.
- *
- * This job is in fact an interface to UploadFromUrl, which is designed such
- * that it does not require any globals. If it does, fix it elsewhere, do not
- * add globals in here.
- *
- * @ingroup JobQueue
- */
-class UploadFromUrlJob extends Job {
-       const SESSION_KEYNAME = 'wsUploadFromUrlJobData';
-
-       /** @var UploadFromUrl */
-       public $upload;
-
-       /** @var User */
-       protected $user;
-
-       public function __construct( $title, $params ) {
-               parent::__construct( 'uploadFromUrl', $title, $params );
-       }
-
-       public function run() {
-               global $wgCopyUploadAsyncTimeout;
-               # Initialize this object and the upload object
-               $this->upload = new UploadFromUrl();
-               $this->upload->initialize(
-                       $this->title->getText(),
-                       $this->params['url'],
-                       false
-               );
-               $this->user = User::newFromName( $this->params['userName'] );
-
-               # Fetch the file
-               $opts = array();
-               if ( $wgCopyUploadAsyncTimeout ) {
-                       $opts['timeout'] = $wgCopyUploadAsyncTimeout;
-               }
-               $status = $this->upload->fetchFile( $opts );
-               if ( !$status->isOk() ) {
-                       $this->leaveMessage( $status );
-
-                       return true;
-               }
-
-               # Verify upload
-               $result = $this->upload->verifyUpload();
-               if ( $result['status'] != UploadBase::OK ) {
-                       $status = $this->upload->convertVerifyErrorToStatus( $result );
-                       $this->leaveMessage( $status );
-
-                       return true;
-               }
-
-               # Check warnings
-               if ( !$this->params['ignoreWarnings'] ) {
-                       $warnings = $this->upload->checkWarnings();
-                       if ( $warnings ) {
-
-                               # Stash the upload
-                               $key = $this->upload->stashFile();
-
-                               // @todo FIXME: This has been broken for a while.
-                               // User::leaveUserMessage() does not exist.
-                               if ( $this->params['leaveMessage'] ) {
-                                       $this->user->leaveUserMessage(
-                                               wfMessage( 'upload-warning-subj' )->text(),
-                                               wfMessage( 'upload-warning-msg',
-                                                       $key,
-                                                       $this->params['url'] )->text()
-                                       );
-                               } else {
-                                       wfSetupSession( $this->params['sessionId'] );
-                                       $this->storeResultInSession( 'Warning',
-                                               'warnings', $warnings );
-                                       session_write_close();
-                               }
-
-                               return true;
-                       }
-               }
-
-               # Perform the upload
-               $status = $this->upload->performUpload(
-                       $this->params['comment'],
-                       $this->params['pageText'],
-                       $this->params['watch'],
-                       $this->user
-               );
-               $this->leaveMessage( $status );
-
-               return true;
-       }
-
-       /**
-        * Leave a message on the user talk page or in the session according to
-        * $params['leaveMessage'].
-        *
-        * @param Status $status
-        */
-       protected function leaveMessage( $status ) {
-               if ( $this->params['leaveMessage'] ) {
-                       if ( $status->isGood() ) {
-                               // @todo FIXME: user->leaveUserMessage does not exist.
-                               $this->user->leaveUserMessage( wfMessage( 'upload-success-subj' )->text(),
-                                       wfMessage( 'upload-success-msg',
-                                               $this->upload->getTitle()->getText(),
-                                               $this->params['url']
-                                       )->text() );
-                       } else {
-                               // @todo FIXME: user->leaveUserMessage does not exist.
-                               $this->user->leaveUserMessage( wfMessage( 'upload-failure-subj' )->text(),
-                                       wfMessage( 'upload-failure-msg',
-                                               $status->getWikiText(),
-                                               $this->params['url']
-                                       )->text() );
-                       }
-               } else {
-                       wfSetupSession( $this->params['sessionId'] );
-                       if ( $status->isOk() ) {
-                               $this->storeResultInSession( 'Success',
-                                       'filename', $this->upload->getLocalFile()->getName() );
-                       } else {
-                               $this->storeResultInSession( 'Failure',
-                                       'errors', $status->getErrorsArray() );
-                       }
-                       session_write_close();
-               }
-       }
-
-       /**
-        * Store a result in the session data. Note that the caller is responsible
-        * for appropriate session_start and session_write_close calls.
-        *
-        * @param string $result the result (Success|Warning|Failure)
-        * @param string $dataKey the key of the extra data
-        * @param mixed $dataValue The extra data itself
-        */
-       protected function storeResultInSession( $result, $dataKey, $dataValue ) {
-               $session =& self::getSessionData( $this->params['sessionKey'] );
-               $session['result'] = $result;
-               $session[$dataKey] = $dataValue;
-       }
-
-       /**
-        * Initialize the session data. Sets the intial result to queued.
-        */
-       public function initializeSessionData() {
-               $session =& self::getSessionData( $this->params['sessionKey'] );
-               $$session['result'] = 'Queued';
-       }
-
-       /**
-        * @param $key
-        * @return mixed
-        */
-       public static function &getSessionData( $key ) {
-               if ( !isset( $_SESSION[self::SESSION_KEYNAME][$key] ) ) {
-                       $_SESSION[self::SESSION_KEYNAME][$key] = array();
-               }
-
-               return $_SESSION[self::SESSION_KEYNAME][$key];
-       }
-}
diff --git a/includes/job/utils/BacklinkJobUtils.php b/includes/job/utils/BacklinkJobUtils.php
deleted file mode 100644 (file)
index c8e5df6..0000000
+++ /dev/null
@@ -1,122 +0,0 @@
-<?php
-/**
- * Job to update links for a given title.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @ingroup JobQueue
- * @author Aaron Schulz
- */
-
-/**
- * Class with Backlink related Job helper methods
- *
- * @ingroup JobQueue
- * @since 1.23
- */
-class BacklinkJobUtils {
-       /**
-        * Break down $job into approximately ($bSize/$cSize) leaf jobs and a single partition
-        * job that covers the remaining backlink range (if needed). Jobs for the first $bSize
-        * titles are collated ($cSize per job) into leaf jobs to do actual work. All the
-        * resulting jobs are of the same class as $job. No partition job is returned if the
-        * range covered by $job was less than $bSize, as the leaf jobs have full coverage.
-        *
-        * The leaf jobs have the 'pages' param set to a (<page ID>:(<namespace>,<DB key>),...)
-        * map so that the run() function knows what pages to act on. The leaf jobs will keep
-        * the same job title as the parent job (e.g. $job).
-        *
-        * The partition jobs have the 'range' parameter set to a map of the format
-        * (start:<integer>, end:<integer>, batchSize:<integer>, subranges:((<start>,<end>),...)),
-        * the 'table' parameter set to that of $job, and the 'recursive' parameter set to true.
-        * This method can be called on the resulting job to repeat the process again.
-        *
-        * The job provided ($job) must have the 'recursive' parameter set to true and the 'table'
-        * parameter must be set to a backlink table. The job title will be used as the title to
-        * find backlinks for. Any 'range' parameter must follow the same format as mentioned above.
-        * This should be managed by recursive calls to this method.
-        *
-        * The first jobs return are always the leaf jobs. This lets the caller use push() to
-        * put them directly into the queue and works well if the queue is FIFO. In such a queue,
-        * the leaf jobs have to get finished first before anything can resolve the next partition
-        * job, which keeps the queue very small.
-        *
-        * $opts includes:
-        *   - params : extra job parameters to include in each job
-        *
-        * @param Job $job
-        * @param int $bSize BacklinkCache partition size; usually $wgUpdateRowsPerJob
-        * @param int $cSize Max titles per leaf job; Usually 1 or a modest value
-        * @param array $opts Optional parameter map
-        * @return Job[] List of Job objects
-        */
-       public static function partitionBacklinkJob( Job $job, $bSize, $cSize, $opts = array() ) {
-               $class = get_class( $job );
-               $title = $job->getTitle();
-               $params = $job->getParams();
-
-               if ( isset( $params['pages'] ) || empty( $params['recursive'] ) ) {
-                       $ranges = array(); // sanity; this is a leaf node
-                       wfWarn( __METHOD__ . " called on {$job->getType()} leaf job (explosive recursion)." );
-               } elseif ( isset( $params['range'] ) ) {
-                       // This is a range job to trigger the insertion of partitioned/title jobs...
-                       $ranges = $params['range']['subranges'];
-                       $realBSize = $params['range']['batchSize'];
-               } else {
-                       // This is a base job to trigger the insertion of partitioned jobs...
-                       $ranges = $title->getBacklinkCache()->partition( $params['table'], $bSize );
-                       $realBSize = $bSize;
-               }
-
-               $extraParams = isset( $opts['params'] ) ? $opts['params'] : array();
-
-               $jobs = array();
-               // Combine the first range (of size $bSize) backlinks into leaf jobs
-               if ( isset( $ranges[0] ) ) {
-                       list( $start, $end ) = $ranges[0];
-                       $titles = $title->getBacklinkCache()->getLinks( $params['table'], $start, $end );
-                       foreach ( array_chunk( iterator_to_array( $titles ), $cSize ) as $titleBatch ) {
-                               $pages = array();
-                               foreach ( $titleBatch as $tl ) {
-                                       $pages[$tl->getArticleId()] = array( $tl->getNamespace(), $tl->getDBKey() );
-                               }
-                               $jobs[] = new $class(
-                                       $title, // maintain parent job title
-                                       array( 'pages' => $pages ) + $extraParams
-                               );
-                       }
-               }
-               // Take all of the remaining ranges and build a partition job from it
-               if ( isset( $ranges[1] ) ) {
-                       $jobs[] = new $class(
-                               $title, // maintain parent job title
-                               array(
-                                       'recursive'     => true,
-                                       'table'         => $params['table'],
-                                       'range'         => array(
-                                               'start'     => $ranges[1][0],
-                                               'end'       => $ranges[count( $ranges ) - 1][1],
-                                               'batchSize' => $realBSize,
-                                               'subranges' => array_slice( $ranges, 1 )
-                                       ),
-                               ) + $extraParams
-                       );
-               }
-
-               return $jobs;
-       }
-}
diff --git a/includes/jobqueue/Job.php b/includes/jobqueue/Job.php
new file mode 100644 (file)
index 0000000..5fc1e06
--- /dev/null
@@ -0,0 +1,330 @@
+<?php
+/**
+ * Job queue task base code.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @defgroup JobQueue JobQueue
+ */
+
+/**
+ * Class to both describe a background job and handle jobs.
+ * The queue aspects of this class are now deprecated.
+ * Using the class to push jobs onto queues is deprecated (use JobSpecification).
+ *
+ * @ingroup JobQueue
+ */
+abstract class Job implements IJobSpecification {
+       /** @var string */
+       public $command;
+
+       /** @var array|bool Array of job parameters or false if none */
+       public $params;
+
+       /** @var array Additional queue metadata */
+       public $metadata = array();
+
+       /** @var Title */
+       protected $title;
+
+       /** @var bool Expensive jobs may set this to true */
+       protected $removeDuplicates;
+
+       /** @var string Text for error that occurred last */
+       protected $error;
+
+       /*-------------------------------------------------------------------------
+        * Abstract functions
+        *------------------------------------------------------------------------*/
+
+       /**
+        * Run the job
+        * @return bool Success
+        */
+       abstract public function run();
+
+       /*-------------------------------------------------------------------------
+        * Static functions
+        *------------------------------------------------------------------------*/
+
+       /**
+        * Create the appropriate object to handle a specific job
+        *
+        * @param string $command Job command
+        * @param Title $title Associated title
+        * @param array|bool $params Job parameters
+        * @throws MWException
+        * @return Job
+        */
+       public static function factory( $command, Title $title, $params = false ) {
+               global $wgJobClasses;
+               if ( isset( $wgJobClasses[$command] ) ) {
+                       $class = $wgJobClasses[$command];
+
+                       return new $class( $title, $params );
+               }
+               throw new MWException( "Invalid job command `{$command}`" );
+       }
+
+       /**
+        * Batch-insert a group of jobs into the queue.
+        * This will be wrapped in a transaction with a forced commit.
+        *
+        * This may add duplicate at insert time, but they will be
+        * removed later on, when the first one is popped.
+        *
+        * @param array $jobs of Job objects
+        * @return bool
+        * @deprecated since 1.21
+        */
+       public static function batchInsert( $jobs ) {
+               return JobQueueGroup::singleton()->push( $jobs );
+       }
+
+       /**
+        * Insert a group of jobs into the queue.
+        *
+        * Same as batchInsert() but does not commit and can thus
+        * be rolled-back as part of a larger transaction. However,
+        * large batches of jobs can cause slave lag.
+        *
+        * @param array $jobs of Job objects
+        * @return bool
+        * @deprecated since 1.21
+        */
+       public static function safeBatchInsert( $jobs ) {
+               return JobQueueGroup::singleton()->push( $jobs, JobQueue::QOS_ATOMIC );
+       }
+
+       /**
+        * Pop a job of a certain type.  This tries less hard than pop() to
+        * actually find a job; it may be adversely affected by concurrent job
+        * runners.
+        *
+        * @param $type string
+        * @return Job|bool Returns false if there are no jobs
+        * @deprecated since 1.21
+        */
+       public static function pop_type( $type ) {
+               return JobQueueGroup::singleton()->get( $type )->pop();
+       }
+
+       /**
+        * Pop a job off the front of the queue.
+        * This is subject to $wgJobTypesExcludedFromDefaultQueue.
+        *
+        * @return Job|bool False if there are no jobs
+        * @deprecated since 1.21
+        */
+       public static function pop() {
+               return JobQueueGroup::singleton()->pop();
+       }
+
+       /*-------------------------------------------------------------------------
+        * Non-static functions
+        *------------------------------------------------------------------------*/
+
+       /**
+        * @param $command
+        * @param $title
+        * @param $params array|bool
+        */
+       public function __construct( $command, $title, $params = false ) {
+               $this->command = $command;
+               $this->title = $title;
+               $this->params = $params;
+
+               // expensive jobs may set this to true
+               $this->removeDuplicates = false;
+       }
+
+       /**
+        * @return string
+        */
+       public function getType() {
+               return $this->command;
+       }
+
+       /**
+        * @return Title
+        */
+       public function getTitle() {
+               return $this->title;
+       }
+
+       /**
+        * @return array
+        */
+       public function getParams() {
+               return $this->params;
+       }
+
+       /**
+        * @return int|null UNIX timestamp to delay running this job until, otherwise null
+        * @since 1.22
+        */
+       public function getReleaseTimestamp() {
+               return isset( $this->params['jobReleaseTimestamp'] )
+                       ? wfTimestampOrNull( TS_UNIX, $this->params['jobReleaseTimestamp'] )
+                       : null;
+       }
+
+       /**
+        * @return bool Whether only one of each identical set of jobs should be run
+        */
+       public function ignoreDuplicates() {
+               return $this->removeDuplicates;
+       }
+
+       /**
+        * @return bool Whether this job can be retried on failure by job runners
+        * @since 1.21
+        */
+       public function allowRetries() {
+               return true;
+       }
+
+       /**
+        * @return integer Number of actually "work items" handled in this job
+        * @see $wgJobBackoffThrottling
+        * @since 1.23
+        */
+       public function workItemCount() {
+               return 1;
+       }
+
+       /**
+        * Subclasses may need to override this to make duplication detection work.
+        * The resulting map conveys everything that makes the job unique. This is
+        * only checked if ignoreDuplicates() returns true, meaning that duplicate
+        * jobs are supposed to be ignored.
+        *
+        * @return array Map of key/values
+        * @since 1.21
+        */
+       public function getDeduplicationInfo() {
+               $info = array(
+                       'type' => $this->getType(),
+                       'namespace' => $this->getTitle()->getNamespace(),
+                       'title' => $this->getTitle()->getDBkey(),
+                       'params' => $this->getParams()
+               );
+               if ( is_array( $info['params'] ) ) {
+                       // Identical jobs with different "root" jobs should count as duplicates
+                       unset( $info['params']['rootJobSignature'] );
+                       unset( $info['params']['rootJobTimestamp'] );
+                       // Likewise for jobs with different delay times
+                       unset( $info['params']['jobReleaseTimestamp'] );
+               }
+
+               return $info;
+       }
+
+       /**
+        * @see JobQueue::deduplicateRootJob()
+        * @param string $key A key that identifies the task
+        * @return array Map of:
+        *   - rootJobSignature : hash (e.g. SHA1) that identifies the task
+        *   - rootJobTimestamp : TS_MW timestamp of this instance of the task
+        * @since 1.21
+        */
+       public static function newRootJobParams( $key ) {
+               return array(
+                       'rootJobSignature' => sha1( $key ),
+                       'rootJobTimestamp' => wfTimestampNow()
+               );
+       }
+
+       /**
+        * @see JobQueue::deduplicateRootJob()
+        * @return array
+        * @since 1.21
+        */
+       public function getRootJobParams() {
+               return array(
+                       'rootJobSignature' => isset( $this->params['rootJobSignature'] )
+                               ? $this->params['rootJobSignature']
+                               : null,
+                       'rootJobTimestamp' => isset( $this->params['rootJobTimestamp'] )
+                               ? $this->params['rootJobTimestamp']
+                               : null
+               );
+       }
+
+       /**
+        * @see JobQueue::deduplicateRootJob()
+        * @return bool
+        * @since 1.22
+        */
+       public function hasRootJobParams() {
+               return isset( $this->params['rootJobSignature'] )
+                       && isset( $this->params['rootJobTimestamp'] );
+       }
+
+       /**
+        * Insert a single job into the queue.
+        * @return bool true on success
+        * @deprecated since 1.21
+        */
+       public function insert() {
+               return JobQueueGroup::singleton()->push( $this );
+       }
+
+       /**
+        * @return string
+        */
+       public function toString() {
+               $paramString = '';
+               if ( $this->params ) {
+                       foreach ( $this->params as $key => $value ) {
+                               if ( $paramString != '' ) {
+                                       $paramString .= ' ';
+                               }
+                               if ( is_array( $value ) ) {
+                                       $value = "array(" . count( $value ) . ")";
+                               } elseif ( is_object( $value ) && !method_exists( $value, '__toString' ) ) {
+                                       $value = "object(" . get_class( $value ) . ")";
+                               }
+                               $value = (string)$value;
+                               if ( mb_strlen( $value ) > 1024 ) {
+                                       $value = "string(" . mb_strlen( $value ) . ")";
+                               }
+
+                               $paramString .= "$key=$value";
+                       }
+               }
+
+               if ( is_object( $this->title ) ) {
+                       $s = "{$this->command} " . $this->title->getPrefixedDBkey();
+                       if ( $paramString !== '' ) {
+                               $s .= ' ' . $paramString;
+                       }
+
+                       return $s;
+               } else {
+                       return "{$this->command} $paramString";
+               }
+       }
+
+       protected function setLastError( $error ) {
+               $this->error = $error;
+       }
+
+       public function getLastError() {
+               return $this->error;
+       }
+}
diff --git a/includes/jobqueue/JobQueue.php b/includes/jobqueue/JobQueue.php
new file mode 100644 (file)
index 0000000..a537861
--- /dev/null
@@ -0,0 +1,745 @@
+<?php
+/**
+ * Job queue base code.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @defgroup JobQueue JobQueue
+ * @author Aaron Schulz
+ */
+
+/**
+ * Class to handle enqueueing and running of background jobs
+ *
+ * @ingroup JobQueue
+ * @since 1.21
+ */
+abstract class JobQueue {
+       /** @var string Wiki ID */
+       protected $wiki;
+
+       /** @var string Job type */
+       protected $type;
+
+       /** @var string Job priority for pop() */
+       protected $order;
+
+       /** @var int Time to live in seconds */
+       protected $claimTTL;
+
+       /** @var int Maximum number of times to try a job */
+       protected $maxTries;
+
+       /** @var bool Allow delayed jobs */
+       protected $checkDelay;
+
+       /** @var BagOStuff */
+       protected $dupCache;
+
+       const QOS_ATOMIC = 1; // integer; "all-or-nothing" job insertions
+
+       const ROOTJOB_TTL = 2419200; // integer; seconds to remember root jobs (28 days)
+
+       /**
+        * @param array $params
+        * @throws MWException
+        */
+       protected function __construct( array $params ) {
+               $this->wiki = $params['wiki'];
+               $this->type = $params['type'];
+               $this->claimTTL = isset( $params['claimTTL'] ) ? $params['claimTTL'] : 0;
+               $this->maxTries = isset( $params['maxTries'] ) ? $params['maxTries'] : 3;
+               if ( isset( $params['order'] ) && $params['order'] !== 'any' ) {
+                       $this->order = $params['order'];
+               } else {
+                       $this->order = $this->optimalOrder();
+               }
+               if ( !in_array( $this->order, $this->supportedOrders() ) ) {
+                       throw new MWException( __CLASS__ . " does not support '{$this->order}' order." );
+               }
+               $this->checkDelay = !empty( $params['checkDelay'] );
+               if ( $this->checkDelay && !$this->supportsDelayedJobs() ) {
+                       throw new MWException( __CLASS__ . " does not support delayed jobs." );
+               }
+               $this->dupCache = wfGetCache( CACHE_ANYTHING );
+       }
+
+       /**
+        * Get a job queue object of the specified type.
+        * $params includes:
+        *   - class      : What job class to use (determines job type)
+        *   - wiki       : wiki ID of the wiki the jobs are for (defaults to current wiki)
+        *   - type       : The name of the job types this queue handles
+        *   - order      : Order that pop() selects jobs, one of "fifo", "timestamp" or "random".
+        *                  If "fifo" is used, the queue will effectively be FIFO. Note that job
+        *                  completion will not appear to be exactly FIFO if there are multiple
+        *                  job runners since jobs can take different times to finish once popped.
+        *                  If "timestamp" is used, the queue will at least be loosely ordered
+        *                  by timestamp, allowing for some jobs to be popped off out of order.
+        *                  If "random" is used, pop() will pick jobs in random order.
+        *                  Note that it may only be weakly random (e.g. a lottery of the oldest X).
+        *                  If "any" is choosen, the queue will use whatever order is the fastest.
+        *                  This might be useful for improving concurrency for job acquisition.
+        *   - claimTTL   : If supported, the queue will recycle jobs that have been popped
+        *                  but not acknowledged as completed after this many seconds. Recycling
+        *                  of jobs simple means re-inserting them into the queue. Jobs can be
+        *                  attempted up to three times before being discarded.
+        *   - checkDelay : If supported, respect Job::getReleaseTimestamp() in the push functions.
+        *                  This lets delayed jobs wait in a staging area until a given timestamp is
+        *                  reached, at which point they will enter the queue. If this is not enabled
+        *                  or not supported, an exception will be thrown on delayed job insertion.
+        *
+        * Queue classes should throw an exception if they do not support the options given.
+        *
+        * @param array $params
+        * @return JobQueue
+        * @throws MWException
+        */
+       final public static function factory( array $params ) {
+               $class = $params['class'];
+               if ( !class_exists( $class ) ) {
+                       throw new MWException( "Invalid job queue class '$class'." );
+               }
+               $obj = new $class( $params );
+               if ( !( $obj instanceof self ) ) {
+                       throw new MWException( "Class '$class' is not a " . __CLASS__ . " class." );
+               }
+
+               return $obj;
+       }
+
+       /**
+        * @return string Wiki ID
+        */
+       final public function getWiki() {
+               return $this->wiki;
+       }
+
+       /**
+        * @return string Job type that this queue handles
+        */
+       final public function getType() {
+               return $this->type;
+       }
+
+       /**
+        * @return string One of (random, timestamp, fifo, undefined)
+        */
+       final public function getOrder() {
+               return $this->order;
+       }
+
+       /**
+        * @return bool Whether delayed jobs are enabled
+        * @since 1.22
+        */
+       final public function delayedJobsEnabled() {
+               return $this->checkDelay;
+       }
+
+       /**
+        * Get the allowed queue orders for configuration validation
+        *
+        * @return array Subset of (random, timestamp, fifo, undefined)
+        */
+       abstract protected function supportedOrders();
+
+       /**
+        * Get the default queue order to use if configuration does not specify one
+        *
+        * @return string One of (random, timestamp, fifo, undefined)
+        */
+       abstract protected function optimalOrder();
+
+       /**
+        * Find out if delayed jobs are supported for configuration validation
+        *
+        * @return bool Whether delayed jobs are supported
+        */
+       protected function supportsDelayedJobs() {
+               return false; // not implemented
+       }
+
+       /**
+        * Quickly check if the queue has no available (unacquired, non-delayed) jobs.
+        * Queue classes should use caching if they are any slower without memcached.
+        *
+        * If caching is used, this might return false when there are actually no jobs.
+        * If pop() is called and returns false then it should correct the cache. Also,
+        * calling flushCaches() first prevents this. However, this affect is typically
+        * not distinguishable from the race condition between isEmpty() and pop().
+        *
+        * @return bool
+        * @throws JobQueueError
+        */
+       final public function isEmpty() {
+               wfProfileIn( __METHOD__ );
+               $res = $this->doIsEmpty();
+               wfProfileOut( __METHOD__ );
+
+               return $res;
+       }
+
+       /**
+        * @see JobQueue::isEmpty()
+        * @return bool
+        */
+       abstract protected function doIsEmpty();
+
+       /**
+        * Get the number of available (unacquired, non-delayed) jobs in the queue.
+        * Queue classes should use caching if they are any slower without memcached.
+        *
+        * If caching is used, this number might be out of date for a minute.
+        *
+        * @return int
+        * @throws JobQueueError
+        */
+       final public function getSize() {
+               wfProfileIn( __METHOD__ );
+               $res = $this->doGetSize();
+               wfProfileOut( __METHOD__ );
+
+               return $res;
+       }
+
+       /**
+        * @see JobQueue::getSize()
+        * @return int
+        */
+       abstract protected function doGetSize();
+
+       /**
+        * Get the number of acquired jobs (these are temporarily out of the queue).
+        * Queue classes should use caching if they are any slower without memcached.
+        *
+        * If caching is used, this number might be out of date for a minute.
+        *
+        * @return int
+        * @throws JobQueueError
+        */
+       final public function getAcquiredCount() {
+               wfProfileIn( __METHOD__ );
+               $res = $this->doGetAcquiredCount();
+               wfProfileOut( __METHOD__ );
+
+               return $res;
+       }
+
+       /**
+        * @see JobQueue::getAcquiredCount()
+        * @return int
+        */
+       abstract protected function doGetAcquiredCount();
+
+       /**
+        * Get the number of delayed jobs (these are temporarily out of the queue).
+        * Queue classes should use caching if they are any slower without memcached.
+        *
+        * If caching is used, this number might be out of date for a minute.
+        *
+        * @return int
+        * @throws JobQueueError
+        * @since 1.22
+        */
+       final public function getDelayedCount() {
+               wfProfileIn( __METHOD__ );
+               $res = $this->doGetDelayedCount();
+               wfProfileOut( __METHOD__ );
+
+               return $res;
+       }
+
+       /**
+        * @see JobQueue::getDelayedCount()
+        * @return int
+        */
+       protected function doGetDelayedCount() {
+               return 0; // not implemented
+       }
+
+       /**
+        * Get the number of acquired jobs that can no longer be attempted.
+        * Queue classes should use caching if they are any slower without memcached.
+        *
+        * If caching is used, this number might be out of date for a minute.
+        *
+        * @return int
+        * @throws JobQueueError
+        */
+       final public function getAbandonedCount() {
+               wfProfileIn( __METHOD__ );
+               $res = $this->doGetAbandonedCount();
+               wfProfileOut( __METHOD__ );
+
+               return $res;
+       }
+
+       /**
+        * @see JobQueue::getAbandonedCount()
+        * @return int
+        */
+       protected function doGetAbandonedCount() {
+               return 0; // not implemented
+       }
+
+       /**
+        * Push one or more jobs into the queue.
+        * This does not require $wgJobClasses to be set for the given job type.
+        * Outside callers should use JobQueueGroup::push() instead of this function.
+        *
+        * @param Job|array $jobs A single job or an array of Jobs
+        * @param int $flags Bitfield (supports JobQueue::QOS_ATOMIC)
+        * @return bool Returns false on failure
+        * @throws JobQueueError
+        */
+       final public function push( $jobs, $flags = 0 ) {
+               return $this->batchPush( is_array( $jobs ) ? $jobs : array( $jobs ), $flags );
+       }
+
+       /**
+        * Push a batch of jobs into the queue.
+        * This does not require $wgJobClasses to be set for the given job type.
+        * Outside callers should use JobQueueGroup::push() instead of this function.
+        *
+        * @param array $jobs List of Jobs
+        * @param int $flags Bitfield (supports JobQueue::QOS_ATOMIC)
+        * @throws MWException
+        * @return bool Returns false on failure
+        */
+       final public function batchPush( array $jobs, $flags = 0 ) {
+               if ( !count( $jobs ) ) {
+                       return true; // nothing to do
+               }
+
+               foreach ( $jobs as $job ) {
+                       if ( $job->getType() !== $this->type ) {
+                               throw new MWException(
+                                       "Got '{$job->getType()}' job; expected a '{$this->type}' job." );
+                       } elseif ( $job->getReleaseTimestamp() && !$this->checkDelay ) {
+                               throw new MWException(
+                                       "Got delayed '{$job->getType()}' job; delays are not supported." );
+                       }
+               }
+
+               wfProfileIn( __METHOD__ );
+               $ok = $this->doBatchPush( $jobs, $flags );
+               wfProfileOut( __METHOD__ );
+
+               return $ok;
+       }
+
+       /**
+        * @see JobQueue::batchPush()
+        * @param array $jobs
+        * @param $flags
+        * @return bool
+        */
+       abstract protected function doBatchPush( array $jobs, $flags );
+
+       /**
+        * Pop a job off of the queue.
+        * This requires $wgJobClasses to be set for the given job type.
+        * Outside callers should use JobQueueGroup::pop() instead of this function.
+        *
+        * @throws MWException
+        * @return Job|bool Returns false if there are no jobs
+        */
+       final public function pop() {
+               global $wgJobClasses;
+
+               if ( $this->wiki !== wfWikiID() ) {
+                       throw new MWException( "Cannot pop '{$this->type}' job off foreign wiki queue." );
+               } elseif ( !isset( $wgJobClasses[$this->type] ) ) {
+                       // Do not pop jobs if there is no class for the queue type
+                       throw new MWException( "Unrecognized job type '{$this->type}'." );
+               }
+
+               wfProfileIn( __METHOD__ );
+               $job = $this->doPop();
+               wfProfileOut( __METHOD__ );
+
+               // Flag this job as an old duplicate based on its "root" job...
+               try {
+                       if ( $job && $this->isRootJobOldDuplicate( $job ) ) {
+                               JobQueue::incrStats( 'job-pop-duplicate', $this->type );
+                               $job = DuplicateJob::newFromJob( $job ); // convert to a no-op
+                       }
+               } catch ( MWException $e ) {
+                       // don't lose jobs over this
+               }
+
+               return $job;
+       }
+
+       /**
+        * @see JobQueue::pop()
+        * @return Job
+        */
+       abstract protected function doPop();
+
+       /**
+        * Acknowledge that a job was completed.
+        *
+        * This does nothing for certain queue classes or if "claimTTL" is not set.
+        * Outside callers should use JobQueueGroup::ack() instead of this function.
+        *
+        * @param Job $job
+        * @throws MWException
+        * @return bool
+        */
+       final public function ack( Job $job ) {
+               if ( $job->getType() !== $this->type ) {
+                       throw new MWException( "Got '{$job->getType()}' job; expected '{$this->type}'." );
+               }
+               wfProfileIn( __METHOD__ );
+               $ok = $this->doAck( $job );
+               wfProfileOut( __METHOD__ );
+
+               return $ok;
+       }
+
+       /**
+        * @see JobQueue::ack()
+        * @param Job $job
+        * @return bool
+        */
+       abstract protected function doAck( Job $job );
+
+       /**
+        * Register the "root job" of a given job into the queue for de-duplication.
+        * This should only be called right *after* all the new jobs have been inserted.
+        * This is used to turn older, duplicate, job entries into no-ops. The root job
+        * information will remain in the registry until it simply falls out of cache.
+        *
+        * This requires that $job has two special fields in the "params" array:
+        *   - rootJobSignature : hash (e.g. SHA1) that identifies the task
+        *   - rootJobTimestamp : TS_MW timestamp of this instance of the task
+        *
+        * A "root job" is a conceptual job that consist of potentially many smaller jobs
+        * that are actually inserted into the queue. For example, "refreshLinks" jobs are
+        * spawned when a template is edited. One can think of the task as "update links
+        * of pages that use template X" and an instance of that task as a "root job".
+        * However, what actually goes into the queue are range and leaf job subtypes.
+        * Since these jobs include things like page ID ranges and DB master positions,
+        * and can morph into smaller jobs recursively, simple duplicate detection
+        * for individual jobs being identical (like that of job_sha1) is not useful.
+        *
+        * In the case of "refreshLinks", if these jobs are still in the queue when the template
+        * is edited again, we want all of these old refreshLinks jobs for that template to become
+        * no-ops. This can greatly reduce server load, since refreshLinks jobs involves parsing.
+        * Essentially, the new batch of jobs belong to a new "root job" and the older ones to a
+        * previous "root job" for the same task of "update links of pages that use template X".
+        *
+        * This does nothing for certain queue classes.
+        *
+        * @param Job $job
+        * @throws MWException
+        * @return bool
+        */
+       final public function deduplicateRootJob( Job $job ) {
+               if ( $job->getType() !== $this->type ) {
+                       throw new MWException( "Got '{$job->getType()}' job; expected '{$this->type}'." );
+               }
+               wfProfileIn( __METHOD__ );
+               $ok = $this->doDeduplicateRootJob( $job );
+               wfProfileOut( __METHOD__ );
+
+               return $ok;
+       }
+
+       /**
+        * @see JobQueue::deduplicateRootJob()
+        * @param Job $job
+        * @throws MWException
+        * @return bool
+        */
+       protected function doDeduplicateRootJob( Job $job ) {
+               if ( !$job->hasRootJobParams() ) {
+                       throw new MWException( "Cannot register root job; missing parameters." );
+               }
+               $params = $job->getRootJobParams();
+
+               $key = $this->getRootJobCacheKey( $params['rootJobSignature'] );
+               // Callers should call batchInsert() and then this function so that if the insert
+               // fails, the de-duplication registration will be aborted. Since the insert is
+               // deferred till "transaction idle", do the same here, so that the ordering is
+               // maintained. Having only the de-duplication registration succeed would cause
+               // jobs to become no-ops without any actual jobs that made them redundant.
+               $timestamp = $this->dupCache->get( $key ); // current last timestamp of this job
+               if ( $timestamp && $timestamp >= $params['rootJobTimestamp'] ) {
+                       return true; // a newer version of this root job was enqueued
+               }
+
+               // Update the timestamp of the last root job started at the location...
+               return $this->dupCache->set( $key, $params['rootJobTimestamp'], JobQueueDB::ROOTJOB_TTL );
+       }
+
+       /**
+        * Check if the "root" job of a given job has been superseded by a newer one
+        *
+        * @param Job $job
+        * @throws MWException
+        * @return bool
+        */
+       final protected function isRootJobOldDuplicate( Job $job ) {
+               if ( $job->getType() !== $this->type ) {
+                       throw new MWException( "Got '{$job->getType()}' job; expected '{$this->type}'." );
+               }
+               wfProfileIn( __METHOD__ );
+               $isDuplicate = $this->doIsRootJobOldDuplicate( $job );
+               wfProfileOut( __METHOD__ );
+
+               return $isDuplicate;
+       }
+
+       /**
+        * @see JobQueue::isRootJobOldDuplicate()
+        * @param Job $job
+        * @return bool
+        */
+       protected function doIsRootJobOldDuplicate( Job $job ) {
+               if ( !$job->hasRootJobParams() ) {
+                       return false; // job has no de-deplication info
+               }
+               $params = $job->getRootJobParams();
+
+               $key = $this->getRootJobCacheKey( $params['rootJobSignature'] );
+               // Get the last time this root job was enqueued
+               $timestamp = $this->dupCache->get( $key );
+
+               // Check if a new root job was started at the location after this one's...
+               return ( $timestamp && $timestamp > $params['rootJobTimestamp'] );
+       }
+
+       /**
+        * @param string $signature Hash identifier of the root job
+        * @return string
+        */
+       protected function getRootJobCacheKey( $signature ) {
+               list( $db, $prefix ) = wfSplitWikiID( $this->wiki );
+
+               return wfForeignMemcKey( $db, $prefix, 'jobqueue', $this->type, 'rootjob', $signature );
+       }
+
+       /**
+        * Deleted all unclaimed and delayed jobs from the queue
+        *
+        * @return bool Success
+        * @throws JobQueueError
+        * @since 1.22
+        */
+       final public function delete() {
+               wfProfileIn( __METHOD__ );
+               $res = $this->doDelete();
+               wfProfileOut( __METHOD__ );
+
+               return $res;
+       }
+
+       /**
+        * @see JobQueue::delete()
+        * @throws MWException
+        * @return bool Success
+        */
+       protected function doDelete() {
+               throw new MWException( "This method is not implemented." );
+       }
+
+       /**
+        * Wait for any slaves or backup servers to catch up.
+        *
+        * This does nothing for certain queue classes.
+        *
+        * @return void
+        * @throws JobQueueError
+        */
+       final public function waitForBackups() {
+               wfProfileIn( __METHOD__ );
+               $this->doWaitForBackups();
+               wfProfileOut( __METHOD__ );
+       }
+
+       /**
+        * @see JobQueue::waitForBackups()
+        * @return void
+        */
+       protected function doWaitForBackups() {
+       }
+
+       /**
+        * Return a map of task names to task definition maps.
+        * A "task" is a fast periodic queue maintenance action.
+        * Mutually exclusive tasks must implement their own locking in the callback.
+        *
+        * Each task value is an associative array with:
+        *   - name     : the name of the task
+        *   - callback : a PHP callable that performs the task
+        *   - period   : the period in seconds corresponding to the task frequency
+        *
+        * @return array
+        */
+       final public function getPeriodicTasks() {
+               $tasks = $this->doGetPeriodicTasks();
+               foreach ( $tasks as $name => &$def ) {
+                       $def['name'] = $name;
+               }
+
+               return $tasks;
+       }
+
+       /**
+        * @see JobQueue::getPeriodicTasks()
+        * @return array
+        */
+       protected function doGetPeriodicTasks() {
+               return array();
+       }
+
+       /**
+        * Clear any process and persistent caches
+        *
+        * @return void
+        */
+       final public function flushCaches() {
+               wfProfileIn( __METHOD__ );
+               $this->doFlushCaches();
+               wfProfileOut( __METHOD__ );
+       }
+
+       /**
+        * @see JobQueue::flushCaches()
+        * @return void
+        */
+       protected function doFlushCaches() {
+       }
+
+       /**
+        * Get an iterator to traverse over all available jobs in this queue.
+        * This does not include jobs that are currently acquired or delayed.
+        * Note: results may be stale if the queue is concurrently modified.
+        *
+        * @return Iterator
+        * @throws JobQueueError
+        */
+       abstract public function getAllQueuedJobs();
+
+       /**
+        * Get an iterator to traverse over all delayed jobs in this queue.
+        * Note: results may be stale if the queue is concurrently modified.
+        *
+        * @return Iterator
+        * @throws JobQueueError
+        * @since 1.22
+        */
+       public function getAllDelayedJobs() {
+               return new ArrayIterator( array() ); // not implemented
+       }
+
+       /**
+        * Do not use this function outside of JobQueue/JobQueueGroup
+        *
+        * @return string
+        * @since 1.22
+        */
+       public function getCoalesceLocationInternal() {
+               return null;
+       }
+
+       /**
+        * Check whether each of the given queues are empty.
+        * This is used for batching checks for queues stored at the same place.
+        *
+        * @param array $types List of queues types
+        * @return array|null (list of non-empty queue types) or null if unsupported
+        * @throws MWException
+        * @since 1.22
+        */
+       final public function getSiblingQueuesWithJobs( array $types ) {
+               $section = new ProfileSection( __METHOD__ );
+
+               return $this->doGetSiblingQueuesWithJobs( $types );
+       }
+
+       /**
+        * @see JobQueue::getSiblingQueuesWithJobs()
+        * @param array $types List of queues types
+        * @return array|null (list of queue types) or null if unsupported
+        */
+       protected function doGetSiblingQueuesWithJobs( array $types ) {
+               return null; // not supported
+       }
+
+       /**
+        * Check the size of each of the given queues.
+        * For queues not served by the same store as this one, 0 is returned.
+        * This is used for batching checks for queues stored at the same place.
+        *
+        * @param array $types List of queues types
+        * @return array|null (job type => whether queue is empty) or null if unsupported
+        * @throws MWException
+        * @since 1.22
+        */
+       final public function getSiblingQueueSizes( array $types ) {
+               $section = new ProfileSection( __METHOD__ );
+
+               return $this->doGetSiblingQueueSizes( $types );
+       }
+
+       /**
+        * @see JobQueue::getSiblingQueuesSize()
+        * @param array $types List of queues types
+        * @return array|null (list of queue types) or null if unsupported
+        */
+       protected function doGetSiblingQueueSizes( array $types ) {
+               return null; // not supported
+       }
+
+       /**
+        * Call wfIncrStats() for the queue overall and for the queue type
+        *
+        * @param string $key Event type
+        * @param string $type Job type
+        * @param int $delta
+        * @since 1.22
+        */
+       public static function incrStats( $key, $type, $delta = 1 ) {
+               wfIncrStats( $key, $delta );
+               wfIncrStats( "{$key}-{$type}", $delta );
+       }
+
+       /**
+        * Namespace the queue with a key to isolate it for testing
+        *
+        * @param string $key
+        * @return void
+        * @throws MWException
+        */
+       public function setTestingPrefix( $key ) {
+               throw new MWException( "Queue namespacing not supported for this queue type." );
+       }
+}
+
+/**
+ * @ingroup JobQueue
+ * @since 1.22
+ */
+class JobQueueError extends MWException {
+}
+
+class JobQueueConnectionError extends JobQueueError {
+}
diff --git a/includes/jobqueue/JobQueueDB.php b/includes/jobqueue/JobQueueDB.php
new file mode 100644 (file)
index 0000000..6097d31
--- /dev/null
@@ -0,0 +1,848 @@
+<?php
+/**
+ * Database-backed job queue code.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @author Aaron Schulz
+ */
+
+/**
+ * Class to handle job queues stored in the DB
+ *
+ * @ingroup JobQueue
+ * @since 1.21
+ */
+class JobQueueDB extends JobQueue {
+       const CACHE_TTL_SHORT = 30; // integer; seconds to cache info without re-validating
+       const CACHE_TTL_LONG = 300; // integer; seconds to cache info that is kept up to date
+       const MAX_AGE_PRUNE = 604800; // integer; seconds a job can live once claimed
+       const MAX_JOB_RANDOM = 2147483647; // integer; 2^31 - 1, used for job_random
+       const MAX_OFFSET = 255; // integer; maximum number of rows to skip
+
+       /** @var BagOStuff */
+       protected $cache;
+
+       /** @var bool|string Name of an external DB cluster. False if not set */
+       protected $cluster = false;
+
+       /**
+        * Additional parameters include:
+        *   - cluster : The name of an external cluster registered via LBFactory.
+        *               If not specified, the primary DB cluster for the wiki will be used.
+        *               This can be overridden with a custom cluster so that DB handles will
+        *               be retrieved via LBFactory::getExternalLB() and getConnection().
+        * @param array $params
+        */
+       protected function __construct( array $params ) {
+               global $wgMemc;
+
+               parent::__construct( $params );
+
+               $this->cluster = isset( $params['cluster'] ) ? $params['cluster'] : false;
+               // Make sure that we don't use the SQL cache, which would be harmful
+               $this->cache = ( $wgMemc instanceof SqlBagOStuff ) ? new EmptyBagOStuff() : $wgMemc;
+       }
+
+       protected function supportedOrders() {
+               return array( 'random', 'timestamp', 'fifo' );
+       }
+
+       protected function optimalOrder() {
+               return 'random';
+       }
+
+       /**
+        * @see JobQueue::doIsEmpty()
+        * @return bool
+        */
+       protected function doIsEmpty() {
+               $key = $this->getCacheKey( 'empty' );
+
+               $isEmpty = $this->cache->get( $key );
+               if ( $isEmpty === 'true' ) {
+                       return true;
+               } elseif ( $isEmpty === 'false' ) {
+                       return false;
+               }
+
+               $dbr = $this->getSlaveDB();
+               try {
+                       $found = $dbr->selectField( // unclaimed job
+                               'job', '1', array( 'job_cmd' => $this->type, 'job_token' => '' ), __METHOD__
+                       );
+               } catch ( DBError $e ) {
+                       $this->throwDBException( $e );
+               }
+               $this->cache->add( $key, $found ? 'false' : 'true', self::CACHE_TTL_LONG );
+
+               return !$found;
+       }
+
+       /**
+        * @see JobQueue::doGetSize()
+        * @return int
+        */
+       protected function doGetSize() {
+               $key = $this->getCacheKey( 'size' );
+
+               $size = $this->cache->get( $key );
+               if ( is_int( $size ) ) {
+                       return $size;
+               }
+
+               try {
+                       $dbr = $this->getSlaveDB();
+                       $size = (int)$dbr->selectField( 'job', 'COUNT(*)',
+                               array( 'job_cmd' => $this->type, 'job_token' => '' ),
+                               __METHOD__
+                       );
+               } catch ( DBError $e ) {
+                       $this->throwDBException( $e );
+               }
+               $this->cache->set( $key, $size, self::CACHE_TTL_SHORT );
+
+               return $size;
+       }
+
+       /**
+        * @see JobQueue::doGetAcquiredCount()
+        * @return int
+        */
+       protected function doGetAcquiredCount() {
+               if ( $this->claimTTL <= 0 ) {
+                       return 0; // no acknowledgements
+               }
+
+               $key = $this->getCacheKey( 'acquiredcount' );
+
+               $count = $this->cache->get( $key );
+               if ( is_int( $count ) ) {
+                       return $count;
+               }
+
+               $dbr = $this->getSlaveDB();
+               try {
+                       $count = (int)$dbr->selectField( 'job', 'COUNT(*)',
+                               array( 'job_cmd' => $this->type, "job_token != {$dbr->addQuotes( '' )}" ),
+                               __METHOD__
+                       );
+               } catch ( DBError $e ) {
+                       $this->throwDBException( $e );
+               }
+               $this->cache->set( $key, $count, self::CACHE_TTL_SHORT );
+
+               return $count;
+       }
+
+       /**
+        * @see JobQueue::doGetAbandonedCount()
+        * @return int
+        * @throws MWException
+        */
+       protected function doGetAbandonedCount() {
+               global $wgMemc;
+
+               if ( $this->claimTTL <= 0 ) {
+                       return 0; // no acknowledgements
+               }
+
+               $key = $this->getCacheKey( 'abandonedcount' );
+
+               $count = $wgMemc->get( $key );
+               if ( is_int( $count ) ) {
+                       return $count;
+               }
+
+               $dbr = $this->getSlaveDB();
+               try {
+                       $count = (int)$dbr->selectField( 'job', 'COUNT(*)',
+                               array(
+                                       'job_cmd' => $this->type,
+                                       "job_token != {$dbr->addQuotes( '' )}",
+                                       "job_attempts >= " . $dbr->addQuotes( $this->maxTries )
+                               ),
+                               __METHOD__
+                       );
+               } catch ( DBError $e ) {
+                       $this->throwDBException( $e );
+               }
+               $wgMemc->set( $key, $count, self::CACHE_TTL_SHORT );
+
+               return $count;
+       }
+
+       /**
+        * @see JobQueue::doBatchPush()
+        * @param array $jobs
+        * @param $flags
+        * @throws DBError|Exception
+        * @return bool
+        */
+       protected function doBatchPush( array $jobs, $flags ) {
+               $dbw = $this->getMasterDB();
+
+               $that = $this;
+               $method = __METHOD__;
+               $dbw->onTransactionIdle(
+                       function () use ( $dbw, $that, $jobs, $flags, $method ) {
+                               $that->doBatchPushInternal( $dbw, $jobs, $flags, $method );
+                       }
+               );
+
+               return true;
+       }
+
+       /**
+        * This function should *not* be called outside of JobQueueDB
+        *
+        * @param IDatabase $dbw
+        * @param array $jobs
+        * @param int $flags
+        * @param string $method
+        * @throws DBError
+        * @return bool
+        */
+       public function doBatchPushInternal( IDatabase $dbw, array $jobs, $flags, $method ) {
+               if ( !count( $jobs ) ) {
+                       return true;
+               }
+
+               $rowSet = array(); // (sha1 => job) map for jobs that are de-duplicated
+               $rowList = array(); // list of jobs for jobs that are are not de-duplicated
+               foreach ( $jobs as $job ) {
+                       $row = $this->insertFields( $job );
+                       if ( $job->ignoreDuplicates() ) {
+                               $rowSet[$row['job_sha1']] = $row;
+                       } else {
+                               $rowList[] = $row;
+                       }
+               }
+
+               if ( $flags & self::QOS_ATOMIC ) {
+                       $dbw->begin( $method ); // wrap all the job additions in one transaction
+               }
+               try {
+                       // Strip out any duplicate jobs that are already in the queue...
+                       if ( count( $rowSet ) ) {
+                               $res = $dbw->select( 'job', 'job_sha1',
+                                       array(
+                                               // No job_type condition since it's part of the job_sha1 hash
+                                               'job_sha1' => array_keys( $rowSet ),
+                                               'job_token' => '' // unclaimed
+                                       ),
+                                       $method
+                               );
+                               foreach ( $res as $row ) {
+                                       wfDebug( "Job with hash '{$row->job_sha1}' is a duplicate.\n" );
+                                       unset( $rowSet[$row->job_sha1] ); // already enqueued
+                               }
+                       }
+                       // Build the full list of job rows to insert
+                       $rows = array_merge( $rowList, array_values( $rowSet ) );
+                       // Insert the job rows in chunks to avoid slave lag...
+                       foreach ( array_chunk( $rows, 50 ) as $rowBatch ) {
+                               $dbw->insert( 'job', $rowBatch, $method );
+                       }
+                       JobQueue::incrStats( 'job-insert', $this->type, count( $rows ) );
+                       JobQueue::incrStats(
+                               'job-insert-duplicate',
+                               $this->type,
+                               count( $rowSet ) + count( $rowList ) - count( $rows )
+                       );
+               } catch ( DBError $e ) {
+                       if ( $flags & self::QOS_ATOMIC ) {
+                               $dbw->rollback( $method );
+                       }
+                       throw $e;
+               }
+               if ( $flags & self::QOS_ATOMIC ) {
+                       $dbw->commit( $method );
+               }
+
+               $this->cache->set( $this->getCacheKey( 'empty' ), 'false', JobQueueDB::CACHE_TTL_LONG );
+
+               return true;
+       }
+
+       /**
+        * @see JobQueue::doPop()
+        * @return Job|bool
+        */
+       protected function doPop() {
+               if ( $this->cache->get( $this->getCacheKey( 'empty' ) ) === 'true' ) {
+                       return false; // queue is empty
+               }
+
+               $dbw = $this->getMasterDB();
+               try {
+                       $dbw->commit( __METHOD__, 'flush' ); // flush existing transaction
+                       $autoTrx = $dbw->getFlag( DBO_TRX ); // get current setting
+                       $dbw->clearFlag( DBO_TRX ); // make each query its own transaction
+                       $scopedReset = new ScopedCallback( function () use ( $dbw, $autoTrx ) {
+                               $dbw->setFlag( $autoTrx ? DBO_TRX : 0 ); // restore old setting
+                       } );
+
+                       $uuid = wfRandomString( 32 ); // pop attempt
+                       $job = false; // job popped off
+                       do { // retry when our row is invalid or deleted as a duplicate
+                               // Try to reserve a row in the DB...
+                               if ( in_array( $this->order, array( 'fifo', 'timestamp' ) ) ) {
+                                       $row = $this->claimOldest( $uuid );
+                               } else { // random first
+                                       $rand = mt_rand( 0, self::MAX_JOB_RANDOM ); // encourage concurrent UPDATEs
+                                       $gte = (bool)mt_rand( 0, 1 ); // find rows with rand before/after $rand
+                                       $row = $this->claimRandom( $uuid, $rand, $gte );
+                               }
+                               // Check if we found a row to reserve...
+                               if ( !$row ) {
+                                       $this->cache->set( $this->getCacheKey( 'empty' ), 'true', self::CACHE_TTL_LONG );
+                                       break; // nothing to do
+                               }
+                               JobQueue::incrStats( 'job-pop', $this->type );
+                               // Get the job object from the row...
+                               $title = Title::makeTitleSafe( $row->job_namespace, $row->job_title );
+                               if ( !$title ) {
+                                       $dbw->delete( 'job', array( 'job_id' => $row->job_id ), __METHOD__ );
+                                       wfDebug( "Row has invalid title '{$row->job_title}'." );
+                                       continue; // try again
+                               }
+                               $job = Job::factory( $row->job_cmd, $title,
+                                       self::extractBlob( $row->job_params ), $row->job_id );
+                               $job->metadata['id'] = $row->job_id;
+                               break; // done
+                       } while ( true );
+               } catch ( DBError $e ) {
+                       $this->throwDBException( $e );
+               }
+
+               return $job;
+       }
+
+       /**
+        * Reserve a row with a single UPDATE without holding row locks over RTTs...
+        *
+        * @param string $uuid 32 char hex string
+        * @param $rand integer Random unsigned integer (31 bits)
+        * @param bool $gte Search for job_random >= $random (otherwise job_random <= $random)
+        * @return stdClass|bool Row|false
+        */
+       protected function claimRandom( $uuid, $rand, $gte ) {
+               $dbw = $this->getMasterDB();
+               // Check cache to see if the queue has <= OFFSET items
+               $tinyQueue = $this->cache->get( $this->getCacheKey( 'small' ) );
+
+               $row = false; // the row acquired
+               $invertedDirection = false; // whether one job_random direction was already scanned
+               // This uses a replication safe method for acquiring jobs. One could use UPDATE+LIMIT
+               // instead, but that either uses ORDER BY (in which case it deadlocks in MySQL) or is
+               // not replication safe. Due to http://bugs.mysql.com/bug.php?id=6980, subqueries cannot
+               // be used here with MySQL.
+               do {
+                       if ( $tinyQueue ) { // queue has <= MAX_OFFSET rows
+                               // For small queues, using OFFSET will overshoot and return no rows more often.
+                               // Instead, this uses job_random to pick a row (possibly checking both directions).
+                               $ineq = $gte ? '>=' : '<=';
+                               $dir = $gte ? 'ASC' : 'DESC';
+                               $row = $dbw->selectRow( 'job', self::selectFields(), // find a random job
+                                       array(
+                                               'job_cmd' => $this->type,
+                                               'job_token' => '', // unclaimed
+                                               "job_random {$ineq} {$dbw->addQuotes( $rand )}" ),
+                                       __METHOD__,
+                                       array( 'ORDER BY' => "job_random {$dir}" )
+                               );
+                               if ( !$row && !$invertedDirection ) {
+                                       $gte = !$gte;
+                                       $invertedDirection = true;
+                                       continue; // try the other direction
+                               }
+                       } else { // table *may* have >= MAX_OFFSET rows
+                               // Bug 42614: "ORDER BY job_random" with a job_random inequality causes high CPU
+                               // in MySQL if there are many rows for some reason. This uses a small OFFSET
+                               // instead of job_random for reducing excess claim retries.
+                               $row = $dbw->selectRow( 'job', self::selectFields(), // find a random job
+                                       array(
+                                               'job_cmd' => $this->type,
+                                               'job_token' => '', // unclaimed
+                                       ),
+                                       __METHOD__,
+                                       array( 'OFFSET' => mt_rand( 0, self::MAX_OFFSET ) )
+                               );
+                               if ( !$row ) {
+                                       $tinyQueue = true; // we know the queue must have <= MAX_OFFSET rows
+                                       $this->cache->set( $this->getCacheKey( 'small' ), 1, 30 );
+                                       continue; // use job_random
+                               }
+                       }
+
+                       if ( $row ) { // claim the job
+                               $dbw->update( 'job', // update by PK
+                                       array(
+                                               'job_token' => $uuid,
+                                               'job_token_timestamp' => $dbw->timestamp(),
+                                               'job_attempts = job_attempts+1' ),
+                                       array( 'job_cmd' => $this->type, 'job_id' => $row->job_id, 'job_token' => '' ),
+                                       __METHOD__
+                               );
+                               // This might get raced out by another runner when claiming the previously
+                               // selected row. The use of job_random should minimize this problem, however.
+                               if ( !$dbw->affectedRows() ) {
+                                       $row = false; // raced out
+                               }
+                       } else {
+                               break; // nothing to do
+                       }
+               } while ( !$row );
+
+               return $row;
+       }
+
+       /**
+        * Reserve a row with a single UPDATE without holding row locks over RTTs...
+        *
+        * @param string $uuid 32 char hex string
+        * @return stdClass|bool Row|false
+        */
+       protected function claimOldest( $uuid ) {
+               $dbw = $this->getMasterDB();
+
+               $row = false; // the row acquired
+               do {
+                       if ( $dbw->getType() === 'mysql' ) {
+                               // Per http://bugs.mysql.com/bug.php?id=6980, we can't use subqueries on the
+                               // same table being changed in an UPDATE query in MySQL (gives Error: 1093).
+                               // Oracle and Postgre have no such limitation. However, MySQL offers an
+                               // alternative here by supporting ORDER BY + LIMIT for UPDATE queries.
+                               $dbw->query( "UPDATE {$dbw->tableName( 'job' )} " .
+                                       "SET " .
+                                               "job_token = {$dbw->addQuotes( $uuid ) }, " .
+                                               "job_token_timestamp = {$dbw->addQuotes( $dbw->timestamp() )}, " .
+                                               "job_attempts = job_attempts+1 " .
+                                       "WHERE ( " .
+                                               "job_cmd = {$dbw->addQuotes( $this->type )} " .
+                                               "AND job_token = {$dbw->addQuotes( '' )} " .
+                                       ") ORDER BY job_id ASC LIMIT 1",
+                                       __METHOD__
+                               );
+                       } else {
+                               // Use a subquery to find the job, within an UPDATE to claim it.
+                               // This uses as much of the DB wrapper functions as possible.
+                               $dbw->update( 'job',
+                                       array(
+                                               'job_token' => $uuid,
+                                               'job_token_timestamp' => $dbw->timestamp(),
+                                               'job_attempts = job_attempts+1' ),
+                                       array( 'job_id = (' .
+                                               $dbw->selectSQLText( 'job', 'job_id',
+                                                       array( 'job_cmd' => $this->type, 'job_token' => '' ),
+                                                       __METHOD__,
+                                                       array( 'ORDER BY' => 'job_id ASC', 'LIMIT' => 1 ) ) .
+                                               ')'
+                                       ),
+                                       __METHOD__
+                               );
+                       }
+                       // Fetch any row that we just reserved...
+                       if ( $dbw->affectedRows() ) {
+                               $row = $dbw->selectRow( 'job', self::selectFields(),
+                                       array( 'job_cmd' => $this->type, 'job_token' => $uuid ), __METHOD__
+                               );
+                               if ( !$row ) { // raced out by duplicate job removal
+                                       wfDebug( "Row deleted as duplicate by another process." );
+                               }
+                       } else {
+                               break; // nothing to do
+                       }
+               } while ( !$row );
+
+               return $row;
+       }
+
+       /**
+        * @see JobQueue::doAck()
+        * @param Job $job
+        * @throws MWException
+        * @return Job|bool
+        */
+       protected function doAck( Job $job ) {
+               if ( !isset( $job->metadata['id'] ) ) {
+                       throw new MWException( "Job of type '{$job->getType()}' has no ID." );
+               }
+
+               $dbw = $this->getMasterDB();
+               try {
+                       $dbw->commit( __METHOD__, 'flush' ); // flush existing transaction
+                       $autoTrx = $dbw->getFlag( DBO_TRX ); // get current setting
+                       $dbw->clearFlag( DBO_TRX ); // make each query its own transaction
+                       $scopedReset = new ScopedCallback( function () use ( $dbw, $autoTrx ) {
+                               $dbw->setFlag( $autoTrx ? DBO_TRX : 0 ); // restore old setting
+                       } );
+
+                       // Delete a row with a single DELETE without holding row locks over RTTs...
+                       $dbw->delete( 'job',
+                               array( 'job_cmd' => $this->type, 'job_id' => $job->metadata['id'] ), __METHOD__ );
+               } catch ( DBError $e ) {
+                       $this->throwDBException( $e );
+               }
+
+               return true;
+       }
+
+       /**
+        * @see JobQueue::doDeduplicateRootJob()
+        * @param Job $job
+        * @throws MWException
+        * @return bool
+        */
+       protected function doDeduplicateRootJob( Job $job ) {
+               $params = $job->getParams();
+               if ( !isset( $params['rootJobSignature'] ) ) {
+                       throw new MWException( "Cannot register root job; missing 'rootJobSignature'." );
+               } elseif ( !isset( $params['rootJobTimestamp'] ) ) {
+                       throw new MWException( "Cannot register root job; missing 'rootJobTimestamp'." );
+               }
+               $key = $this->getRootJobCacheKey( $params['rootJobSignature'] );
+               // Callers should call batchInsert() and then this function so that if the insert
+               // fails, the de-duplication registration will be aborted. Since the insert is
+               // deferred till "transaction idle", do the same here, so that the ordering is
+               // maintained. Having only the de-duplication registration succeed would cause
+               // jobs to become no-ops without any actual jobs that made them redundant.
+               $dbw = $this->getMasterDB();
+               $cache = $this->dupCache;
+               $dbw->onTransactionIdle( function () use ( $cache, $params, $key, $dbw ) {
+                       $timestamp = $cache->get( $key ); // current last timestamp of this job
+                       if ( $timestamp && $timestamp >= $params['rootJobTimestamp'] ) {
+                               return true; // a newer version of this root job was enqueued
+                       }
+
+                       // Update the timestamp of the last root job started at the location...
+                       return $cache->set( $key, $params['rootJobTimestamp'], JobQueueDB::ROOTJOB_TTL );
+               } );
+
+               return true;
+       }
+
+       /**
+        * @see JobQueue::doDelete()
+        * @return bool
+        */
+       protected function doDelete() {
+               $dbw = $this->getMasterDB();
+               try {
+                       $dbw->delete( 'job', array( 'job_cmd' => $this->type ) );
+               } catch ( DBError $e ) {
+                       $this->throwDBException( $e );
+               }
+
+               return true;
+       }
+
+       /**
+        * @see JobQueue::doWaitForBackups()
+        * @return void
+        */
+       protected function doWaitForBackups() {
+               wfWaitForSlaves();
+       }
+
+       /**
+        * @return array
+        */
+       protected function doGetPeriodicTasks() {
+               return array(
+                       'recycleAndDeleteStaleJobs' => array(
+                               'callback' => array( $this, 'recycleAndDeleteStaleJobs' ),
+                               'period' => ceil( $this->claimTTL / 2 )
+                       )
+               );
+       }
+
+       /**
+        * @return void
+        */
+       protected function doFlushCaches() {
+               foreach ( array( 'empty', 'size', 'acquiredcount' ) as $type ) {
+                       $this->cache->delete( $this->getCacheKey( $type ) );
+               }
+       }
+
+       /**
+        * @see JobQueue::getAllQueuedJobs()
+        * @return Iterator
+        */
+       public function getAllQueuedJobs() {
+               $dbr = $this->getSlaveDB();
+               try {
+                       return new MappedIterator(
+                               $dbr->select( 'job', self::selectFields(),
+                                       array( 'job_cmd' => $this->getType(), 'job_token' => '' ) ),
+                               function ( $row ) use ( $dbr ) {
+                                       $job = Job::factory(
+                                               $row->job_cmd,
+                                               Title::makeTitle( $row->job_namespace, $row->job_title ),
+                                               strlen( $row->job_params ) ? unserialize( $row->job_params ) : false
+                                       );
+                                       $job->metadata['id'] = $row->job_id;
+                                       return $job;
+                               }
+                       );
+               } catch ( DBError $e ) {
+                       $this->throwDBException( $e );
+               }
+       }
+
+       public function getCoalesceLocationInternal() {
+               return $this->cluster
+                       ? "DBCluster:{$this->cluster}:{$this->wiki}"
+                       : "LBFactory:{$this->wiki}";
+       }
+
+       protected function doGetSiblingQueuesWithJobs( array $types ) {
+               $dbr = $this->getSlaveDB();
+               $res = $dbr->select( 'job', 'DISTINCT job_cmd',
+                       array( 'job_cmd' => $types ), __METHOD__ );
+
+               $types = array();
+               foreach ( $res as $row ) {
+                       $types[] = $row->job_cmd;
+               }
+
+               return $types;
+       }
+
+       protected function doGetSiblingQueueSizes( array $types ) {
+               $dbr = $this->getSlaveDB();
+               $res = $dbr->select( 'job', array( 'job_cmd', 'COUNT(*) AS count' ),
+                       array( 'job_cmd' => $types ), __METHOD__, array( 'GROUP BY' => 'job_cmd' ) );
+
+               $sizes = array();
+               foreach ( $res as $row ) {
+                       $sizes[$row->job_cmd] = (int)$row->count;
+               }
+
+               return $sizes;
+       }
+
+       /**
+        * Recycle or destroy any jobs that have been claimed for too long
+        *
+        * @return int Number of jobs recycled/deleted
+        */
+       public function recycleAndDeleteStaleJobs() {
+               $now = time();
+               $count = 0; // affected rows
+               $dbw = $this->getMasterDB();
+
+               try {
+                       if ( !$dbw->lock( "jobqueue-recycle-{$this->type}", __METHOD__, 1 ) ) {
+                               return $count; // already in progress
+                       }
+
+                       // Remove claims on jobs acquired for too long if enabled...
+                       if ( $this->claimTTL > 0 ) {
+                               $claimCutoff = $dbw->timestamp( $now - $this->claimTTL );
+                               // Get the IDs of jobs that have be claimed but not finished after too long.
+                               // These jobs can be recycled into the queue by expiring the claim. Selecting
+                               // the IDs first means that the UPDATE can be done by primary key (less deadlocks).
+                               $res = $dbw->select( 'job', 'job_id',
+                                       array(
+                                               'job_cmd' => $this->type,
+                                               "job_token != {$dbw->addQuotes( '' )}", // was acquired
+                                               "job_token_timestamp < {$dbw->addQuotes( $claimCutoff )}", // stale
+                                               "job_attempts < {$dbw->addQuotes( $this->maxTries )}" ), // retries left
+                                       __METHOD__
+                               );
+                               $ids = array_map(
+                                       function ( $o ) {
+                                               return $o->job_id;
+                                       }, iterator_to_array( $res )
+                               );
+                               if ( count( $ids ) ) {
+                                       // Reset job_token for these jobs so that other runners will pick them up.
+                                       // Set the timestamp to the current time, as it is useful to now that the job
+                                       // was already tried before (the timestamp becomes the "released" time).
+                                       $dbw->update( 'job',
+                                               array(
+                                                       'job_token' => '',
+                                                       'job_token_timestamp' => $dbw->timestamp( $now ) ), // time of release
+                                               array(
+                                                       'job_id' => $ids ),
+                                               __METHOD__
+                                       );
+                                       $count += $dbw->affectedRows();
+                                       JobQueue::incrStats( 'job-recycle', $this->type, $dbw->affectedRows() );
+                                       $this->cache->set( $this->getCacheKey( 'empty' ), 'false', self::CACHE_TTL_LONG );
+                               }
+                       }
+
+                       // Just destroy any stale jobs...
+                       $pruneCutoff = $dbw->timestamp( $now - self::MAX_AGE_PRUNE );
+                       $conds = array(
+                               'job_cmd' => $this->type,
+                               "job_token != {$dbw->addQuotes( '' )}", // was acquired
+                               "job_token_timestamp < {$dbw->addQuotes( $pruneCutoff )}" // stale
+                       );
+                       if ( $this->claimTTL > 0 ) { // only prune jobs attempted too many times...
+                               $conds[] = "job_attempts >= {$dbw->addQuotes( $this->maxTries )}";
+                       }
+                       // Get the IDs of jobs that are considered stale and should be removed. Selecting
+                       // the IDs first means that the UPDATE can be done by primary key (less deadlocks).
+                       $res = $dbw->select( 'job', 'job_id', $conds, __METHOD__ );
+                       $ids = array_map(
+                               function ( $o ) {
+                                       return $o->job_id;
+                               }, iterator_to_array( $res )
+                       );
+                       if ( count( $ids ) ) {
+                               $dbw->delete( 'job', array( 'job_id' => $ids ), __METHOD__ );
+                               $count += $dbw->affectedRows();
+                               JobQueue::incrStats( 'job-abandon', $this->type, $dbw->affectedRows() );
+                       }
+
+                       $dbw->unlock( "jobqueue-recycle-{$this->type}", __METHOD__ );
+               } catch ( DBError $e ) {
+                       $this->throwDBException( $e );
+               }
+
+               return $count;
+       }
+
+       /**
+        * @param IJobSpecification $job
+        * @return array
+        */
+       protected function insertFields( IJobSpecification $job ) {
+               $dbw = $this->getMasterDB();
+
+               return array(
+                       // Fields that describe the nature of the job
+                       'job_cmd' => $job->getType(),
+                       'job_namespace' => $job->getTitle()->getNamespace(),
+                       'job_title' => $job->getTitle()->getDBkey(),
+                       'job_params' => self::makeBlob( $job->getParams() ),
+                       // Additional job metadata
+                       'job_id' => $dbw->nextSequenceValue( 'job_job_id_seq' ),
+                       'job_timestamp' => $dbw->timestamp(),
+                       'job_sha1' => wfBaseConvert(
+                               sha1( serialize( $job->getDeduplicationInfo() ) ),
+                               16, 36, 31
+                       ),
+                       'job_random' => mt_rand( 0, self::MAX_JOB_RANDOM )
+               );
+       }
+
+       /**
+        * @throws JobQueueConnectionError
+        * @return DBConnRef
+        */
+       protected function getSlaveDB() {
+               try {
+                       return $this->getDB( DB_SLAVE );
+               } catch ( DBConnectionError $e ) {
+                       throw new JobQueueConnectionError( "DBConnectionError:" . $e->getMessage() );
+               }
+       }
+
+       /**
+        * @throws JobQueueConnectionError
+        * @return DBConnRef
+        */
+       protected function getMasterDB() {
+               try {
+                       return $this->getDB( DB_MASTER );
+               } catch ( DBConnectionError $e ) {
+                       throw new JobQueueConnectionError( "DBConnectionError:" . $e->getMessage() );
+               }
+       }
+
+       /**
+        * @param $index integer (DB_SLAVE/DB_MASTER)
+        * @return DBConnRef
+        */
+       protected function getDB( $index ) {
+               $lb = ( $this->cluster !== false )
+                       ? wfGetLBFactory()->getExternalLB( $this->cluster, $this->wiki )
+                       : wfGetLB( $this->wiki );
+
+               return $lb->getConnectionRef( $index, array(), $this->wiki );
+       }
+
+       /**
+        * @param $property
+        * @return string
+        */
+       private function getCacheKey( $property ) {
+               list( $db, $prefix ) = wfSplitWikiID( $this->wiki );
+               $cluster = is_string( $this->cluster ) ? $this->cluster : 'main';
+
+               return wfForeignMemcKey( $db, $prefix, 'jobqueue', $cluster, $this->type, $property );
+       }
+
+       /**
+        * @param $params
+        * @return string
+        */
+       protected static function makeBlob( $params ) {
+               if ( $params !== false ) {
+                       return serialize( $params );
+               } else {
+                       return '';
+               }
+       }
+
+       /**
+        * @param $blob
+        * @return bool|mixed
+        */
+       protected static function extractBlob( $blob ) {
+               if ( (string)$blob !== '' ) {
+                       return unserialize( $blob );
+               } else {
+                       return false;
+               }
+       }
+
+       /**
+        * @param DBError $e
+        * @throws JobQueueError
+        */
+       protected function throwDBException( DBError $e ) {
+               throw new JobQueueError( get_class( $e ) . ": " . $e->getMessage() );
+       }
+
+       /**
+        * Return the list of job fields that should be selected.
+        * @since 1.23
+        * @return array
+        */
+       public static function selectFields() {
+               return array(
+                       'job_id',
+                       'job_cmd',
+                       'job_namespace',
+                       'job_title',
+                       'job_timestamp',
+                       'job_params',
+                       'job_random',
+                       'job_attempts',
+                       'job_token',
+                       'job_token_timestamp',
+                       'job_sha1',
+               );
+       }
+}
diff --git a/includes/jobqueue/JobQueueFederated.php b/includes/jobqueue/JobQueueFederated.php
new file mode 100644 (file)
index 0000000..9502148
--- /dev/null
@@ -0,0 +1,553 @@
+<?php
+/**
+ * Job queue code for federated queues.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @author Aaron Schulz
+ */
+
+/**
+ * Class to handle enqueueing and running of background jobs for federated queues
+ *
+ * This class allows for queues to be partitioned into smaller queues.
+ * A partition is defined by the configuration for a JobQueue instance.
+ * For example, one can set $wgJobTypeConf['refreshLinks'] to point to a
+ * JobQueueFederated instance, which itself would consist of three JobQueueRedis
+ * instances, each using their own redis server. This would allow for the jobs
+ * to be split (evenly or based on weights) accross multiple servers if a single
+ * server becomes impractical or expensive. Different JobQueue classes can be mixed.
+ *
+ * The basic queue configuration (e.g. "order", "claimTTL") of a federated queue
+ * is inherited by the partition queues. Additional configuration defines what
+ * section each wiki is in, what partition queues each section uses (and their weight),
+ * and the JobQueue configuration for each partition. Some sections might only need a
+ * single queue partition, like the sections for groups of small wikis.
+ *
+ * If used for performance, then $wgMainCacheType should be set to memcached/redis.
+ * Note that "fifo" cannot be used for the ordering, since the data is distributed.
+ * One can still use "timestamp" instead, as in "roughly timestamp ordered". Also,
+ * queue classes used by this should ignore down servers (with TTL) to avoid slowness.
+ *
+ * @ingroup JobQueue
+ * @since 1.22
+ */
+class JobQueueFederated extends JobQueue {
+       /** @var array (partition name => weight) reverse sorted by weight */
+       protected $partitionMap = array();
+
+       /** @var array (partition name => JobQueue) reverse sorted by weight */
+       protected $partitionQueues = array();
+
+       /** @var HashRing */
+       protected $partitionPushRing;
+
+       /** @var BagOStuff */
+       protected $cache;
+
+       /** @var int Maximum number of partitions to try */
+       protected $maxPartitionsTry;
+
+       const CACHE_TTL_SHORT = 30; // integer; seconds to cache info without re-validating
+       const CACHE_TTL_LONG = 300; // integer; seconds to cache info that is kept up to date
+
+       /**
+        * @params include:
+        *  - sectionsByWiki      : A map of wiki IDs to section names.
+        *                          Wikis will default to using the section "default".
+        *  - partitionsBySection : Map of section names to maps of (partition name => weight).
+        *                          A section called 'default' must be defined if not all wikis
+        *                          have explicitly defined sections.
+        *  - configByPartition   : Map of queue partition names to configuration arrays.
+        *                          These configuration arrays are passed to JobQueue::factory().
+        *                          The options set here are overriden by those passed to this
+        *                          the federated queue itself (e.g. 'order' and 'claimTTL').
+        *  - partitionsNoPush    : List of partition names that can handle pop() but not push().
+        *                          This can be used to migrate away from a certain partition.
+        *  - maxPartitionsTry    : Maximum number of times to attempt job insertion using
+        *                          different partition queues. This improves availability
+        *                          during failure, at the cost of added latency and somewhat
+        *                          less reliable job de-duplication mechanisms.
+        * @param array $params
+        * @throws MWException
+        */
+       protected function __construct( array $params ) {
+               parent::__construct( $params );
+               $section = isset( $params['sectionsByWiki'][$this->wiki] )
+                       ? $params['sectionsByWiki'][$this->wiki]
+                       : 'default';
+               if ( !isset( $params['partitionsBySection'][$section] ) ) {
+                       throw new MWException( "No configuration for section '$section'." );
+               }
+               $this->maxPartitionsTry = isset( $params['maxPartitionsTry'] )
+                       ? $params['maxPartitionsTry']
+                       : 2;
+               // Get the full partition map
+               $this->partitionMap = $params['partitionsBySection'][$section];
+               arsort( $this->partitionMap, SORT_NUMERIC );
+               // Get the partitions jobs can actually be pushed to
+               $partitionPushMap = $this->partitionMap;
+               if ( isset( $params['partitionsNoPush'] ) ) {
+                       foreach ( $params['partitionsNoPush'] as $partition ) {
+                               unset( $partitionPushMap[$partition] );
+                       }
+               }
+               // Get the config to pass to merge into each partition queue config
+               $baseConfig = $params;
+               foreach ( array( 'class', 'sectionsByWiki', 'maxPartitionsTry',
+                       'partitionsBySection', 'configByPartition', 'partitionsNoPush' ) as $o
+               ) {
+                       unset( $baseConfig[$o] ); // partition queue doesn't care about this
+               }
+               // Get the partition queue objects
+               foreach ( $this->partitionMap as $partition => $w ) {
+                       if ( !isset( $params['configByPartition'][$partition] ) ) {
+                               throw new MWException( "No configuration for partition '$partition'." );
+                       }
+                       $this->partitionQueues[$partition] = JobQueue::factory(
+                               $baseConfig + $params['configByPartition'][$partition] );
+               }
+               // Get the ring of partitions to push jobs into
+               $this->partitionPushRing = new HashRing( $partitionPushMap );
+               // Aggregate cache some per-queue values if there are multiple partition queues
+               $this->cache = count( $this->partitionMap ) > 1 ? wfGetMainCache() : new EmptyBagOStuff();
+       }
+
+       protected function supportedOrders() {
+               // No FIFO due to partitioning, though "rough timestamp order" is supported
+               return array( 'undefined', 'random', 'timestamp' );
+       }
+
+       protected function optimalOrder() {
+               return 'undefined'; // defer to the partitions
+       }
+
+       protected function supportsDelayedJobs() {
+               return true; // defer checks to the partitions
+       }
+
+       protected function doIsEmpty() {
+               $key = $this->getCacheKey( 'empty' );
+
+               $isEmpty = $this->cache->get( $key );
+               if ( $isEmpty === 'true' ) {
+                       return true;
+               } elseif ( $isEmpty === 'false' ) {
+                       return false;
+               }
+
+               $empty = true;
+               $failed = 0;
+               foreach ( $this->partitionQueues as $queue ) {
+                       try {
+                               $empty = $empty && $queue->doIsEmpty();
+                       } catch ( JobQueueError $e ) {
+                               ++$failed;
+                               MWExceptionHandler::logException( $e );
+                       }
+               }
+               $this->throwErrorIfAllPartitionsDown( $failed );
+
+               $this->cache->add( $key, $empty ? 'true' : 'false', self::CACHE_TTL_LONG );
+               return $empty;
+       }
+
+       protected function doGetSize() {
+               return $this->getCrossPartitionSum( 'size', 'doGetSize' );
+       }
+
+       protected function doGetAcquiredCount() {
+               return $this->getCrossPartitionSum( 'acquiredcount', 'doGetAcquiredCount' );
+       }
+
+       protected function doGetDelayedCount() {
+               return $this->getCrossPartitionSum( 'delayedcount', 'doGetDelayedCount' );
+       }
+
+       protected function doGetAbandonedCount() {
+               return $this->getCrossPartitionSum( 'abandonedcount', 'doGetAbandonedCount' );
+       }
+
+       /**
+        * @param string $type
+        * @param string $method
+        * @return int
+        */
+       protected function getCrossPartitionSum( $type, $method ) {
+               $key = $this->getCacheKey( $type );
+
+               $count = $this->cache->get( $key );
+               if ( is_int( $count ) ) {
+                       return $count;
+               }
+
+               $failed = 0;
+               foreach ( $this->partitionQueues as $queue ) {
+                       try {
+                               $count += $queue->$method();
+                       } catch ( JobQueueError $e ) {
+                               ++$failed;
+                               MWExceptionHandler::logException( $e );
+                       }
+               }
+               $this->throwErrorIfAllPartitionsDown( $failed );
+
+               $this->cache->set( $key, $count, self::CACHE_TTL_SHORT );
+
+               return $count;
+       }
+
+       protected function doBatchPush( array $jobs, $flags ) {
+               // Local ring variable that may be changed to point to a new ring on failure
+               $partitionRing = $this->partitionPushRing;
+               // Try to insert the jobs and update $partitionsTry on any failures.
+               // Retry to insert any remaning jobs again, ignoring the bad partitions.
+               $jobsLeft = $jobs;
+               for ( $i = $this->maxPartitionsTry; $i > 0 && count( $jobsLeft ); --$i ) {
+                       $jobsLeft = $this->tryJobInsertions( $jobsLeft, $partitionRing, $flags );
+               }
+               if ( count( $jobsLeft ) ) {
+                       throw new JobQueueError(
+                               "Could not insert job(s), {$this->maxPartitionsTry} partitions tried." );
+               }
+
+               return true;
+       }
+
+       /**
+        * @param array $jobs
+        * @param HashRing $partitionRing
+        * @param int $flags
+        * @throws JobQueueError
+        * @return array List of Job object that could not be inserted
+        */
+       protected function tryJobInsertions( array $jobs, HashRing &$partitionRing, $flags ) {
+               $jobsLeft = array();
+
+               // Because jobs are spread across partitions, per-job de-duplication needs
+               // to use a consistent hash to avoid allowing duplicate jobs per partition.
+               // When inserting a batch of de-duplicated jobs, QOS_ATOMIC is disregarded.
+               $uJobsByPartition = array(); // (partition name => job list)
+               /** @var Job $job */
+               foreach ( $jobs as $key => $job ) {
+                       if ( $job->ignoreDuplicates() ) {
+                               $sha1 = sha1( serialize( $job->getDeduplicationInfo() ) );
+                               $uJobsByPartition[$partitionRing->getLocation( $sha1 )][] = $job;
+                               unset( $jobs[$key] );
+                       }
+               }
+               // Get the batches of jobs that are not de-duplicated
+               if ( $flags & self::QOS_ATOMIC ) {
+                       $nuJobBatches = array( $jobs ); // all or nothing
+               } else {
+                       // Split the jobs into batches and spread them out over servers if there
+                       // are many jobs. This helps keep the partitions even. Otherwise, send all
+                       // the jobs to a single partition queue to avoids the extra connections.
+                       $nuJobBatches = array_chunk( $jobs, 300 );
+               }
+
+               // Insert the de-duplicated jobs into the queues...
+               foreach ( $uJobsByPartition as $partition => $jobBatch ) {
+                       /** @var JobQueue $queue */
+                       $queue = $this->partitionQueues[$partition];
+                       try {
+                               $ok = $queue->doBatchPush( $jobBatch, $flags | self::QOS_ATOMIC );
+                       } catch ( JobQueueError $e ) {
+                               $ok = false;
+                               MWExceptionHandler::logException( $e );
+                       }
+                       if ( $ok ) {
+                               $key = $this->getCacheKey( 'empty' );
+                               $this->cache->set( $key, 'false', JobQueueDB::CACHE_TTL_LONG );
+                       } else {
+                               $partitionRing = $partitionRing->newWithoutLocation( $partition ); // blacklist
+                               if ( !$partitionRing ) {
+                                       throw new JobQueueError( "Could not insert job(s), no partitions available." );
+                               }
+                               $jobsLeft = array_merge( $jobsLeft, $jobBatch ); // not inserted
+                       }
+               }
+
+               // Insert the jobs that are not de-duplicated into the queues...
+               foreach ( $nuJobBatches as $jobBatch ) {
+                       $partition = ArrayUtils::pickRandom( $partitionRing->getLocationWeights() );
+                       $queue = $this->partitionQueues[$partition];
+                       try {
+                               $ok = $queue->doBatchPush( $jobBatch, $flags | self::QOS_ATOMIC );
+                       } catch ( JobQueueError $e ) {
+                               $ok = false;
+                               MWExceptionHandler::logException( $e );
+                       }
+                       if ( $ok ) {
+                               $key = $this->getCacheKey( 'empty' );
+                               $this->cache->set( $key, 'false', JobQueueDB::CACHE_TTL_LONG );
+                       } else {
+                               $partitionRing = $partitionRing->newWithoutLocation( $partition ); // blacklist
+                               if ( !$partitionRing ) {
+                                       throw new JobQueueError( "Could not insert job(s), no partitions available." );
+                               }
+                               $jobsLeft = array_merge( $jobsLeft, $jobBatch ); // not inserted
+                       }
+               }
+
+               return $jobsLeft;
+       }
+
+       protected function doPop() {
+               $key = $this->getCacheKey( 'empty' );
+
+               $isEmpty = $this->cache->get( $key );
+               if ( $isEmpty === 'true' ) {
+                       return false;
+               }
+
+               $partitionsTry = $this->partitionMap; // (partition => weight)
+
+               $failed = 0;
+               while ( count( $partitionsTry ) ) {
+                       $partition = ArrayUtils::pickRandom( $partitionsTry );
+                       if ( $partition === false ) {
+                               break; // all partitions at 0 weight
+                       }
+
+                       /** @var JobQueue $queue */
+                       $queue = $this->partitionQueues[$partition];
+                       try {
+                               $job = $queue->pop();
+                       } catch ( JobQueueError $e ) {
+                               ++$failed;
+                               MWExceptionHandler::logException( $e );
+                               $job = false;
+                       }
+                       if ( $job ) {
+                               $job->metadata['QueuePartition'] = $partition;
+
+                               return $job;
+                       } else {
+                               unset( $partitionsTry[$partition] ); // blacklist partition
+                       }
+               }
+               $this->throwErrorIfAllPartitionsDown( $failed );
+
+               $this->cache->set( $key, 'true', JobQueueDB::CACHE_TTL_LONG );
+
+               return false;
+       }
+
+       protected function doAck( Job $job ) {
+               if ( !isset( $job->metadata['QueuePartition'] ) ) {
+                       throw new MWException( "The given job has no defined partition name." );
+               }
+
+               return $this->partitionQueues[$job->metadata['QueuePartition']]->ack( $job );
+       }
+
+       protected function doIsRootJobOldDuplicate( Job $job ) {
+               $params = $job->getRootJobParams();
+               $partitions = $this->partitionPushRing->getLocations( $params['rootJobSignature'], 2 );
+               try {
+                       return $this->partitionQueues[$partitions[0]]->doIsRootJobOldDuplicate( $job );
+               } catch ( JobQueueError $e ) {
+                       if ( isset( $partitions[1] ) ) { // check fallback partition
+                               return $this->partitionQueues[$partitions[1]]->doIsRootJobOldDuplicate( $job );
+                       }
+               }
+
+               return false;
+       }
+
+       protected function doDeduplicateRootJob( Job $job ) {
+               $params = $job->getRootJobParams();
+               $partitions = $this->partitionPushRing->getLocations( $params['rootJobSignature'], 2 );
+               try {
+                       return $this->partitionQueues[$partitions[0]]->doDeduplicateRootJob( $job );
+               } catch ( JobQueueError $e ) {
+                       if ( isset( $partitions[1] ) ) { // check fallback partition
+                               return $this->partitionQueues[$partitions[1]]->doDeduplicateRootJob( $job );
+                       }
+               }
+
+               return false;
+       }
+
+       protected function doDelete() {
+               $failed = 0;
+               /** @var JobQueue $queue */
+               foreach ( $this->partitionQueues as $queue ) {
+                       try {
+                               $queue->doDelete();
+                       } catch ( JobQueueError $e ) {
+                               ++$failed;
+                               MWExceptionHandler::logException( $e );
+                       }
+               }
+               $this->throwErrorIfAllPartitionsDown( $failed );
+               return true;
+       }
+
+       protected function doWaitForBackups() {
+               $failed = 0;
+               /** @var JobQueue $queue */
+               foreach ( $this->partitionQueues as $queue ) {
+                       try {
+                               $queue->waitForBackups();
+                       } catch ( JobQueueError $e ) {
+                               ++$failed;
+                               MWExceptionHandler::logException( $e );
+                       }
+               }
+               $this->throwErrorIfAllPartitionsDown( $failed );
+       }
+
+       protected function doGetPeriodicTasks() {
+               $tasks = array();
+               /** @var JobQueue $queue */
+               foreach ( $this->partitionQueues as $partition => $queue ) {
+                       foreach ( $queue->getPeriodicTasks() as $task => $def ) {
+                               $tasks["{$partition}:{$task}"] = $def;
+                       }
+               }
+
+               return $tasks;
+       }
+
+       protected function doFlushCaches() {
+               static $types = array(
+                       'empty',
+                       'size',
+                       'acquiredcount',
+                       'delayedcount',
+                       'abandonedcount'
+               );
+
+               foreach ( $types as $type ) {
+                       $this->cache->delete( $this->getCacheKey( $type ) );
+               }
+
+               /** @var JobQueue $queue */
+               foreach ( $this->partitionQueues as $queue ) {
+                       $queue->doFlushCaches();
+               }
+       }
+
+       public function getAllQueuedJobs() {
+               $iterator = new AppendIterator();
+
+               /** @var JobQueue $queue */
+               foreach ( $this->partitionQueues as $queue ) {
+                       $iterator->append( $queue->getAllQueuedJobs() );
+               }
+
+               return $iterator;
+       }
+
+       public function getAllDelayedJobs() {
+               $iterator = new AppendIterator();
+
+               /** @var JobQueue $queue */
+               foreach ( $this->partitionQueues as $queue ) {
+                       $iterator->append( $queue->getAllDelayedJobs() );
+               }
+
+               return $iterator;
+       }
+
+       public function getCoalesceLocationInternal() {
+               return "JobQueueFederated:wiki:{$this->wiki}" .
+                       sha1( serialize( array_keys( $this->partitionMap ) ) );
+       }
+
+       protected function doGetSiblingQueuesWithJobs( array $types ) {
+               $result = array();
+
+               $failed = 0;
+               /** @var JobQueue $queue */
+               foreach ( $this->partitionQueues as $queue ) {
+                       try {
+                               $nonEmpty = $queue->doGetSiblingQueuesWithJobs( $types );
+                               if ( is_array( $nonEmpty ) ) {
+                                       $result = array_unique( array_merge( $result, $nonEmpty ) );
+                               } else {
+                                       return null; // not supported on all partitions; bail
+                               }
+                               if ( count( $result ) == count( $types ) ) {
+                                       break; // short-circuit
+                               }
+                       } catch ( JobQueueError $e ) {
+                               ++$failed;
+                               MWExceptionHandler::logException( $e );
+                       }
+               }
+               $this->throwErrorIfAllPartitionsDown( $failed );
+
+               return array_values( $result );
+       }
+
+       protected function doGetSiblingQueueSizes( array $types ) {
+               $result = array();
+               $failed = 0;
+               /** @var JobQueue $queue */
+               foreach ( $this->partitionQueues as $queue ) {
+                       try {
+                               $sizes = $queue->doGetSiblingQueueSizes( $types );
+                               if ( is_array( $sizes ) ) {
+                                       foreach ( $sizes as $type => $size ) {
+                                               $result[$type] = isset( $result[$type] ) ? $result[$type] + $size : $size;
+                                       }
+                               } else {
+                                       return null; // not supported on all partitions; bail
+                               }
+                       } catch ( JobQueueError $e ) {
+                               ++$failed;
+                               MWExceptionHandler::logException( $e );
+                       }
+               }
+               $this->throwErrorIfAllPartitionsDown( $failed );
+
+               return $result;
+       }
+
+       /**
+        * Throw an error if no partitions available
+        *
+        * @param int $down The number of up partitions down
+        * @return void
+        * @throws JobQueueError
+        */
+       protected function throwErrorIfAllPartitionsDown( $down ) {
+               if ( $down >= count( $this->partitionQueues ) ) {
+                       throw new JobQueueError( 'No queue partitions available.' );
+               }
+       }
+
+       public function setTestingPrefix( $key ) {
+               /** @var JobQueue $queue */
+               foreach ( $this->partitionQueues as $queue ) {
+                       $queue->setTestingPrefix( $key );
+               }
+       }
+
+       /**
+        * @param $property
+        * @return string
+        */
+       private function getCacheKey( $property ) {
+               list( $db, $prefix ) = wfSplitWikiID( $this->wiki );
+
+               return wfForeignMemcKey( $db, $prefix, 'jobqueue', $this->type, $property );
+       }
+}
diff --git a/includes/jobqueue/JobQueueGroup.php b/includes/jobqueue/JobQueueGroup.php
new file mode 100644 (file)
index 0000000..90742ce
--- /dev/null
@@ -0,0 +1,417 @@
+<?php
+/**
+ * Job queue base code.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @author Aaron Schulz
+ */
+
+/**
+ * Class to handle enqueueing of background jobs
+ *
+ * @ingroup JobQueue
+ * @since 1.21
+ */
+class JobQueueGroup {
+       /** @var array */
+       protected static $instances = array();
+
+       /** @var ProcessCacheLRU */
+       protected $cache;
+
+       /** @var string Wiki ID */
+       protected $wiki;
+
+       /** @var array Map of (bucket => (queue => JobQueue, types => list of types) */
+       protected $coalescedQueues;
+
+       const TYPE_DEFAULT = 1; // integer; jobs popped by default
+       const TYPE_ANY = 2; // integer; any job
+
+       const USE_CACHE = 1; // integer; use process or persistent cache
+
+       const PROC_CACHE_TTL = 15; // integer; seconds
+
+       const CACHE_VERSION = 1; // integer; cache version
+
+       /**
+        * @param string $wiki Wiki ID
+        */
+       protected function __construct( $wiki ) {
+               $this->wiki = $wiki;
+               $this->cache = new ProcessCacheLRU( 10 );
+       }
+
+       /**
+        * @param bool|string $wiki Wiki ID
+        * @return JobQueueGroup
+        */
+       public static function singleton( $wiki = false ) {
+               $wiki = ( $wiki === false ) ? wfWikiID() : $wiki;
+               if ( !isset( self::$instances[$wiki] ) ) {
+                       self::$instances[$wiki] = new self( $wiki );
+               }
+
+               return self::$instances[$wiki];
+       }
+
+       /**
+        * Destroy the singleton instances
+        *
+        * @return void
+        */
+       public static function destroySingletons() {
+               self::$instances = array();
+       }
+
+       /**
+        * Get the job queue object for a given queue type
+        *
+        * @param string $type
+        * @return JobQueue
+        */
+       public function get( $type ) {
+               global $wgJobTypeConf;
+
+               $conf = array( 'wiki' => $this->wiki, 'type' => $type );
+               if ( isset( $wgJobTypeConf[$type] ) ) {
+                       $conf = $conf + $wgJobTypeConf[$type];
+               } else {
+                       $conf = $conf + $wgJobTypeConf['default'];
+               }
+
+               return JobQueue::factory( $conf );
+       }
+
+       /**
+        * Insert jobs into the respective queues of with the belong.
+        *
+        * This inserts the jobs into the queue specified by $wgJobTypeConf
+        * and updates the aggregate job queue information cache as needed.
+        *
+        * @param Job|array $jobs A single Job or a list of Jobs
+        * @throws MWException
+        * @return bool
+        */
+       public function push( $jobs ) {
+               $jobs = is_array( $jobs ) ? $jobs : array( $jobs );
+               if ( !count( $jobs ) ) {
+                       return true;
+               }
+
+               $jobsByType = array(); // (job type => list of jobs)
+               foreach ( $jobs as $job ) {
+                       if ( $job instanceof IJobSpecification ) {
+                               $jobsByType[$job->getType()][] = $job;
+                       } else {
+                               throw new MWException( "Attempted to push a non-Job object into a queue." );
+                       }
+               }
+
+               $ok = true;
+               foreach ( $jobsByType as $type => $jobs ) {
+                       if ( $this->get( $type )->push( $jobs ) ) {
+                               JobQueueAggregator::singleton()->notifyQueueNonEmpty( $this->wiki, $type );
+                       } else {
+                               $ok = false;
+                       }
+               }
+
+               if ( $this->cache->has( 'queues-ready', 'list' ) ) {
+                       $list = $this->cache->get( 'queues-ready', 'list' );
+                       if ( count( array_diff( array_keys( $jobsByType ), $list ) ) ) {
+                               $this->cache->clear( 'queues-ready' );
+                       }
+               }
+
+               return $ok;
+       }
+
+       /**
+        * Pop a job off one of the job queues
+        *
+        * This pops a job off a queue as specified by $wgJobTypeConf and
+        * updates the aggregate job queue information cache as needed.
+        *
+        * @param int|string $qtype JobQueueGroup::TYPE_* constant or job type string
+        * @param int $flags Bitfield of JobQueueGroup::USE_* constants
+        * @param array $blacklist List of job types to ignore
+        * @return Job|bool Returns false on failure
+        */
+       public function pop( $qtype = self::TYPE_DEFAULT, $flags = 0, array $blacklist = array() ) {
+               $job = false;
+
+               if ( is_string( $qtype ) ) { // specific job type
+                       if ( !in_array( $qtype, $blacklist ) ) {
+                               $job = $this->get( $qtype )->pop();
+                               if ( !$job ) {
+                                       JobQueueAggregator::singleton()->notifyQueueEmpty( $this->wiki, $qtype );
+                               }
+                       }
+               } else { // any job in the "default" jobs types
+                       if ( $flags & self::USE_CACHE ) {
+                               if ( !$this->cache->has( 'queues-ready', 'list', self::PROC_CACHE_TTL ) ) {
+                                       $this->cache->set( 'queues-ready', 'list', $this->getQueuesWithJobs() );
+                               }
+                               $types = $this->cache->get( 'queues-ready', 'list' );
+                       } else {
+                               $types = $this->getQueuesWithJobs();
+                       }
+
+                       if ( $qtype == self::TYPE_DEFAULT ) {
+                               $types = array_intersect( $types, $this->getDefaultQueueTypes() );
+                       }
+
+                       $types = array_diff( $types, $blacklist ); // avoid selected types
+                       shuffle( $types ); // avoid starvation
+
+                       foreach ( $types as $type ) { // for each queue...
+                               $job = $this->get( $type )->pop();
+                               if ( $job ) { // found
+                                       break;
+                               } else { // not found
+                                       JobQueueAggregator::singleton()->notifyQueueEmpty( $this->wiki, $type );
+                                       $this->cache->clear( 'queues-ready' );
+                               }
+                       }
+               }
+
+               return $job;
+       }
+
+       /**
+        * Acknowledge that a job was completed
+        *
+        * @param Job $job
+        * @return bool
+        */
+       public function ack( Job $job ) {
+               return $this->get( $job->getType() )->ack( $job );
+       }
+
+       /**
+        * Register the "root job" of a given job into the queue for de-duplication.
+        * This should only be called right *after* all the new jobs have been inserted.
+        *
+        * @param Job $job
+        * @return bool
+        */
+       public function deduplicateRootJob( Job $job ) {
+               return $this->get( $job->getType() )->deduplicateRootJob( $job );
+       }
+
+       /**
+        * Wait for any slaves or backup queue servers to catch up.
+        *
+        * This does nothing for certain queue classes.
+        *
+        * @return void
+        * @throws MWException
+        */
+       public function waitForBackups() {
+               global $wgJobTypeConf;
+
+               wfProfileIn( __METHOD__ );
+               // Try to avoid doing this more than once per queue storage medium
+               foreach ( $wgJobTypeConf as $type => $conf ) {
+                       $this->get( $type )->waitForBackups();
+               }
+               wfProfileOut( __METHOD__ );
+       }
+
+       /**
+        * Get the list of queue types
+        *
+        * @return array List of strings
+        */
+       public function getQueueTypes() {
+               return array_keys( $this->getCachedConfigVar( 'wgJobClasses' ) );
+       }
+
+       /**
+        * Get the list of default queue types
+        *
+        * @return array List of strings
+        */
+       public function getDefaultQueueTypes() {
+               global $wgJobTypesExcludedFromDefaultQueue;
+
+               return array_diff( $this->getQueueTypes(), $wgJobTypesExcludedFromDefaultQueue );
+       }
+
+       /**
+        * Get the list of job types that have non-empty queues
+        *
+        * @return array List of job types that have non-empty queues
+        */
+       public function getQueuesWithJobs() {
+               $types = array();
+               foreach ( $this->getCoalescedQueues() as $info ) {
+                       $nonEmpty = $info['queue']->getSiblingQueuesWithJobs( $this->getQueueTypes() );
+                       if ( is_array( $nonEmpty ) ) { // batching features supported
+                               $types = array_merge( $types, $nonEmpty );
+                       } else { // we have to go through the queues in the bucket one-by-one
+                               foreach ( $info['types'] as $type ) {
+                                       if ( !$this->get( $type )->isEmpty() ) {
+                                               $types[] = $type;
+                                       }
+                               }
+                       }
+               }
+
+               return $types;
+       }
+
+       /**
+        * Get the size of the queus for a list of job types
+        *
+        * @return array Map of (job type => size)
+        */
+       public function getQueueSizes() {
+               $sizeMap = array();
+               foreach ( $this->getCoalescedQueues() as $info ) {
+                       $sizes = $info['queue']->getSiblingQueueSizes( $this->getQueueTypes() );
+                       if ( is_array( $sizes ) ) { // batching features supported
+                               $sizeMap = $sizeMap + $sizes;
+                       } else { // we have to go through the queues in the bucket one-by-one
+                               foreach ( $info['types'] as $type ) {
+                                       $sizeMap[$type] = $this->get( $type )->getSize();
+                               }
+                       }
+               }
+
+               return $sizeMap;
+       }
+
+       /**
+        * @return array
+        */
+       protected function getCoalescedQueues() {
+               global $wgJobTypeConf;
+
+               if ( $this->coalescedQueues === null ) {
+                       $this->coalescedQueues = array();
+                       foreach ( $wgJobTypeConf as $type => $conf ) {
+                               $queue = JobQueue::factory(
+                                       array( 'wiki' => $this->wiki, 'type' => 'null' ) + $conf );
+                               $loc = $queue->getCoalesceLocationInternal();
+                               if ( !isset( $this->coalescedQueues[$loc] ) ) {
+                                       $this->coalescedQueues[$loc]['queue'] = $queue;
+                                       $this->coalescedQueues[$loc]['types'] = array();
+                               }
+                               if ( $type === 'default' ) {
+                                       $this->coalescedQueues[$loc]['types'] = array_merge(
+                                               $this->coalescedQueues[$loc]['types'],
+                                               array_diff( $this->getQueueTypes(), array_keys( $wgJobTypeConf ) )
+                                       );
+                               } else {
+                                       $this->coalescedQueues[$loc]['types'][] = $type;
+                               }
+                       }
+               }
+
+               return $this->coalescedQueues;
+       }
+
+       /**
+        * Execute any due periodic queue maintenance tasks for all queues.
+        *
+        * A task is "due" if the time ellapsed since the last run is greater than
+        * the defined run period. Concurrent calls to this function will cause tasks
+        * to be attempted twice, so they may need their own methods of mutual exclusion.
+        *
+        * @return int Number of tasks run
+        */
+       public function executeReadyPeriodicTasks() {
+               global $wgMemc;
+
+               list( $db, $prefix ) = wfSplitWikiID( $this->wiki );
+               $key = wfForeignMemcKey( $db, $prefix, 'jobqueuegroup', 'taskruns', 'v1' );
+               $lastRuns = $wgMemc->get( $key ); // (queue => task => UNIX timestamp)
+
+               $count = 0;
+               $tasksRun = array(); // (queue => task => UNIX timestamp)
+               foreach ( $this->getQueueTypes() as $type ) {
+                       $queue = $this->get( $type );
+                       foreach ( $queue->getPeriodicTasks() as $task => $definition ) {
+                               if ( $definition['period'] <= 0 ) {
+                                       continue; // disabled
+                               } elseif ( !isset( $lastRuns[$type][$task] )
+                                       || $lastRuns[$type][$task] < ( time() - $definition['period'] )
+                               ) {
+                                       try {
+                                               if ( call_user_func( $definition['callback'] ) !== null ) {
+                                                       $tasksRun[$type][$task] = time();
+                                                       ++$count;
+                                               }
+                                       } catch ( JobQueueError $e ) {
+                                               MWExceptionHandler::logException( $e );
+                                       }
+                               }
+                       }
+                       // The tasks may have recycled jobs or release delayed jobs into the queue
+                       if ( isset( $tasksRun[$type] ) && !$queue->isEmpty() ) {
+                               JobQueueAggregator::singleton()->notifyQueueNonEmpty( $this->wiki, $type );
+                       }
+               }
+
+               $wgMemc->merge( $key, function ( $cache, $key, $lastRuns ) use ( $tasksRun ) {
+                       if ( is_array( $lastRuns ) ) {
+                               foreach ( $tasksRun as $type => $tasks ) {
+                                       foreach ( $tasks as $task => $timestamp ) {
+                                               if ( !isset( $lastRuns[$type][$task] )
+                                                       || $timestamp > $lastRuns[$type][$task]
+                                               ) {
+                                                       $lastRuns[$type][$task] = $timestamp;
+                                               }
+                                       }
+                               }
+                       } else {
+                               $lastRuns = $tasksRun;
+                       }
+
+                       return $lastRuns;
+               } );
+
+               return $count;
+       }
+
+       /**
+        * @param $name string
+        * @return mixed
+        */
+       private function getCachedConfigVar( $name ) {
+               global $wgConf, $wgMemc;
+
+               if ( $this->wiki === wfWikiID() ) {
+                       return $GLOBALS[$name]; // common case
+               } else {
+                       list( $db, $prefix ) = wfSplitWikiID( $this->wiki );
+                       $key = wfForeignMemcKey( $db, $prefix, 'configvalue', $name );
+                       $value = $wgMemc->get( $key ); // ('v' => ...) or false
+                       if ( is_array( $value ) ) {
+                               return $value['v'];
+                       } else {
+                               $value = $wgConf->getConfig( $this->wiki, $name );
+                               $wgMemc->set( $key, array( 'v' => $value ), 86400 + mt_rand( 0, 86400 ) );
+
+                               return $value;
+                       }
+               }
+       }
+}
diff --git a/includes/jobqueue/JobQueueRedis.php b/includes/jobqueue/JobQueueRedis.php
new file mode 100644 (file)
index 0000000..c785cb2
--- /dev/null
@@ -0,0 +1,874 @@
+<?php
+/**
+ * Redis-backed job queue code.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @author Aaron Schulz
+ */
+
+/**
+ * Class to handle job queues stored in Redis
+ *
+ * This is faster, less resource intensive, queue that JobQueueDB.
+ * All data for a queue using this class is placed into one redis server.
+ *
+ * There are eight main redis keys used to track jobs:
+ *   - l-unclaimed  : A list of job IDs used for ready unclaimed jobs
+ *   - z-claimed    : A sorted set of (job ID, UNIX timestamp as score) used for job retries
+ *   - z-abandoned  : A sorted set of (job ID, UNIX timestamp as score) used for broken jobs
+ *   - z-delayed    : A sorted set of (job ID, UNIX timestamp as score) used for delayed jobs
+ *   - h-idBySha1   : A hash of (SHA1 => job ID) for unclaimed jobs used for de-duplication
+ *   - h-sha1ById   : A hash of (job ID => SHA1) for unclaimed jobs used for de-duplication
+ *   - h-attempts   : A hash of (job ID => attempt count) used for job claiming/retries
+ *   - h-data       : A hash of (job ID => serialized blobs) for job storage
+ * A job ID can be in only one of z-delayed, l-unclaimed, z-claimed, and z-abandoned.
+ * If an ID appears in any of those lists, it should have a h-data entry for its ID.
+ * If a job has a SHA1 de-duplication value and its ID is in l-unclaimed or z-delayed, then
+ * there should be no other such jobs with that SHA1. Every h-idBySha1 entry has an h-sha1ById
+ * entry and every h-sha1ById must refer to an ID that is l-unclaimed. If a job has its
+ * ID in z-claimed or z-abandoned, then it must also have an h-attempts entry for its ID.
+ *
+ * Additionally, "rootjob:* keys track "root jobs" used for additional de-duplication.
+ * Aside from root job keys, all keys have no expiry, and are only removed when jobs are run.
+ * All the keys are prefixed with the relevant wiki ID information.
+ *
+ * This class requires Redis 2.6 as it makes use Lua scripts for fast atomic operations.
+ * Additionally, it should be noted that redis has different persistence modes, such
+ * as rdb snapshots, journaling, and no persistent. Appropriate configuration should be
+ * made on the servers based on what queues are using it and what tolerance they have.
+ *
+ * @ingroup JobQueue
+ * @ingroup Redis
+ * @since 1.22
+ */
+class JobQueueRedis extends JobQueue {
+       /** @var RedisConnectionPool */
+       protected $redisPool;
+
+       /** @var string Server address */
+       protected $server;
+
+       /** @var string Compression method to use */
+       protected $compression;
+
+       const MAX_AGE_PRUNE = 604800; // integer; seconds a job can live once claimed (7 days)
+
+       /** @var string Key to prefix the queue keys with (used for testing) */
+       protected $key;
+
+       /**
+        * @var null|int maximum seconds between execution of periodic tasks.  Used to speed up
+        * testing but should otherwise be left unset.
+        */
+       protected $maximumPeriodicTaskSeconds;
+
+       /**
+        * @params include:
+        *   - redisConfig : An array of parameters to RedisConnectionPool::__construct().
+        *                   Note that the serializer option is ignored as "none" is always used.
+        *   - redisServer : A hostname/port combination or the absolute path of a UNIX socket.
+        *                   If a hostname is specified but no port, the standard port number
+        *                   6379 will be used. Required.
+        *   - compression : The type of compression to use; one of (none,gzip).
+        *   - maximumPeriodicTaskSeconds : Maximum seconds between check periodic tasks.  Set to
+        *                   force faster execution of periodic tasks for inegration tests that
+        *                   rely on checkDelay.  Without this the integration tests are very very
+        *                   slow.  This really shouldn't be set in production.
+        * @param array $params
+        */
+       public function __construct( array $params ) {
+               parent::__construct( $params );
+               $params['redisConfig']['serializer'] = 'none'; // make it easy to use Lua
+               $this->server = $params['redisServer'];
+               $this->compression = isset( $params['compression'] ) ? $params['compression'] : 'none';
+               $this->redisPool = RedisConnectionPool::singleton( $params['redisConfig'] );
+               $this->maximumPeriodicTaskSeconds = isset( $params['maximumPeriodicTaskSeconds'] ) ?
+                       $params['maximumPeriodicTaskSeconds'] : null;
+       }
+
+       protected function supportedOrders() {
+               return array( 'timestamp', 'fifo' );
+       }
+
+       protected function optimalOrder() {
+               return 'fifo';
+       }
+
+       protected function supportsDelayedJobs() {
+               return true;
+       }
+
+       /**
+        * @see JobQueue::doIsEmpty()
+        * @return bool
+        * @throws MWException
+        */
+       protected function doIsEmpty() {
+               return $this->doGetSize() == 0;
+       }
+
+       /**
+        * @see JobQueue::doGetSize()
+        * @return int
+        * @throws MWException
+        */
+       protected function doGetSize() {
+               $conn = $this->getConnection();
+               try {
+                       return $conn->lSize( $this->getQueueKey( 'l-unclaimed' ) );
+               } catch ( RedisException $e ) {
+                       $this->throwRedisException( $conn, $e );
+               }
+       }
+
+       /**
+        * @see JobQueue::doGetAcquiredCount()
+        * @return int
+        * @throws JobQueueError
+        */
+       protected function doGetAcquiredCount() {
+               if ( $this->claimTTL <= 0 ) {
+                       return 0; // no acknowledgements
+               }
+               $conn = $this->getConnection();
+               try {
+                       $conn->multi( Redis::PIPELINE );
+                       $conn->zSize( $this->getQueueKey( 'z-claimed' ) );
+                       $conn->zSize( $this->getQueueKey( 'z-abandoned' ) );
+
+                       return array_sum( $conn->exec() );
+               } catch ( RedisException $e ) {
+                       $this->throwRedisException( $conn, $e );
+               }
+       }
+
+       /**
+        * @see JobQueue::doGetDelayedCount()
+        * @return int
+        * @throws JobQueueError
+        */
+       protected function doGetDelayedCount() {
+               if ( !$this->checkDelay ) {
+                       return 0; // no delayed jobs
+               }
+               $conn = $this->getConnection();
+               try {
+                       return $conn->zSize( $this->getQueueKey( 'z-delayed' ) );
+               } catch ( RedisException $e ) {
+                       $this->throwRedisException( $conn, $e );
+               }
+       }
+
+       /**
+        * @see JobQueue::doGetAbandonedCount()
+        * @return int
+        * @throws JobQueueError
+        */
+       protected function doGetAbandonedCount() {
+               if ( $this->claimTTL <= 0 ) {
+                       return 0; // no acknowledgements
+               }
+               $conn = $this->getConnection();
+               try {
+                       return $conn->zSize( $this->getQueueKey( 'z-abandoned' ) );
+               } catch ( RedisException $e ) {
+                       $this->throwRedisException( $conn, $e );
+               }
+       }
+
+       /**
+        * @see JobQueue::doBatchPush()
+        * @param array $jobs
+        * @param $flags
+        * @return bool
+        * @throws JobQueueError
+        */
+       protected function doBatchPush( array $jobs, $flags ) {
+               // Convert the jobs into field maps (de-duplicated against each other)
+               $items = array(); // (job ID => job fields map)
+               foreach ( $jobs as $job ) {
+                       $item = $this->getNewJobFields( $job );
+                       if ( strlen( $item['sha1'] ) ) { // hash identifier => de-duplicate
+                               $items[$item['sha1']] = $item;
+                       } else {
+                               $items[$item['uuid']] = $item;
+                       }
+               }
+
+               if ( !count( $items ) ) {
+                       return true; // nothing to do
+               }
+
+               $conn = $this->getConnection();
+               try {
+                       // Actually push the non-duplicate jobs into the queue...
+                       if ( $flags & self::QOS_ATOMIC ) {
+                               $batches = array( $items ); // all or nothing
+                       } else {
+                               $batches = array_chunk( $items, 500 ); // avoid tying up the server
+                       }
+                       $failed = 0;
+                       $pushed = 0;
+                       foreach ( $batches as $itemBatch ) {
+                               $added = $this->pushBlobs( $conn, $itemBatch );
+                               if ( is_int( $added ) ) {
+                                       $pushed += $added;
+                               } else {
+                                       $failed += count( $itemBatch );
+                               }
+                       }
+                       if ( $failed > 0 ) {
+                               wfDebugLog( 'JobQueueRedis', "Could not insert {$failed} {$this->type} job(s)." );
+
+                               return false;
+                       }
+                       JobQueue::incrStats( 'job-insert', $this->type, count( $items ) );
+                       JobQueue::incrStats( 'job-insert-duplicate', $this->type,
+                               count( $items ) - $failed - $pushed );
+               } catch ( RedisException $e ) {
+                       $this->throwRedisException( $conn, $e );
+               }
+
+               return true;
+       }
+
+       /**
+        * @param RedisConnRef $conn
+        * @param array $items List of results from JobQueueRedis::getNewJobFields()
+        * @return int Number of jobs inserted (duplicates are ignored)
+        * @throws RedisException
+        */
+       protected function pushBlobs( RedisConnRef $conn, array $items ) {
+               $args = array(); // ([id, sha1, rtime, blob [, id, sha1, rtime, blob ... ] ] )
+               foreach ( $items as $item ) {
+                       $args[] = (string)$item['uuid'];
+                       $args[] = (string)$item['sha1'];
+                       $args[] = (string)$item['rtimestamp'];
+                       $args[] = (string)$this->serialize( $item );
+               }
+               static $script =
+<<<LUA
+               local kUnclaimed, kSha1ById, kIdBySha1, kDelayed, kData = unpack(KEYS)
+               if #ARGV % 4 ~= 0 then return redis.error_reply('Unmatched arguments') end
+               local pushed = 0
+               for i = 1,#ARGV,4 do
+                       local id,sha1,rtimestamp,blob = ARGV[i],ARGV[i+1],ARGV[i+2],ARGV[i+3]
+                       if sha1 == '' or redis.call('hExists',kIdBySha1,sha1) == 0 then
+                               if 1*rtimestamp > 0 then
+                                       -- Insert into delayed queue (release time as score)
+                                       redis.call('zAdd',kDelayed,rtimestamp,id)
+                               else
+                                       -- Insert into unclaimed queue
+                                       redis.call('lPush',kUnclaimed,id)
+                               end
+                               if sha1 ~= '' then
+                                       redis.call('hSet',kSha1ById,id,sha1)
+                                       redis.call('hSet',kIdBySha1,sha1,id)
+                               end
+                               redis.call('hSet',kData,id,blob)
+                               pushed = pushed + 1
+                       end
+               end
+               return pushed
+LUA;
+               return $conn->luaEval( $script,
+                       array_merge(
+                               array(
+                                       $this->getQueueKey( 'l-unclaimed' ), # KEYS[1]
+                                       $this->getQueueKey( 'h-sha1ById' ), # KEYS[2]
+                                       $this->getQueueKey( 'h-idBySha1' ), # KEYS[3]
+                                       $this->getQueueKey( 'z-delayed' ), # KEYS[4]
+                                       $this->getQueueKey( 'h-data' ), # KEYS[5]
+                               ),
+                               $args
+                       ),
+                       5 # number of first argument(s) that are keys
+               );
+       }
+
+       /**
+        * @see JobQueue::doPop()
+        * @return Job|bool
+        * @throws JobQueueError
+        */
+       protected function doPop() {
+               $job = false;
+
+               // Push ready delayed jobs into the queue every 10 jobs to spread the load.
+               // This is also done as a periodic task, but we don't want too much done at once.
+               if ( $this->checkDelay && mt_rand( 0, 9 ) == 0 ) {
+                       $this->recyclePruneAndUndelayJobs();
+               }
+
+               $conn = $this->getConnection();
+               try {
+                       do {
+                               if ( $this->claimTTL > 0 ) {
+                                       // Keep the claimed job list down for high-traffic queues
+                                       if ( mt_rand( 0, 99 ) == 0 ) {
+                                               $this->recyclePruneAndUndelayJobs();
+                                       }
+                                       $blob = $this->popAndAcquireBlob( $conn );
+                               } else {
+                                       $blob = $this->popAndDeleteBlob( $conn );
+                               }
+                               if ( $blob === false ) {
+                                       break; // no jobs; nothing to do
+                               }
+
+                               JobQueue::incrStats( 'job-pop', $this->type );
+                               $item = $this->unserialize( $blob );
+                               if ( $item === false ) {
+                                       wfDebugLog( 'JobQueueRedis', "Could not unserialize {$this->type} job." );
+                                       continue;
+                               }
+
+                               // If $item is invalid, recyclePruneAndUndelayJobs() will cleanup as needed
+                               $job = $this->getJobFromFields( $item ); // may be false
+                       } while ( !$job ); // job may be false if invalid
+               } catch ( RedisException $e ) {
+                       $this->throwRedisException( $conn, $e );
+               }
+
+               return $job;
+       }
+
+       /**
+        * @param RedisConnRef $conn
+        * @return array serialized string or false
+        * @throws RedisException
+        */
+       protected function popAndDeleteBlob( RedisConnRef $conn ) {
+               static $script =
+<<<LUA
+               local kUnclaimed, kSha1ById, kIdBySha1, kData = unpack(KEYS)
+               -- Pop an item off the queue
+               local id = redis.call('rpop',kUnclaimed)
+               if not id then return false end
+               -- Get the job data and remove it
+               local item = redis.call('hGet',kData,id)
+               redis.call('hDel',kData,id)
+               -- Allow new duplicates of this job
+               local sha1 = redis.call('hGet',kSha1ById,id)
+               if sha1 then redis.call('hDel',kIdBySha1,sha1) end
+               redis.call('hDel',kSha1ById,id)
+               -- Return the job data
+               return item
+LUA;
+               return $conn->luaEval( $script,
+                       array(
+                               $this->getQueueKey( 'l-unclaimed' ), # KEYS[1]
+                               $this->getQueueKey( 'h-sha1ById' ), # KEYS[2]
+                               $this->getQueueKey( 'h-idBySha1' ), # KEYS[3]
+                               $this->getQueueKey( 'h-data' ), # KEYS[4]
+                       ),
+                       4 # number of first argument(s) that are keys
+               );
+       }
+
+       /**
+        * @param RedisConnRef $conn
+        * @return array serialized string or false
+        * @throws RedisException
+        */
+       protected function popAndAcquireBlob( RedisConnRef $conn ) {
+               static $script =
+<<<LUA
+               local kUnclaimed, kSha1ById, kIdBySha1, kClaimed, kAttempts, kData = unpack(KEYS)
+               -- Pop an item off the queue
+               local id = redis.call('rPop',kUnclaimed)
+               if not id then return false end
+               -- Allow new duplicates of this job
+               local sha1 = redis.call('hGet',kSha1ById,id)
+               if sha1 then redis.call('hDel',kIdBySha1,sha1) end
+               redis.call('hDel',kSha1ById,id)
+               -- Mark the jobs as claimed and return it
+               redis.call('zAdd',kClaimed,ARGV[1],id)
+               redis.call('hIncrBy',kAttempts,id,1)
+               return redis.call('hGet',kData,id)
+LUA;
+               return $conn->luaEval( $script,
+                       array(
+                               $this->getQueueKey( 'l-unclaimed' ), # KEYS[1]
+                               $this->getQueueKey( 'h-sha1ById' ), # KEYS[2]
+                               $this->getQueueKey( 'h-idBySha1' ), # KEYS[3]
+                               $this->getQueueKey( 'z-claimed' ), # KEYS[4]
+                               $this->getQueueKey( 'h-attempts' ), # KEYS[5]
+                               $this->getQueueKey( 'h-data' ), # KEYS[6]
+                               time(), # ARGV[1] (injected to be replication-safe)
+                       ),
+                       6 # number of first argument(s) that are keys
+               );
+       }
+
+       /**
+        * @see JobQueue::doAck()
+        * @param Job $job
+        * @return Job|bool
+        * @throws MWException|JobQueueError
+        */
+       protected function doAck( Job $job ) {
+               if ( !isset( $job->metadata['uuid'] ) ) {
+                       throw new MWException( "Job of type '{$job->getType()}' has no UUID." );
+               }
+               if ( $this->claimTTL > 0 ) {
+                       $conn = $this->getConnection();
+                       try {
+                               static $script =
+<<<LUA
+                               local kClaimed, kAttempts, kData = unpack(KEYS)
+                               -- Unmark the job as claimed
+                               redis.call('zRem',kClaimed,ARGV[1])
+                               redis.call('hDel',kAttempts,ARGV[1])
+                               -- Delete the job data itself
+                               return redis.call('hDel',kData,ARGV[1])
+LUA;
+                               $res = $conn->luaEval( $script,
+                                       array(
+                                               $this->getQueueKey( 'z-claimed' ), # KEYS[1]
+                                               $this->getQueueKey( 'h-attempts' ), # KEYS[2]
+                                               $this->getQueueKey( 'h-data' ), # KEYS[3]
+                                               $job->metadata['uuid'] # ARGV[1]
+                                       ),
+                                       3 # number of first argument(s) that are keys
+                               );
+
+                               if ( !$res ) {
+                                       wfDebugLog( 'JobQueueRedis', "Could not acknowledge {$this->type} job." );
+
+                                       return false;
+                               }
+                       } catch ( RedisException $e ) {
+                               $this->throwRedisException( $conn, $e );
+                       }
+               }
+
+               return true;
+       }
+
+       /**
+        * @see JobQueue::doDeduplicateRootJob()
+        * @param Job $job
+        * @return bool
+        * @throws MWException|JobQueueError
+        */
+       protected function doDeduplicateRootJob( Job $job ) {
+               if ( !$job->hasRootJobParams() ) {
+                       throw new MWException( "Cannot register root job; missing parameters." );
+               }
+               $params = $job->getRootJobParams();
+
+               $key = $this->getRootJobCacheKey( $params['rootJobSignature'] );
+
+               $conn = $this->getConnection();
+               try {
+                       $timestamp = $conn->get( $key ); // current last timestamp of this job
+                       if ( $timestamp && $timestamp >= $params['rootJobTimestamp'] ) {
+                               return true; // a newer version of this root job was enqueued
+                       }
+
+                       // Update the timestamp of the last root job started at the location...
+                       return $conn->set( $key, $params['rootJobTimestamp'], self::ROOTJOB_TTL ); // 2 weeks
+               } catch ( RedisException $e ) {
+                       $this->throwRedisException( $conn, $e );
+               }
+       }
+
+       /**
+        * @see JobQueue::doIsRootJobOldDuplicate()
+        * @param Job $job
+        * @return bool
+        * @throws JobQueueError
+        */
+       protected function doIsRootJobOldDuplicate( Job $job ) {
+               if ( !$job->hasRootJobParams() ) {
+                       return false; // job has no de-deplication info
+               }
+               $params = $job->getRootJobParams();
+
+               $conn = $this->getConnection();
+               try {
+                       // Get the last time this root job was enqueued
+                       $timestamp = $conn->get( $this->getRootJobCacheKey( $params['rootJobSignature'] ) );
+               } catch ( RedisException $e ) {
+                       $this->throwRedisException( $conn, $e );
+               }
+
+               // Check if a new root job was started at the location after this one's...
+               return ( $timestamp && $timestamp > $params['rootJobTimestamp'] );
+       }
+
+       /**
+        * @see JobQueue::doDelete()
+        * @return bool
+        * @throws JobQueueError
+        */
+       protected function doDelete() {
+               static $props = array( 'l-unclaimed', 'z-claimed', 'z-abandoned',
+                       'z-delayed', 'h-idBySha1', 'h-sha1ById', 'h-attempts', 'h-data' );
+
+               $conn = $this->getConnection();
+               try {
+                       $keys = array();
+                       foreach ( $props as $prop ) {
+                               $keys[] = $this->getQueueKey( $prop );
+                       }
+
+                       return ( $conn->delete( $keys ) !== false );
+               } catch ( RedisException $e ) {
+                       $this->throwRedisException( $conn, $e );
+               }
+       }
+
+       /**
+        * @see JobQueue::getAllQueuedJobs()
+        * @return Iterator
+        */
+       public function getAllQueuedJobs() {
+               $conn = $this->getConnection();
+               try {
+                       $that = $this;
+
+                       return new MappedIterator(
+                               $conn->lRange( $this->getQueueKey( 'l-unclaimed' ), 0, -1 ),
+                               function ( $uid ) use ( $that, $conn ) {
+                                       return $that->getJobFromUidInternal( $uid, $conn );
+                               },
+                               array( 'accept' => function ( $job ) {
+                                       return is_object( $job );
+                               } )
+                       );
+               } catch ( RedisException $e ) {
+                       $this->throwRedisException( $conn, $e );
+               }
+       }
+
+       /**
+        * @see JobQueue::getAllQueuedJobs()
+        * @return Iterator
+        */
+       public function getAllDelayedJobs() {
+               $conn = $this->getConnection();
+               try {
+                       $that = $this;
+
+                       return new MappedIterator( // delayed jobs
+                               $conn->zRange( $this->getQueueKey( 'z-delayed' ), 0, -1 ),
+                               function ( $uid ) use ( $that, $conn ) {
+                                       return $that->getJobFromUidInternal( $uid, $conn );
+                               },
+                               array( 'accept' => function ( $job ) {
+                                       return is_object( $job );
+                               } )
+                       );
+               } catch ( RedisException $e ) {
+                       $this->throwRedisException( $conn, $e );
+               }
+       }
+
+       public function getCoalesceLocationInternal() {
+               return "RedisServer:" . $this->server;
+       }
+
+       protected function doGetSiblingQueuesWithJobs( array $types ) {
+               return array_keys( array_filter( $this->doGetSiblingQueueSizes( $types ) ) );
+       }
+
+       protected function doGetSiblingQueueSizes( array $types ) {
+               $sizes = array(); // (type => size)
+               $types = array_values( $types ); // reindex
+               $conn = $this->getConnection();
+               try {
+                       $conn->multi( Redis::PIPELINE );
+                       foreach ( $types as $type ) {
+                               $conn->lSize( $this->getQueueKey( 'l-unclaimed', $type ) );
+                       }
+                       $res = $conn->exec();
+                       if ( is_array( $res ) ) {
+                               foreach ( $res as $i => $size ) {
+                                       $sizes[$types[$i]] = $size;
+                               }
+                       }
+               } catch ( RedisException $e ) {
+                       $this->throwRedisException( $conn, $e );
+               }
+
+               return $sizes;
+       }
+
+       /**
+        * This function should not be called outside JobQueueRedis
+        *
+        * @param $uid string
+        * @param $conn RedisConnRef
+        * @return Job|bool Returns false if the job does not exist
+        * @throws MWException|JobQueueError
+        */
+       public function getJobFromUidInternal( $uid, RedisConnRef $conn ) {
+               try {
+                       $data = $conn->hGet( $this->getQueueKey( 'h-data' ), $uid );
+                       if ( $data === false ) {
+                               return false; // not found
+                       }
+                       $item = $this->unserialize( $conn->hGet( $this->getQueueKey( 'h-data' ), $uid ) );
+                       if ( !is_array( $item ) ) { // this shouldn't happen
+                               throw new MWException( "Could not find job with ID '$uid'." );
+                       }
+                       $title = Title::makeTitle( $item['namespace'], $item['title'] );
+                       $job = Job::factory( $item['type'], $title, $item['params'] );
+                       $job->metadata['uuid'] = $item['uuid'];
+
+                       return $job;
+               } catch ( RedisException $e ) {
+                       $this->throwRedisException( $conn, $e );
+               }
+       }
+
+       /**
+        * Recycle or destroy any jobs that have been claimed for too long
+        * and release any ready delayed jobs into the queue
+        *
+        * @return int Number of jobs recycled/deleted/undelayed
+        * @throws MWException|JobQueueError
+        */
+       public function recyclePruneAndUndelayJobs() {
+               $count = 0;
+               // For each job item that can be retried, we need to add it back to the
+               // main queue and remove it from the list of currenty claimed job items.
+               // For those that cannot, they are marked as dead and kept around for
+               // investigation and manual job restoration but are eventually deleted.
+               $conn = $this->getConnection();
+               try {
+                       $now = time();
+                       static $script =
+<<<LUA
+                       local kClaimed, kAttempts, kUnclaimed, kData, kAbandoned, kDelayed = unpack(KEYS)
+                       local released,abandoned,pruned,undelayed = 0,0,0,0
+                       -- Get all non-dead jobs that have an expired claim on them.
+                       -- The score for each item is the last claim timestamp (UNIX).
+                       local staleClaims = redis.call('zRangeByScore',kClaimed,0,ARGV[1])
+                       for k,id in ipairs(staleClaims) do
+                               local timestamp = redis.call('zScore',kClaimed,id)
+                               local attempts = redis.call('hGet',kAttempts,id)
+                               if attempts < ARGV[3] then
+                                       -- Claim expired and retries left: re-enqueue the job
+                                       redis.call('lPush',kUnclaimed,id)
+                                       redis.call('hIncrBy',kAttempts,id,1)
+                                       released = released + 1
+                               else
+                                       -- Claim expired and no retries left: mark the job as dead
+                                       redis.call('zAdd',kAbandoned,timestamp,id)
+                                       abandoned = abandoned + 1
+                               end
+                               redis.call('zRem',kClaimed,id)
+                       end
+                       -- Get all of the dead jobs that have been marked as dead for too long.
+                       -- The score for each item is the last claim timestamp (UNIX).
+                       local deadClaims = redis.call('zRangeByScore',kAbandoned,0,ARGV[2])
+                       for k,id in ipairs(deadClaims) do
+                               -- Stale and out of retries: remove any traces of the job
+                               redis.call('zRem',kAbandoned,id)
+                               redis.call('hDel',kAttempts,id)
+                               redis.call('hDel',kData,id)
+                               pruned = pruned + 1
+                       end
+                       -- Get the list of ready delayed jobs, sorted by readiness (UNIX timestamp)
+                       local ids = redis.call('zRangeByScore',kDelayed,0,ARGV[4])
+                       -- Migrate the jobs from the "delayed" set to the "unclaimed" list
+                       for k,id in ipairs(ids) do
+                               redis.call('lPush',kUnclaimed,id)
+                               redis.call('zRem',kDelayed,id)
+                       end
+                       undelayed = #ids
+                       return {released,abandoned,pruned,undelayed}
+LUA;
+                       $res = $conn->luaEval( $script,
+                               array(
+                                       $this->getQueueKey( 'z-claimed' ), # KEYS[1]
+                                       $this->getQueueKey( 'h-attempts' ), # KEYS[2]
+                                       $this->getQueueKey( 'l-unclaimed' ), # KEYS[3]
+                                       $this->getQueueKey( 'h-data' ), # KEYS[4]
+                                       $this->getQueueKey( 'z-abandoned' ), # KEYS[5]
+                                       $this->getQueueKey( 'z-delayed' ), # KEYS[6]
+                                       $now - $this->claimTTL, # ARGV[1]
+                                       $now - self::MAX_AGE_PRUNE, # ARGV[2]
+                                       $this->maxTries, # ARGV[3]
+                                       $now # ARGV[4]
+                               ),
+                               6 # number of first argument(s) that are keys
+                       );
+                       if ( $res ) {
+                               list( $released, $abandoned, $pruned, $undelayed ) = $res;
+                               $count += $released + $pruned + $undelayed;
+                               JobQueue::incrStats( 'job-recycle', $this->type, $released );
+                               JobQueue::incrStats( 'job-abandon', $this->type, $abandoned );
+                       }
+               } catch ( RedisException $e ) {
+                       $this->throwRedisException( $conn, $e );
+               }
+
+               return $count;
+       }
+
+       /**
+        * @return array
+        */
+       protected function doGetPeriodicTasks() {
+               $periods = array( 3600 ); // standard cleanup (useful on config change)
+               if ( $this->claimTTL > 0 ) {
+                       $periods[] = ceil( $this->claimTTL / 2 ); // avoid bad timing
+               }
+               if ( $this->checkDelay ) {
+                       $periods[] = 300; // 5 minutes
+               }
+               $period = min( $periods );
+               $period = max( $period, 30 ); // sanity
+               // Support override for faster testing
+               if ( $this->maximumPeriodicTaskSeconds !== null ) {
+                       $period = min( $period, $this->maximumPeriodicTaskSeconds );
+               }
+               return array(
+                       'recyclePruneAndUndelayJobs' => array(
+                               'callback' => array( $this, 'recyclePruneAndUndelayJobs' ),
+                               'period'   => $period,
+                       )
+               );
+       }
+
+       /**
+        * @param IJobSpecification $job
+        * @return array
+        */
+       protected function getNewJobFields( IJobSpecification $job ) {
+               return array(
+                       // Fields that describe the nature of the job
+                       'type' => $job->getType(),
+                       'namespace' => $job->getTitle()->getNamespace(),
+                       'title' => $job->getTitle()->getDBkey(),
+                       'params' => $job->getParams(),
+                       // Some jobs cannot run until a "release timestamp"
+                       'rtimestamp' => $job->getReleaseTimestamp() ?: 0,
+                       // Additional job metadata
+                       'uuid' => UIDGenerator::newRawUUIDv4( UIDGenerator::QUICK_RAND ),
+                       'sha1' => $job->ignoreDuplicates()
+                               ? wfBaseConvert( sha1( serialize( $job->getDeduplicationInfo() ) ), 16, 36, 31 )
+                               : '',
+                       'timestamp' => time() // UNIX timestamp
+               );
+       }
+
+       /**
+        * @param $fields array
+        * @return Job|bool
+        */
+       protected function getJobFromFields( array $fields ) {
+               $title = Title::makeTitleSafe( $fields['namespace'], $fields['title'] );
+               if ( $title ) {
+                       $job = Job::factory( $fields['type'], $title, $fields['params'] );
+                       $job->metadata['uuid'] = $fields['uuid'];
+
+                       return $job;
+               }
+
+               return false;
+       }
+
+       /**
+        * @param array $fields
+        * @return string Serialized and possibly compressed version of $fields
+        */
+       protected function serialize( array $fields ) {
+               $blob = serialize( $fields );
+               if ( $this->compression === 'gzip'
+                       && strlen( $blob ) >= 1024
+                       && function_exists( 'gzdeflate' )
+               ) {
+                       $object = (object)array( 'blob' => gzdeflate( $blob ), 'enc' => 'gzip' );
+                       $blobz = serialize( $object );
+
+                       return ( strlen( $blobz ) < strlen( $blob ) ) ? $blobz : $blob;
+               } else {
+                       return $blob;
+               }
+       }
+
+       /**
+        * @param string $blob
+        * @return array|bool Unserialized version of $blob or false
+        */
+       protected function unserialize( $blob ) {
+               $fields = unserialize( $blob );
+               if ( is_object( $fields ) ) {
+                       if ( $fields->enc === 'gzip' && function_exists( 'gzinflate' ) ) {
+                               $fields = unserialize( gzinflate( $fields->blob ) );
+                       } else {
+                               $fields = false;
+                       }
+               }
+
+               return is_array( $fields ) ? $fields : false;
+       }
+
+       /**
+        * Get a connection to the server that handles all sub-queues for this queue
+        *
+        * @return RedisConnRef
+        * @throws JobQueueConnectionError
+        */
+       protected function getConnection() {
+               $conn = $this->redisPool->getConnection( $this->server );
+               if ( !$conn ) {
+                       throw new JobQueueConnectionError( "Unable to connect to redis server." );
+               }
+
+               return $conn;
+       }
+
+       /**
+        * @param $conn RedisConnRef
+        * @param $e RedisException
+        * @throws JobQueueError
+        */
+       protected function throwRedisException( RedisConnRef $conn, $e ) {
+               $this->redisPool->handleError( $conn, $e );
+               throw new JobQueueError( "Redis server error: {$e->getMessage()}\n" );
+       }
+
+       /**
+        * @param $prop string
+        * @param $type string|null
+        * @return string
+        */
+       private function getQueueKey( $prop, $type = null ) {
+               $type = is_string( $type ) ? $type : $this->type;
+               list( $db, $prefix ) = wfSplitWikiID( $this->wiki );
+               if ( strlen( $this->key ) ) { // namespaced queue (for testing)
+                       return wfForeignMemcKey( $db, $prefix, 'jobqueue', $type, $this->key, $prop );
+               } else {
+                       return wfForeignMemcKey( $db, $prefix, 'jobqueue', $type, $prop );
+               }
+       }
+
+       /**
+        * @param $key string
+        * @return void
+        */
+       public function setTestingPrefix( $key ) {
+               $this->key = $key;
+       }
+}
diff --git a/includes/jobqueue/JobSpecification.php b/includes/jobqueue/JobSpecification.php
new file mode 100644 (file)
index 0000000..e074e5c
--- /dev/null
@@ -0,0 +1,189 @@
+<?php
+/**
+ * Job queue task description base code.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup JobQueue
+ */
+
+/**
+ * Job queue task description interface
+ *
+ * @ingroup JobQueue
+ * @since 1.23
+ */
+interface IJobSpecification {
+       /**
+        * @return string Job type
+        */
+       public function getType();
+
+       /**
+        * @return array
+        */
+       public function getParams();
+
+       /**
+        * @return int|null UNIX timestamp to delay running this job until, otherwise null
+        */
+       public function getReleaseTimestamp();
+
+       /**
+        * @return bool Whether only one of each identical set of jobs should be run
+        */
+       public function ignoreDuplicates();
+
+       /**
+        * Subclasses may need to override this to make duplication detection work.
+        * The resulting map conveys everything that makes the job unique. This is
+        * only checked if ignoreDuplicates() returns true, meaning that duplicate
+        * jobs are supposed to be ignored.
+        *
+        * @return array Map of key/values
+        */
+       public function getDeduplicationInfo();
+
+       /**
+        * @return Title Descriptive title (this can simply be informative)
+        */
+       public function getTitle();
+}
+
+/**
+ * Job queue task description base code
+ *
+ * Example usage:
+ * <code>
+ * $job = new JobSpecification(
+ *             'null',
+ *             array( 'lives' => 1, 'usleep' => 100, 'pi' => 3.141569 ),
+ *             array( 'removeDuplicates' => 1 ),
+ *             Title::makeTitle( NS_SPECIAL, 'nullity' )
+ * );
+ * JobQueueGroup::singleton()->push( $job )
+ * </code>
+ *
+ * @ingroup JobQueue
+ * @since 1.23
+ */
+class JobSpecification implements IJobSpecification {
+       /** @var string */
+       protected $type;
+
+       /** @var array Array of job parameters or false if none */
+       protected $params;
+
+       /** @var Title */
+       protected $title;
+
+       /** @var bool Expensive jobs may set this to true */
+       protected $ignoreDuplicates;
+
+       /**
+        * @param string $type
+        * @param array $params Map of key/values
+        * @param array $opts Map of key/values
+        * @param Title $title Optional descriptive title
+        */
+       public function __construct(
+               $type, array $params, array $opts = array(), Title $title = null
+       ) {
+               $this->validateParams( $params );
+
+               $this->type = $type;
+               $this->params = $params;
+               $this->title = $title ?: Title::newMainPage();
+               $this->ignoreDuplicates = !empty( $opts['removeDuplicates'] );
+       }
+
+       /**
+        * @param array $params
+        */
+       protected function validateParams( array $params ) {
+               foreach ( $params as $p => $v ) {
+                       if ( is_array( $v ) ) {
+                               $this->validateParams( $v );
+                       } elseif ( !is_scalar( $v ) && $v !== null ) {
+                               throw new UnexpectedValueException( 'Job parameters are not JSON serializable.' );
+                       }
+               }
+       }
+
+       /**
+        * @return string
+        */
+       public function getType() {
+               return $this->type;
+       }
+
+       /**
+        * @return Title
+        */
+       public function getTitle() {
+               return $this->title;
+       }
+
+       /**
+        * @return array
+        */
+       public function getParams() {
+               return $this->params;
+       }
+
+       /**
+        * @return int|null UNIX timestamp to delay running this job until, otherwise null
+        */
+       public function getReleaseTimestamp() {
+               return isset( $this->params['jobReleaseTimestamp'] )
+                       ? wfTimestampOrNull( TS_UNIX, $this->params['jobReleaseTimestamp'] )
+                       : null;
+       }
+
+       /**
+        * @return bool Whether only one of each identical set of jobs should be run
+        */
+       public function ignoreDuplicates() {
+               return $this->ignoreDuplicates;
+       }
+
+       /**
+        * Subclasses may need to override this to make duplication detection work.
+        * The resulting map conveys everything that makes the job unique. This is
+        * only checked if ignoreDuplicates() returns true, meaning that duplicate
+        * jobs are supposed to be ignored.
+        *
+        * @return array Map of key/values
+        */
+       public function getDeduplicationInfo() {
+               $info = array(
+                       'type' => $this->getType(),
+                       'namespace' => $this->getTitle()->getNamespace(),
+                       'title' => $this->getTitle()->getDBkey(),
+                       'params' => $this->getParams()
+               );
+               if ( is_array( $info['params'] ) ) {
+                       // Identical jobs with different "root" jobs should count as duplicates
+                       unset( $info['params']['rootJobSignature'] );
+                       unset( $info['params']['rootJobTimestamp'] );
+                       // Likewise for jobs with different delay times
+                       unset( $info['params']['jobReleaseTimestamp'] );
+               }
+
+               return $info;
+       }
+}
diff --git a/includes/jobqueue/README b/includes/jobqueue/README
new file mode 100644 (file)
index 0000000..c11d5a7
--- /dev/null
@@ -0,0 +1,81 @@
+/*!
+\ingroup JobQueue
+\page jobqueue_design Job queue design
+
+Notes on the Job queuing system architecture.
+
+\section intro Introduction
+
+The data model consist of the following main components:
+* The Job object represents a particular deferred task that happens in the
+  background. All jobs subclass the Job object and put the main logic in the
+  function called run().
+* The JobQueue object represents a particular queue of jobs of a certain type.
+  For example there may be a queue for email jobs and a queue for squid purge
+  jobs.
+
+\section jobqueue Job queues
+
+Each job type has its own queue and is associated to a storage medium. One
+queue might save its jobs in redis while another one uses would use a database.
+
+Storage medium are defined in a queue class. Before using it, you must
+define in $wgJobTypeConf a mapping of the job type to a queue class.
+
+The factory class JobQueueGroup provides helper functions:
+- getting the queue for a given job
+- route new job insertions to the proper queue
+
+The following queue classes are available:
+* JobQueueDB (stores jobs in the `job` table in a database)
+* JobQueueRedis (stores jobs in a redis server)
+
+All queue classes support some basic operations (though some may be no-ops):
+* enqueueing a batch of jobs
+* dequeueing a single job
+* acknowledging a job is completed
+* checking if the queue is empty
+
+Some queue classes (like JobQueueDB) may dequeue jobs in random order while other
+queues might dequeue jobs in exact FIFO order. Callers should thus not assume jobs
+are executed in FIFO order.
+
+Also note that not all queue classes will have the same reliability guarantees.
+In-memory queues may lose data when restarted depending on snapshot and journal
+settings (including journal fsync() frequency).  Some queue types may totally remove
+jobs when dequeued while leaving the ack() function as a no-op; if a job is
+dequeued by a job runner, which crashes before completion, the job will be
+lost. Some jobs, like purging squid caches after a template change, may not
+require durable queues, whereas other jobs might be more important.
+
+\section aggregator Job queue aggregator
+
+The aggregators are used by nextJobDB.php, which is a script that will return a
+random ready queue (on any wiki in the farm) that can be used with runJobs.php.
+This can be used in conjunction with any scripts that handle wiki farm job queues.
+Note that $wgLocalDatabases defines what wikis are in the wiki farm.
+
+Since each job type has its own queue, and wiki-farms may have many wikis,
+there might be a large number of queues to keep track of. To avoid wasting
+large amounts of time polling empty queues, aggregators exists to keep track
+of which queues are ready.
+
+The following queue aggregator classes are available:
+* JobQueueAggregatorMemc (uses $wgMemc to track ready queues)
+* JobQueueAggregatorRedis (uses a redis server to track ready queues)
+
+Some aggregators cache data for a few minutes while others may be always up to date.
+This can be an important factor for jobs that need a low pickup time (or latency).
+
+\section jobs Jobs
+
+Callers should also try to make jobs maintain correctness when executed twice.
+This is useful for queues that actually implement ack(), since they may recycle
+dequeued but un-acknowledged jobs back into the queue to be attempted again. If
+a runner dequeues a job, runs it, but then crashes before calling ack(), the
+job may be returned to the queue and run a second time. Jobs like cache purging can
+happen several times without any correctness problems. However, a pathological case
+would be if a bug causes the problem to systematically keep repeating. For example,
+a job may always throw a DB error at the end of run(). This problem is trickier to
+solve and more obnoxious for things like email jobs, for example. For such jobs,
+it might be useful to use a queue that does not retry jobs.
diff --git a/includes/jobqueue/aggregator/JobQueueAggregator.php b/includes/jobqueue/aggregator/JobQueueAggregator.php
new file mode 100644 (file)
index 0000000..8600eed
--- /dev/null
@@ -0,0 +1,162 @@
+<?php
+/**
+ * Job queue aggregator code.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @author Aaron Schulz
+ */
+
+/**
+ * Class to handle tracking information about all queues
+ *
+ * @ingroup JobQueue
+ * @since 1.21
+ */
+abstract class JobQueueAggregator {
+       /** @var JobQueueAggregator */
+       protected static $instance = null;
+
+       /**
+        * @param array $params
+        */
+       protected function __construct( array $params ) {
+       }
+
+       /**
+        * @throws MWException
+        * @return JobQueueAggregator
+        */
+       final public static function singleton() {
+               global $wgJobQueueAggregator;
+
+               if ( !isset( self::$instance ) ) {
+                       $class = $wgJobQueueAggregator['class'];
+                       $obj = new $class( $wgJobQueueAggregator );
+                       if ( !( $obj instanceof JobQueueAggregator ) ) {
+                               throw new MWException( "Class '$class' is not a JobQueueAggregator class." );
+                       }
+                       self::$instance = $obj;
+               }
+
+               return self::$instance;
+       }
+
+       /**
+        * Destroy the singleton instance
+        *
+        * @return void
+        */
+       final public static function destroySingleton() {
+               self::$instance = null;
+       }
+
+       /**
+        * Mark a queue as being empty
+        *
+        * @param string $wiki
+        * @param string $type
+        * @return bool Success
+        */
+       final public function notifyQueueEmpty( $wiki, $type ) {
+               wfProfileIn( __METHOD__ );
+               $ok = $this->doNotifyQueueEmpty( $wiki, $type );
+               wfProfileOut( __METHOD__ );
+
+               return $ok;
+       }
+
+       /**
+        * @see JobQueueAggregator::notifyQueueEmpty()
+        */
+       abstract protected function doNotifyQueueEmpty( $wiki, $type );
+
+       /**
+        * Mark a queue as being non-empty
+        *
+        * @param string $wiki
+        * @param string $type
+        * @return bool Success
+        */
+       final public function notifyQueueNonEmpty( $wiki, $type ) {
+               wfProfileIn( __METHOD__ );
+               $ok = $this->doNotifyQueueNonEmpty( $wiki, $type );
+               wfProfileOut( __METHOD__ );
+
+               return $ok;
+       }
+
+       /**
+        * @see JobQueueAggregator::notifyQueueNonEmpty()
+        */
+       abstract protected function doNotifyQueueNonEmpty( $wiki, $type );
+
+       /**
+        * Get the list of all of the queues with jobs
+        *
+        * @return array (job type => (list of wiki IDs))
+        */
+       final public function getAllReadyWikiQueues() {
+               wfProfileIn( __METHOD__ );
+               $res = $this->doGetAllReadyWikiQueues();
+               wfProfileOut( __METHOD__ );
+
+               return $res;
+       }
+
+       /**
+        * @see JobQueueAggregator::getAllReadyWikiQueues()
+        */
+       abstract protected function doGetAllReadyWikiQueues();
+
+       /**
+        * Purge all of the aggregator information
+        *
+        * @return bool Success
+        */
+       final public function purge() {
+               wfProfileIn( __METHOD__ );
+               $res = $this->doPurge();
+               wfProfileOut( __METHOD__ );
+
+               return $res;
+       }
+
+       /**
+        * @see JobQueueAggregator::purge()
+        */
+       abstract protected function doPurge();
+
+       /**
+        * Get all databases that have a pending job.
+        * This poll all the queues and is this expensive.
+        *
+        * @return array (job type => (list of wiki IDs))
+        */
+       protected function findPendingWikiQueues() {
+               global $wgLocalDatabases;
+
+               $pendingDBs = array(); // (job type => (db list))
+               foreach ( $wgLocalDatabases as $db ) {
+                       foreach ( JobQueueGroup::singleton( $db )->getQueuesWithJobs() as $type ) {
+                               $pendingDBs[$type][] = $db;
+                       }
+               }
+
+               return $pendingDBs;
+       }
+}
diff --git a/includes/jobqueue/aggregator/JobQueueAggregatorMemc.php b/includes/jobqueue/aggregator/JobQueueAggregatorMemc.php
new file mode 100644 (file)
index 0000000..d733a42
--- /dev/null
@@ -0,0 +1,126 @@
+<?php
+/**
+ * Job queue aggregator code that uses BagOStuff.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @author Aaron Schulz
+ */
+
+/**
+ * Class to handle tracking information about all queues using BagOStuff
+ *
+ * @ingroup JobQueue
+ * @since 1.21
+ */
+class JobQueueAggregatorMemc extends JobQueueAggregator {
+       /** @var BagOStuff */
+       protected $cache;
+
+       protected $cacheTTL; // integer; seconds
+
+       /**
+        * @params include:
+        *   - objectCache : Name of an object cache registered in $wgObjectCaches.
+        *                   This defaults to the one specified by $wgMainCacheType.
+        *   - cacheTTL    : Seconds to cache the aggregate data before regenerating.
+        * @param array $params
+        */
+       protected function __construct( array $params ) {
+               parent::__construct( $params );
+               $this->cache = isset( $params['objectCache'] )
+                       ? wfGetCache( $params['objectCache'] )
+                       : wfGetMainCache();
+               $this->cacheTTL = isset( $params['cacheTTL'] ) ? $params['cacheTTL'] : 180; // 3 min
+       }
+
+       /**
+        * @see JobQueueAggregator::doNotifyQueueEmpty()
+        */
+       protected function doNotifyQueueEmpty( $wiki, $type ) {
+               $key = $this->getReadyQueueCacheKey();
+               // Delist the queue from the "ready queue" list
+               if ( $this->cache->add( "$key:lock", 1, 60 ) ) { // lock
+                       $curInfo = $this->cache->get( $key );
+                       if ( is_array( $curInfo ) && isset( $curInfo['pendingDBs'][$type] ) ) {
+                               if ( in_array( $wiki, $curInfo['pendingDBs'][$type] ) ) {
+                                       $curInfo['pendingDBs'][$type] = array_diff(
+                                               $curInfo['pendingDBs'][$type], array( $wiki ) );
+                                       $this->cache->set( $key, $curInfo );
+                               }
+                       }
+                       $this->cache->delete( "$key:lock" ); // unlock
+               }
+
+               return true;
+       }
+
+       /**
+        * @see JobQueueAggregator::doNotifyQueueNonEmpty()
+        */
+       protected function doNotifyQueueNonEmpty( $wiki, $type ) {
+               return true; // updated periodically
+       }
+
+       /**
+        * @see JobQueueAggregator::doAllGetReadyWikiQueues()
+        */
+       protected function doGetAllReadyWikiQueues() {
+               $key = $this->getReadyQueueCacheKey();
+               // If the cache entry wasn't present, is stale, or in .1% of cases otherwise,
+               // regenerate the cache. Use any available stale cache if another process is
+               // currently regenerating the pending DB information.
+               $pendingDbInfo = $this->cache->get( $key );
+               if ( !is_array( $pendingDbInfo )
+                       || ( time() - $pendingDbInfo['timestamp'] ) > $this->cacheTTL
+                       || mt_rand( 0, 999 ) == 0
+               ) {
+                       if ( $this->cache->add( "$key:rebuild", 1, 1800 ) ) { // lock
+                               $pendingDbInfo = array(
+                                       'pendingDBs' => $this->findPendingWikiQueues(),
+                                       'timestamp' => time()
+                               );
+                               for ( $attempts = 1; $attempts <= 25; ++$attempts ) {
+                                       if ( $this->cache->add( "$key:lock", 1, 60 ) ) { // lock
+                                               $this->cache->set( $key, $pendingDbInfo );
+                                               $this->cache->delete( "$key:lock" ); // unlock
+                                               break;
+                                       }
+                               }
+                               $this->cache->delete( "$key:rebuild" ); // unlock
+                       }
+               }
+
+               return is_array( $pendingDbInfo )
+                       ? $pendingDbInfo['pendingDBs']
+                       : array(); // cache is both empty and locked
+       }
+
+       /**
+        * @see JobQueueAggregator::doPurge()
+        */
+       protected function doPurge() {
+               return $this->cache->delete( $this->getReadyQueueCacheKey() );
+       }
+
+       /**
+        * @return string
+        */
+       private function getReadyQueueCacheKey() {
+               return "jobqueue:aggregator:ready-queues:v1"; // global
+       }
+}
diff --git a/includes/jobqueue/aggregator/JobQueueAggregatorRedis.php b/includes/jobqueue/aggregator/JobQueueAggregatorRedis.php
new file mode 100644 (file)
index 0000000..2aec3c9
--- /dev/null
@@ -0,0 +1,206 @@
+<?php
+/**
+ * Job queue aggregator code that uses PhpRedis.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @author Aaron Schulz
+ */
+
+/**
+ * Class to handle tracking information about all queues using PhpRedis
+ *
+ * @ingroup JobQueue
+ * @ingroup Redis
+ * @since 1.21
+ */
+class JobQueueAggregatorRedis extends JobQueueAggregator {
+       /** @var RedisConnectionPool */
+       protected $redisPool;
+
+       /** @var array List of Redis server addresses */
+       protected $servers;
+
+       /**
+        * @params include:
+        *   - redisConfig  : An array of parameters to RedisConnectionPool::__construct().
+        *   - redisServers : Array of server entries, the first being the primary and the
+        *                    others being fallback servers. Each entry is either a hostname/port
+        *                    combination or the absolute path of a UNIX socket.
+        *                    If a hostname is specified but no port, the standard port number
+        *                    6379 will be used. Required.
+        * @param array $params
+        */
+       protected function __construct( array $params ) {
+               parent::__construct( $params );
+               $this->servers = isset( $params['redisServers'] )
+                       ? $params['redisServers']
+                       : array( $params['redisServer'] ); // b/c
+               $this->redisPool = RedisConnectionPool::singleton( $params['redisConfig'] );
+       }
+
+       protected function doNotifyQueueEmpty( $wiki, $type ) {
+               $conn = $this->getConnection();
+               if ( !$conn ) {
+                       return false;
+               }
+               try {
+                       $conn->hDel( $this->getReadyQueueKey(), $this->encQueueName( $type, $wiki ) );
+
+                       return true;
+               } catch ( RedisException $e ) {
+                       $this->handleException( $conn, $e );
+
+                       return false;
+               }
+       }
+
+       protected function doNotifyQueueNonEmpty( $wiki, $type ) {
+               $conn = $this->getConnection();
+               if ( !$conn ) {
+                       return false;
+               }
+               try {
+                       $conn->hSet( $this->getReadyQueueKey(), $this->encQueueName( $type, $wiki ), time() );
+
+                       return true;
+               } catch ( RedisException $e ) {
+                       $this->handleException( $conn, $e );
+
+                       return false;
+               }
+       }
+
+       protected function doGetAllReadyWikiQueues() {
+               $conn = $this->getConnection();
+               if ( !$conn ) {
+                       return array();
+               }
+               try {
+                       $conn->multi( Redis::PIPELINE );
+                       $conn->exists( $this->getReadyQueueKey() );
+                       $conn->hGetAll( $this->getReadyQueueKey() );
+                       list( $exists, $map ) = $conn->exec();
+
+                       if ( $exists ) { // cache hit
+                               $pendingDBs = array(); // (type => list of wikis)
+                               foreach ( $map as $key => $time ) {
+                                       list( $type, $wiki ) = $this->dencQueueName( $key );
+                                       $pendingDBs[$type][] = $wiki;
+                               }
+                       } else { // cache miss
+                               // Avoid duplicated effort
+                               $rand = wfRandomString( 32 );
+                               $conn->multi( Redis::MULTI );
+                               $conn->setex( "{$rand}:lock", 3600, 1 );
+                               $conn->renamenx( "{$rand}:lock", $this->getReadyQueueKey() . ":lock" );
+                               if ( $conn->exec() !== array( true, true ) ) { // lock
+                                       $conn->delete( "{$rand}:lock" );
+                                       return array(); // already in progress
+                               }
+
+                               $pendingDBs = $this->findPendingWikiQueues(); // (type => list of wikis)
+
+                               $conn->delete( $this->getReadyQueueKey() . ":lock" ); // unlock
+
+                               $now = time();
+                               $map = array();
+                               foreach ( $pendingDBs as $type => $wikis ) {
+                                       foreach ( $wikis as $wiki ) {
+                                               $map[$this->encQueueName( $type, $wiki )] = $now;
+                                       }
+                               }
+                               $conn->hMSet( $this->getReadyQueueKey(), $map );
+                       }
+
+                       return $pendingDBs;
+               } catch ( RedisException $e ) {
+                       $this->handleException( $conn, $e );
+
+                       return array();
+               }
+       }
+
+       protected function doPurge() {
+               $conn = $this->getConnection();
+               if ( !$conn ) {
+                       return false;
+               }
+               try {
+                       $conn->delete( $this->getReadyQueueKey() );
+               } catch ( RedisException $e ) {
+                       $this->handleException( $conn, $e );
+
+                       return false;
+               }
+
+               return true;
+       }
+
+       /**
+        * Get a connection to the server that handles all sub-queues for this queue
+        *
+        * @return RedisConnRef|bool Returns false on failure
+        * @throws MWException
+        */
+       protected function getConnection() {
+               $conn = false;
+               foreach ( $this->servers as $server ) {
+                       $conn = $this->redisPool->getConnection( $server );
+                       if ( $conn ) {
+                               break;
+                       }
+               }
+
+               return $conn;
+       }
+
+       /**
+        * @param RedisConnRef $conn
+        * @param RedisException $e
+        * @return void
+        */
+       protected function handleException( RedisConnRef $conn, $e ) {
+               $this->redisPool->handleError( $conn, $e );
+       }
+
+       /**
+        * @return string
+        */
+       private function getReadyQueueKey() {
+               return "jobqueue:aggregator:h-ready-queues:v1"; // global
+       }
+
+       /**
+        * @param string $type
+        * @param string $wiki
+        * @return string
+        */
+       private function encQueueName( $type, $wiki ) {
+               return rawurlencode( $type ) . '/' . rawurlencode( $wiki );
+       }
+
+       /**
+        * @param string $name
+        * @return string
+        */
+       private function dencQueueName( $name ) {
+               list( $type, $wiki ) = explode( '/', $name, 2 );
+
+               return array( rawurldecode( $type ), rawurldecode( $wiki ) );
+       }
+}
diff --git a/includes/jobqueue/jobs/AssembleUploadChunksJob.php b/includes/jobqueue/jobs/AssembleUploadChunksJob.php
new file mode 100644 (file)
index 0000000..19b0558
--- /dev/null
@@ -0,0 +1,134 @@
+<?php
+/**
+ * Assemble the segments of a chunked upload.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup Upload
+ */
+
+/**
+ * Assemble the segments of a chunked upload.
+ *
+ * @ingroup Upload
+ */
+class AssembleUploadChunksJob extends Job {
+       public function __construct( $title, $params ) {
+               parent::__construct( 'AssembleUploadChunks', $title, $params );
+               $this->removeDuplicates = true;
+       }
+
+       public function run() {
+               $scope = RequestContext::importScopedSession( $this->params['session'] );
+               $context = RequestContext::getMain();
+               try {
+                       $user = $context->getUser();
+                       if ( !$user->isLoggedIn() ) {
+                               $this->setLastError( "Could not load the author user from session." );
+
+                               return false;
+                       }
+
+                       if ( count( $_SESSION ) === 0 ) {
+                               // Empty session probably indicates that we didn't associate
+                               // with the session correctly. Note that being able to load
+                               // the user does not necessarily mean the session was loaded.
+                               // Most likely cause by suhosin.session.encrypt = On.
+                               $this->setLastError( "Error associating with user session. " .
+                                       "Try setting suhosin.session.encrypt = Off" );
+
+                               return false;
+                       }
+
+                       UploadBase::setSessionStatus(
+                               $this->params['filekey'],
+                               array( 'result' => 'Poll', 'stage' => 'assembling', 'status' => Status::newGood() )
+                       );
+
+                       $upload = new UploadFromChunks( $user );
+                       $upload->continueChunks(
+                               $this->params['filename'],
+                               $this->params['filekey'],
+                               $context->getRequest()
+                       );
+
+                       // Combine all of the chunks into a local file and upload that to a new stash file
+                       $status = $upload->concatenateChunks();
+                       if ( !$status->isGood() ) {
+                               UploadBase::setSessionStatus(
+                                       $this->params['filekey'],
+                                       array( 'result' => 'Failure', 'stage' => 'assembling', 'status' => $status )
+                               );
+                               $this->setLastError( $status->getWikiText() );
+
+                               return false;
+                       }
+
+                       // We have a new filekey for the fully concatenated file
+                       $newFileKey = $upload->getLocalFile()->getFileKey();
+
+                       // Remove the old stash file row and first chunk file
+                       $upload->stash->removeFileNoAuth( $this->params['filekey'] );
+
+                       // Build the image info array while we have the local reference handy
+                       $apiMain = new ApiMain(); // dummy object (XXX)
+                       $imageInfo = $upload->getImageInfo( $apiMain->getResult() );
+
+                       // Cleanup any temporary local file
+                       $upload->cleanupTempFile();
+
+                       // Cache the info so the user doesn't have to wait forever to get the final info
+                       UploadBase::setSessionStatus(
+                               $this->params['filekey'],
+                               array(
+                                       'result' => 'Success',
+                                       'stage' => 'assembling',
+                                       'filekey' => $newFileKey,
+                                       'imageinfo' => $imageInfo,
+                                       'status' => Status::newGood()
+                               )
+                       );
+               } catch ( MWException $e ) {
+                       UploadBase::setSessionStatus(
+                               $this->params['filekey'],
+                               array(
+                                       'result' => 'Failure',
+                                       'stage' => 'assembling',
+                                       'status' => Status::newFatal( 'api-error-stashfailed' )
+                               )
+                       );
+                       $this->setLastError( get_class( $e ) . ": " . $e->getText() );
+
+                       return false;
+               }
+
+               return true;
+       }
+
+       public function getDeduplicationInfo() {
+               $info = parent::getDeduplicationInfo();
+               if ( is_array( $info['params'] ) ) {
+                       $info['params'] = array( 'filekey' => $info['params']['filekey'] );
+               }
+
+               return $info;
+       }
+
+       public function allowRetries() {
+               return false;
+       }
+}
diff --git a/includes/jobqueue/jobs/DoubleRedirectJob.php b/includes/jobqueue/jobs/DoubleRedirectJob.php
new file mode 100644 (file)
index 0000000..94b56ef
--- /dev/null
@@ -0,0 +1,251 @@
+<?php
+/**
+ * Job to fix double redirects after moving a page.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup JobQueue
+ */
+
+/**
+ * Job to fix double redirects after moving a page
+ *
+ * @ingroup JobQueue
+ */
+class DoubleRedirectJob extends Job {
+       /** @var string Reason for the change, 'maintenance' or 'move'. Suffix fo
+        *    message key 'double-redirect-fixed-'.
+        */
+       private $reason;
+
+       /** @var Title The title which has changed, redirects pointing to this
+        *    title are fixed
+        */
+       private $redirTitle;
+
+       /** @var User */
+       private static $user;
+
+       /**
+        * Insert jobs into the job queue to fix redirects to the given title
+        * @param string $reason the reason for the fix, see message
+        *   "double-redirect-fixed-<reason>"
+        * @param $redirTitle Title: the title which has changed, redirects
+        *   pointing to this title are fixed
+        * @param bool $destTitle Not used
+        */
+       public static function fixRedirects( $reason, $redirTitle, $destTitle = false ) {
+               # Need to use the master to get the redirect table updated in the same transaction
+               $dbw = wfGetDB( DB_MASTER );
+               $res = $dbw->select(
+                       array( 'redirect', 'page' ),
+                       array( 'page_namespace', 'page_title' ),
+                       array(
+                               'page_id = rd_from',
+                               'rd_namespace' => $redirTitle->getNamespace(),
+                               'rd_title' => $redirTitle->getDBkey()
+                       ), __METHOD__ );
+               if ( !$res->numRows() ) {
+                       return;
+               }
+               $jobs = array();
+               foreach ( $res as $row ) {
+                       $title = Title::makeTitle( $row->page_namespace, $row->page_title );
+                       if ( !$title ) {
+                               continue;
+                       }
+
+                       $jobs[] = new self( $title, array(
+                               'reason' => $reason,
+                               'redirTitle' => $redirTitle->getPrefixedDBkey() ) );
+                       # Avoid excessive memory usage
+                       if ( count( $jobs ) > 10000 ) {
+                               JobQueueGroup::singleton()->push( $jobs );
+                               $jobs = array();
+                       }
+               }
+               JobQueueGroup::singleton()->push( $jobs );
+       }
+
+       /**
+        * @param Title $title
+        * @param array|bool $params
+        * @param int $id
+        */
+       function __construct( $title, $params = false ) {
+               parent::__construct( 'fixDoubleRedirect', $title, $params );
+               $this->reason = $params['reason'];
+               $this->redirTitle = Title::newFromText( $params['redirTitle'] );
+       }
+
+       /**
+        * @return bool
+        */
+       function run() {
+               if ( !$this->redirTitle ) {
+                       $this->setLastError( 'Invalid title' );
+
+                       return false;
+               }
+
+               $targetRev = Revision::newFromTitle( $this->title, false, Revision::READ_LATEST );
+               if ( !$targetRev ) {
+                       wfDebug( __METHOD__ . ": target redirect already deleted, ignoring\n" );
+
+                       return true;
+               }
+               $content = $targetRev->getContent();
+               $currentDest = $content ? $content->getRedirectTarget() : null;
+               if ( !$currentDest || !$currentDest->equals( $this->redirTitle ) ) {
+                       wfDebug( __METHOD__ . ": Redirect has changed since the job was queued\n" );
+
+                       return true;
+               }
+
+               // Check for a suppression tag (used e.g. in periodically archived discussions)
+               $mw = MagicWord::get( 'staticredirect' );
+               if ( $content->matchMagicWord( $mw ) ) {
+                       wfDebug( __METHOD__ . ": skipping: suppressed with __STATICREDIRECT__\n" );
+
+                       return true;
+               }
+
+               // Find the current final destination
+               $newTitle = self::getFinalDestination( $this->redirTitle );
+               if ( !$newTitle ) {
+                       wfDebug( __METHOD__ .
+                               ": skipping: single redirect, circular redirect or invalid redirect destination\n" );
+
+                       return true;
+               }
+               if ( $newTitle->equals( $this->redirTitle ) ) {
+                       // The redirect is already right, no need to change it
+                       // This can happen if the page was moved back (say after vandalism)
+                       wfDebug( __METHOD__ . " : skipping, already good\n" );
+               }
+
+               // Preserve fragment (bug 14904)
+               $newTitle = Title::makeTitle( $newTitle->getNamespace(), $newTitle->getDBkey(),
+                       $currentDest->getFragment(), $newTitle->getInterwiki() );
+
+               // Fix the text
+               $newContent = $content->updateRedirect( $newTitle );
+
+               if ( $newContent->equals( $content ) ) {
+                       $this->setLastError( 'Content unchanged???' );
+
+                       return false;
+               }
+
+               $user = $this->getUser();
+               if ( !$user ) {
+                       $this->setLastError( 'Invalid user' );
+
+                       return false;
+               }
+
+               // Save it
+               global $wgUser;
+               $oldUser = $wgUser;
+               $wgUser = $user;
+               $article = WikiPage::factory( $this->title );
+
+               // Messages: double-redirect-fixed-move, double-redirect-fixed-maintenance
+               $reason = wfMessage( 'double-redirect-fixed-' . $this->reason,
+                       $this->redirTitle->getPrefixedText(), $newTitle->getPrefixedText()
+               )->inContentLanguage()->text();
+               $article->doEditContent( $newContent, $reason, EDIT_UPDATE | EDIT_SUPPRESS_RC, false, $user );
+               $wgUser = $oldUser;
+
+               return true;
+       }
+
+       /**
+        * Get the final destination of a redirect
+        *
+        * @param $title Title
+        *
+        * @return bool if the specified title is not a redirect, or if it is a circular redirect
+        */
+       public static function getFinalDestination( $title ) {
+               $dbw = wfGetDB( DB_MASTER );
+
+               // Circular redirect check
+               $seenTitles = array();
+               $dest = false;
+
+               while ( true ) {
+                       $titleText = $title->getPrefixedDBkey();
+                       if ( isset( $seenTitles[$titleText] ) ) {
+                               wfDebug( __METHOD__, "Circular redirect detected, aborting\n" );
+
+                               return false;
+                       }
+                       $seenTitles[$titleText] = true;
+
+                       if ( $title->isExternal() ) {
+                               // If the target is interwiki, we have to break early (bug 40352).
+                               // Otherwise it will look up a row in the local page table
+                               // with the namespace/page of the interwiki target which can cause
+                               // unexpected results (e.g. X -> foo:Bar -> Bar -> .. )
+                               break;
+                       }
+
+                       $row = $dbw->selectRow(
+                               array( 'redirect', 'page' ),
+                               array( 'rd_namespace', 'rd_title', 'rd_interwiki' ),
+                               array(
+                                       'rd_from=page_id',
+                                       'page_namespace' => $title->getNamespace(),
+                                       'page_title' => $title->getDBkey()
+                               ), __METHOD__ );
+                       if ( !$row ) {
+                               # No redirect from here, chain terminates
+                               break;
+                       } else {
+                               $dest = $title = Title::makeTitle(
+                                       $row->rd_namespace,
+                                       $row->rd_title,
+                                       '',
+                                       $row->rd_interwiki
+                               );
+                       }
+               }
+
+               return $dest;
+       }
+
+       /**
+        * Get a user object for doing edits, from a request-lifetime cache
+        * False will be returned if the user name specified in the
+        * 'double-redirect-fixer' message is invalid.
+        *
+        * @return User|bool
+        */
+       function getUser() {
+               if ( !self::$user ) {
+                       $username = wfMessage( 'double-redirect-fixer' )->inContentLanguage()->text();
+                       self::$user = User::newFromName( $username );
+                       # User::newFromName() can return false on a badly configured wiki.
+                       if ( self::$user && !self::$user->isLoggedIn() ) {
+                               self::$user->addToDatabase();
+                       }
+               }
+
+               return self::$user;
+       }
+}
diff --git a/includes/jobqueue/jobs/DuplicateJob.php b/includes/jobqueue/jobs/DuplicateJob.php
new file mode 100644 (file)
index 0000000..b0a6ef7
--- /dev/null
@@ -0,0 +1,59 @@
+<?php
+/**
+ * No-op job that does nothing.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup Cache
+ */
+
+/**
+ * No-op job that does nothing. Used to represent duplicates.
+ *
+ * @ingroup JobQueue
+ */
+final class DuplicateJob extends Job {
+       /**
+        * Callers should use DuplicateJob::newFromJob() instead
+        *
+        * @param Title $title
+        * @param array $params job parameters
+        */
+       function __construct( $title, $params ) {
+               parent::__construct( 'duplicate', $title, $params );
+       }
+
+       /**
+        * Get a duplicate no-op version of a job
+        *
+        * @param Job $job
+        * @return Job
+        */
+       public static function newFromJob( Job $job ) {
+               $djob = new self( $job->getTitle(), $job->getParams() );
+               $djob->command = $job->getType();
+               $djob->params = is_array( $djob->params ) ? $djob->params : array();
+               $djob->params = array( 'isDuplicate' => true ) + $djob->params;
+               $djob->metadata = $job->metadata;
+
+               return $djob;
+       }
+
+       public function run() {
+               return true;
+       }
+}
diff --git a/includes/jobqueue/jobs/EmaillingJob.php b/includes/jobqueue/jobs/EmaillingJob.php
new file mode 100644 (file)
index 0000000..df8ae63
--- /dev/null
@@ -0,0 +1,46 @@
+<?php
+/**
+ * Old job for notification emails.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup JobQueue
+ */
+
+/**
+ * Old job used for sending single notification emails;
+ * kept for backwards-compatibility
+ *
+ * @ingroup JobQueue
+ */
+class EmaillingJob extends Job {
+       function __construct( $title, $params ) {
+               parent::__construct( 'sendMail', Title::newMainPage(), $params );
+       }
+
+       function run() {
+               $status = UserMailer::send(
+                       $this->params['to'],
+                       $this->params['from'],
+                       $this->params['subj'],
+                       $this->params['body'],
+                       $this->params['replyto']
+               );
+
+               return $status->isOK();
+       }
+}
diff --git a/includes/jobqueue/jobs/EnotifNotifyJob.php b/includes/jobqueue/jobs/EnotifNotifyJob.php
new file mode 100644 (file)
index 0000000..1ed99a5
--- /dev/null
@@ -0,0 +1,57 @@
+<?php
+/**
+ * Job for notification emails.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup JobQueue
+ */
+
+/**
+ * Job for email notification mails
+ *
+ * @ingroup JobQueue
+ */
+class EnotifNotifyJob extends Job {
+       function __construct( $title, $params ) {
+               parent::__construct( 'enotifNotify', $title, $params );
+       }
+
+       function run() {
+               $enotif = new EmailNotification();
+               // Get the user from ID (rename safe). Anons are 0, so defer to name.
+               if ( isset( $this->params['editorID'] ) && $this->params['editorID'] ) {
+                       $editor = User::newFromId( $this->params['editorID'] );
+               // B/C, only the name might be given.
+               } else {
+                       # @todo FIXME: newFromName could return false on a badly configured wiki.
+                       $editor = User::newFromName( $this->params['editor'], false );
+               }
+               $enotif->actuallyNotifyOnPageChange(
+                       $editor,
+                       $this->title,
+                       $this->params['timestamp'],
+                       $this->params['summary'],
+                       $this->params['minorEdit'],
+                       $this->params['oldid'],
+                       $this->params['watchers'],
+                       $this->params['pageStatus']
+               );
+
+               return true;
+       }
+}
diff --git a/includes/jobqueue/jobs/HTMLCacheUpdateJob.php b/includes/jobqueue/jobs/HTMLCacheUpdateJob.php
new file mode 100644 (file)
index 0000000..a7c5dc0
--- /dev/null
@@ -0,0 +1,170 @@
+<?php
+/**
+ * HTML cache invalidation of all pages linking to a given title.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup Cache
+ */
+
+/**
+ * Job to purge the cache for all pages that link to or use another page or file
+ *
+ * This job comes in a few variants:
+ *   - a) Recursive jobs to purge caches for backlink pages for a given title.
+ *        These jobs have have (recursive:true,table:<table>) set.
+ *   - b) Jobs to purge caches for a set of titles (the job title is ignored).
+ *           These jobs have have (pages:(<page ID>:(<namespace>,<title>),...) set.
+ *
+ * @ingroup JobQueue
+ */
+class HTMLCacheUpdateJob extends Job {
+       function __construct( $title, $params = '' ) {
+               parent::__construct( 'htmlCacheUpdate', $title, $params );
+               // Base backlink purge jobs can be de-duplicated
+               $this->removeDuplicates = ( !isset( $params['range'] ) && !isset( $params['pages'] ) );
+       }
+
+       function run() {
+               global $wgUpdateRowsPerJob, $wgUpdateRowsPerQuery, $wgMaxBacklinksInvalidate;
+
+               static $expected = array( 'recursive', 'pages' ); // new jobs have one of these
+
+               $oldRangeJob = false;
+               if ( !array_intersect( array_keys( $this->params ), $expected ) ) {
+                       // B/C for older job params formats that lack these fields:
+                       // a) base jobs with just ("table") and b) range jobs with ("table","start","end")
+                       if ( isset( $this->params['start'] ) && isset( $this->params['end'] ) ) {
+                               $oldRangeJob = true;
+                       } else {
+                               $this->params['recursive'] = true; // base job
+                       }
+               }
+
+               // Job to purge all (or a range of) backlink pages for a page
+               if ( !empty( $this->params['recursive'] ) ) {
+                       // @TODO: try to use delayed jobs if possible?
+                       if ( !isset( $this->params['range'] ) && $wgMaxBacklinksInvalidate !== false ) {
+                               $numRows = $this->title->getBacklinkCache()->getNumLinks(
+                                       $this->params['table'], $wgMaxBacklinksInvalidate );
+                               if ( $numRows > $wgMaxBacklinksInvalidate ) {
+                                       return true;
+                               }
+                       }
+                       // Convert this into no more than $wgUpdateRowsPerJob HTMLCacheUpdateJob per-title
+                       // jobs and possibly a recursive HTMLCacheUpdateJob job for the rest of the backlinks
+                       $jobs = BacklinkJobUtils::partitionBacklinkJob(
+                               $this,
+                               $wgUpdateRowsPerJob,
+                               $wgUpdateRowsPerQuery, // jobs-per-title
+                               // Carry over information for de-duplication
+                               array( 'params' => $this->getRootJobParams() )
+                       );
+                       JobQueueGroup::singleton()->push( $jobs );
+               // Job to purge pages for for a set of titles
+               } elseif ( isset( $this->params['pages'] ) ) {
+                       $this->invalidateTitles( $this->params['pages'] );
+               // B/C for job to purge a range of backlink pages for a given page
+               } elseif ( $oldRangeJob ) {
+                       $titleArray = $this->title->getBacklinkCache()->getLinks(
+                               $this->params['table'], $this->params['start'], $this->params['end'] );
+
+                       $pages = array(); // same format BacklinkJobUtils uses
+                       foreach ( $titleArray as $tl ) {
+                               $pages[$tl->getArticleId()] = array( $tl->getNamespace(), $tl->getDbKey() );
+                       }
+
+                       $jobs = array();
+                       foreach ( array_chunk( $pages, $wgUpdateRowsPerJob ) as $pageChunk ) {
+                               $jobs[] = new HTMLCacheUpdateJob( $this->title,
+                                       array(
+                                               'table' => $this->params['table'],
+                                               'pages' => $pageChunk
+                                       ) + $this->getRootJobParams() // carry over information for de-duplication
+                               );
+                       }
+                       JobQueueGroup::singleton()->push( $jobs );
+               }
+
+               return true;
+       }
+
+       /**
+        * @param array $pages Map of (page ID => (namespace, DB key)) entries
+        */
+       protected function invalidateTitles( array $pages ) {
+               global $wgUpdateRowsPerQuery, $wgUseFileCache, $wgUseSquid;
+
+               // Get all page IDs in this query into an array
+               $pageIds = array_keys( $pages );
+               if ( !$pageIds ) {
+                       return;
+               }
+
+               $dbw = wfGetDB( DB_MASTER );
+
+               // The page_touched field will need to be bumped for these pages.
+               // Only bump it to the present time if no "rootJobTimestamp" was known.
+               // If it is known, it can be used instead, which avoids invalidating output
+               // that was in fact generated *after* the relevant dependency change time
+               // (e.g. template edit). This is particularily useful since refreshLinks jobs
+               // save back parser output and usually run along side htmlCacheUpdate jobs;
+               // their saved output would be invalidated by using the current timestamp.
+               if ( isset( $this->params['rootJobTimestamp'] ) ) {
+                       $touchTimestamp = $this->params['rootJobTimestamp'];
+               } else {
+                       $touchTimestamp = wfTimestampNow();
+               }
+
+               // Update page_touched (skipping pages already touched since the root job).
+               // Check $wgUpdateRowsPerQuery for sanity; batch jobs are sized by that already.
+               foreach ( array_chunk( $pageIds, $wgUpdateRowsPerQuery ) as $batch ) {
+                       $dbw->update( 'page',
+                               array( 'page_touched' => $dbw->timestamp( $touchTimestamp ) ),
+                               array( 'page_id' => $batch,
+                                       // don't invalidated pages that were already invalidated
+                                       "page_touched < " . $dbw->addQuotes( $dbw->timestamp( $touchTimestamp ) )
+                               ),
+                               __METHOD__
+                       );
+               }
+               // Get the list of affected pages (races only mean something else did the purge)
+               $titleArray = TitleArray::newFromResult( $dbw->select(
+                       'page',
+                       array( 'page_namespace', 'page_title' ),
+                       array( 'page_id' => $pageIds, 'page_touched' => $dbw->timestamp( $touchTimestamp ) ),
+                       __METHOD__
+               ) );
+
+               // Update squid
+               if ( $wgUseSquid ) {
+                       $u = SquidUpdate::newFromTitles( $titleArray );
+                       $u->doUpdate();
+               }
+
+               // Update file cache
+               if ( $wgUseFileCache ) {
+                       foreach ( $titleArray as $title ) {
+                               HTMLFileCache::clearFileCache( $title );
+                       }
+               }
+       }
+
+       public function workItemCount() {
+               return isset( $this->params['pages'] ) ? count( $this->params['pages'] ) : 1;
+       }
+}
diff --git a/includes/jobqueue/jobs/NullJob.php b/includes/jobqueue/jobs/NullJob.php
new file mode 100644 (file)
index 0000000..b2d6a9a
--- /dev/null
@@ -0,0 +1,76 @@
+<?php
+/**
+ * Degenerate job that does nothing.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup Cache
+ */
+
+/**
+ * Degenerate job that does nothing, but can optionally replace itself
+ * in the queue and/or sleep for a brief time period. These can be used
+ * to represent "no-op" jobs or test lock contention and performance.
+ *
+ * @par Example:
+ * Inserting a null job in the configured job queue:
+ * @code
+ * $ php maintenance/eval.php
+ * > $queue = JobQueueGroup::singleton();
+ * > $job = new NullJob( Title::newMainPage(), array( 'lives' => 10 ) );
+ * > $queue->push( $job );
+ * @endcode
+ * You can then confirm the job has been enqueued by using the showJobs.php
+ * maintenance utility:
+ * @code
+ * $ php maintenance/showJobs.php --group
+ * null: 1 queue; 0 claimed (0 active, 0 abandoned)
+ * $
+ * @endcode
+ *
+ * @ingroup JobQueue
+ */
+class NullJob extends Job {
+       /**
+        * @param Title $title
+        * @param array $params job parameters (lives, usleep)
+        */
+       function __construct( $title, $params ) {
+               parent::__construct( 'null', $title, $params );
+               if ( !isset( $this->params['lives'] ) ) {
+                       $this->params['lives'] = 1;
+               }
+               if ( !isset( $this->params['usleep'] ) ) {
+                       $this->params['usleep'] = 0;
+               }
+               $this->removeDuplicates = !empty( $this->params['removeDuplicates'] );
+       }
+
+       public function run() {
+               if ( $this->params['usleep'] > 0 ) {
+                       usleep( $this->params['usleep'] );
+               }
+               if ( $this->params['lives'] > 1 ) {
+                       $params = $this->params;
+                       $params['lives']--;
+                       $job = new self( $this->title, $params );
+                       JobQueueGroup::singleton()->push( $job );
+               }
+
+               return true;
+       }
+}
diff --git a/includes/jobqueue/jobs/PublishStashedFileJob.php b/includes/jobqueue/jobs/PublishStashedFileJob.php
new file mode 100644 (file)
index 0000000..d7667f3
--- /dev/null
@@ -0,0 +1,147 @@
+<?php
+/**
+ * Upload a file from the upload stash into the local file repo.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup Upload
+ */
+
+/**
+ * Upload a file from the upload stash into the local file repo.
+ *
+ * @ingroup Upload
+ */
+class PublishStashedFileJob extends Job {
+       public function __construct( $title, $params ) {
+               parent::__construct( 'PublishStashedFile', $title, $params );
+               $this->removeDuplicates = true;
+       }
+
+       public function run() {
+               $scope = RequestContext::importScopedSession( $this->params['session'] );
+               $context = RequestContext::getMain();
+               try {
+                       $user = $context->getUser();
+                       if ( !$user->isLoggedIn() ) {
+                               $this->setLastError( "Could not load the author user from session." );
+
+                               return false;
+                       }
+
+                       if ( count( $_SESSION ) === 0 ) {
+                               // Empty session probably indicates that we didn't associate
+                               // with the session correctly. Note that being able to load
+                               // the user does not necessarily mean the session was loaded.
+                               // Most likely cause by suhosin.session.encrypt = On.
+                               $this->setLastError( "Error associating with user session. " .
+                                       "Try setting suhosin.session.encrypt = Off" );
+
+                               return false;
+                       }
+
+                       UploadBase::setSessionStatus(
+                               $this->params['filekey'],
+                               array( 'result' => 'Poll', 'stage' => 'publish', 'status' => Status::newGood() )
+                       );
+
+                       $upload = new UploadFromStash( $user );
+                       // @todo initialize() causes a GET, ideally we could frontload the antivirus
+                       // checks and anything else to the stash stage (which includes concatenation and
+                       // the local file is thus already there). That way, instead of GET+PUT, there could
+                       // just be a COPY operation from the stash to the public zone.
+                       $upload->initialize( $this->params['filekey'], $this->params['filename'] );
+
+                       // Check if the local file checks out (this is generally a no-op)
+                       $verification = $upload->verifyUpload();
+                       if ( $verification['status'] !== UploadBase::OK ) {
+                               $status = Status::newFatal( 'verification-error' );
+                               $status->value = array( 'verification' => $verification );
+                               UploadBase::setSessionStatus(
+                                       $this->params['filekey'],
+                                       array( 'result' => 'Failure', 'stage' => 'publish', 'status' => $status )
+                               );
+                               $this->setLastError( "Could not verify upload." );
+
+                               return false;
+                       }
+
+                       // Upload the stashed file to a permanent location
+                       $status = $upload->performUpload(
+                               $this->params['comment'],
+                               $this->params['text'],
+                               $this->params['watch'],
+                               $user
+                       );
+                       if ( !$status->isGood() ) {
+                               UploadBase::setSessionStatus(
+                                       $this->params['filekey'],
+                                       array( 'result' => 'Failure', 'stage' => 'publish', 'status' => $status )
+                               );
+                               $this->setLastError( $status->getWikiText() );
+
+                               return false;
+                       }
+
+                       // Build the image info array while we have the local reference handy
+                       $apiMain = new ApiMain(); // dummy object (XXX)
+                       $imageInfo = $upload->getImageInfo( $apiMain->getResult() );
+
+                       // Cleanup any temporary local file
+                       $upload->cleanupTempFile();
+
+                       // Cache the info so the user doesn't have to wait forever to get the final info
+                       UploadBase::setSessionStatus(
+                               $this->params['filekey'],
+                               array(
+                                       'result' => 'Success',
+                                       'stage' => 'publish',
+                                       'filename' => $upload->getLocalFile()->getName(),
+                                       'imageinfo' => $imageInfo,
+                                       'status' => Status::newGood()
+                               )
+                       );
+               } catch ( MWException $e ) {
+                       UploadBase::setSessionStatus(
+                               $this->params['filekey'],
+                               array(
+                                       'result' => 'Failure',
+                                       'stage' => 'publish',
+                                       'status' => Status::newFatal( 'api-error-publishfailed' )
+                               )
+                       );
+                       $this->setLastError( get_class( $e ) . ": " . $e->getText() );
+
+                       return false;
+               }
+
+               return true;
+       }
+
+       public function getDeduplicationInfo() {
+               $info = parent::getDeduplicationInfo();
+               if ( is_array( $info['params'] ) ) {
+                       $info['params'] = array( 'filekey' => $info['params']['filekey'] );
+               }
+
+               return $info;
+       }
+
+       public function allowRetries() {
+               return false;
+       }
+}
diff --git a/includes/jobqueue/jobs/RefreshLinksJob.php b/includes/jobqueue/jobs/RefreshLinksJob.php
new file mode 100644 (file)
index 0000000..3bcb4fc
--- /dev/null
@@ -0,0 +1,197 @@
+<?php
+/**
+ * Job to update link tables for pages
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup JobQueue
+ */
+
+/**
+ * Job to update link tables for pages
+ *
+ * This job comes in a few variants:
+ *   - a) Recursive jobs to update links for backlink pages for a given title.
+ *        These jobs have have (recursive:true,table:<table>) set.
+ *   - b) Jobs to update links for a set of pages (the job title is ignored).
+ *           These jobs have have (pages:(<page ID>:(<namespace>,<title>),...) set.
+ *   - c) Jobs to update links for a single page (the job title)
+ *        These jobs need no extra fields set.
+ *
+ * @ingroup JobQueue
+ */
+class RefreshLinksJob extends Job {
+       const PARSE_THRESHOLD_SEC = 1.0;
+
+       function __construct( $title, $params = '' ) {
+               parent::__construct( 'refreshLinks', $title, $params );
+               // Base backlink update jobs and per-title update jobs can be de-duplicated.
+               // If template A changes twice before any jobs run, a clean queue will have:
+               //              (A base, A base)
+               // The second job is ignored by the queue on insertion.
+               // Suppose, many pages use template A, and that template itself uses template B.
+               // An edit to both will first create two base jobs. A clean FIFO queue will have:
+               //              (A base, B base)
+               // When these jobs run, the queue will have per-title and remnant partition jobs:
+               //              (titleX,titleY,titleZ,...,A remnant,titleM,titleN,titleO,...,B remnant)
+               // Some these jobs will be the same, and will automatically be ignored by
+               // the queue upon insertion. Some title jobs will run before the duplicate is
+               // inserted, so the work will still be done twice in those cases. More titles
+               // can be de-duplicated as the remnant jobs continue to be broken down. This
+               // works best when $wgUpdateRowsPerJob, and either the pages have few backlinks
+               // and/or the backlink sets for pages A and B are almost identical.
+               $this->removeDuplicates = !isset( $params['range'] )
+                       && ( !isset( $params['pages'] ) || count( $params['pages'] ) == 1 );
+       }
+
+       function run() {
+               global $wgUpdateRowsPerJob;
+
+               // Job to update all (or a range of) backlink pages for a page
+               if ( !empty( $this->params['recursive'] ) ) {
+                       // Carry over information for de-duplication
+                       $extraParams = $this->getRootJobParams();
+                       // Avoid slave lag when fetching templates.
+                       // When the outermost job is run, we know that the caller that enqueued it must have
+                       // committed the relevant changes to the DB by now. At that point, record the master
+                       // position and pass it along as the job recursively breaks into smaller range jobs.
+                       // Hopefully, when leaf jobs are popped, the slaves will have reached that position.
+                       if ( isset( $this->params['masterPos'] ) ) {
+                               $extraParams['masterPos'] = $this->params['masterPos'];
+                       } elseif ( wfGetLB()->getServerCount() > 1 ) {
+                               $extraParams['masterPos'] = wfGetLB()->getMasterPos();
+                       } else {
+                               $extraParams['masterPos'] = false;
+                       }
+                       // Convert this into no more than $wgUpdateRowsPerJob RefreshLinks per-title
+                       // jobs and possibly a recursive RefreshLinks job for the rest of the backlinks
+                       $jobs = BacklinkJobUtils::partitionBacklinkJob(
+                               $this,
+                               $wgUpdateRowsPerJob,
+                               1, // job-per-title
+                               array( 'params' => $extraParams )
+                       );
+                       JobQueueGroup::singleton()->push( $jobs );
+               // Job to update link tables for for a set of titles
+               } elseif ( isset( $this->params['pages'] ) ) {
+                       foreach ( $this->params['pages'] as $pageId => $nsAndKey ) {
+                               list( $ns, $dbKey ) = $nsAndKey;
+                               $this->runForTitle( Title::makeTitleSafe( $ns, $dbKey ) );
+                       }
+               // Job to update link tables for a given title
+               } else {
+                       $this->runForTitle( $this->title );
+               }
+
+               return true;
+       }
+
+       protected function runForTitle( Title $title = null ) {
+               $linkCache = LinkCache::singleton();
+               $linkCache->clear();
+
+               if ( is_null( $title ) ) {
+                       $this->setLastError( "refreshLinks: Invalid title" );
+                       return false;
+               }
+
+               // Wait for the DB of the current/next slave DB handle to catch up to the master.
+               // This way, we get the correct page_latest for templates or files that just changed
+               // milliseconds ago, having triggered this job to begin with.
+               if ( isset( $this->params['masterPos'] ) && $this->params['masterPos'] !== false ) {
+                       wfGetLB()->waitFor( $this->params['masterPos'] );
+               }
+
+               $page = WikiPage::factory( $title );
+
+               // Fetch the current revision...
+               $revision = Revision::newFromTitle( $title, false, Revision::READ_NORMAL );
+               if ( !$revision ) {
+                       $this->setLastError( "refreshLinks: Article not found {$title->getPrefixedDBkey()}" );
+                       return false; // XXX: what if it was just deleted?
+               }
+               $content = $revision->getContent( Revision::RAW );
+               if ( !$content ) {
+                       // If there is no content, pretend the content is empty
+                       $content = $revision->getContentHandler()->makeEmptyContent();
+               }
+
+               $parserOutput = false;
+               $parserOptions = $page->makeParserOptions( 'canonical' );
+               // If page_touched changed after this root job (with a good slave lag skew factor),
+               // then it is likely that any views of the pages already resulted in re-parses which
+               // are now in cache. This can be reused to avoid expensive parsing in some cases.
+               if ( isset( $this->params['rootJobTimestamp'] ) ) {
+                       $skewedTimestamp = wfTimestamp( TS_UNIX, $this->params['rootJobTimestamp'] ) + 5;
+                       if ( $page->getLinksTimestamp() > wfTimestamp( TS_MW, $skewedTimestamp ) ) {
+                               // Something already updated the backlinks since this job was made
+                               return true;
+                       }
+                       if ( $page->getTouched() > wfTimestamp( TS_MW, $skewedTimestamp ) ) {
+                               $parserOutput = ParserCache::singleton()->getDirty( $page, $parserOptions );
+                               if ( $parserOutput && $parserOutput->getCacheTime() <= $skewedTimestamp ) {
+                                       $parserOutput = false; // too stale
+                               }
+                       }
+               }
+               // Fetch the current revision and parse it if necessary...
+               if ( $parserOutput == false ) {
+                       $start = microtime( true );
+                       // Revision ID must be passed to the parser output to get revision variables correct
+                       $parserOutput = $content->getParserOutput(
+                               $title, $revision->getId(), $parserOptions, false );
+                       $ellapsed = microtime( true ) - $start;
+                       // If it took a long time to render, then save this back to the cache to avoid
+                       // wasted CPU by other apaches or job runners. We don't want to always save to
+                       // cache as this cause cause high cache I/O and LRU churn when a template changes.
+                       if ( $ellapsed >= self::PARSE_THRESHOLD_SEC
+                               && $page->isParserCacheUsed( $parserOptions, $revision->getId() )
+                               && $parserOutput->isCacheable()
+                       ) {
+                               $ctime = wfTimestamp( TS_MW, (int)$start ); // cache time
+                               ParserCache::singleton()->save( $parserOutput, $page, $parserOptions, $ctime );
+                       }
+               }
+
+               $updates = $content->getSecondaryDataUpdates( $title, null, false, $parserOutput );
+               DataUpdate::runUpdates( $updates );
+
+               InfoAction::invalidateCache( $title );
+
+               return true;
+       }
+
+       public function getDeduplicationInfo() {
+               $info = parent::getDeduplicationInfo();
+               if ( is_array( $info['params'] ) ) {
+                       // Don't let highly unique "masterPos" values ruin duplicate detection
+                       unset( $info['params']['masterPos'] );
+                       // For per-pages jobs, the job title is that of the template that changed
+                       // (or similar), so remove that since it ruins duplicate detection
+                       if ( isset( $info['pages'] ) ) {
+                               unset( $info['namespace'] );
+                               unset( $info['title'] );
+                       }
+               }
+
+               return $info;
+       }
+
+       public function workItemCount() {
+               return isset( $this->params['pages'] ) ? count( $this->params['pages'] ) : 1;
+       }
+}
diff --git a/includes/jobqueue/jobs/RefreshLinksJob2.php b/includes/jobqueue/jobs/RefreshLinksJob2.php
new file mode 100644 (file)
index 0000000..77e3b3f
--- /dev/null
@@ -0,0 +1,141 @@
+<?php
+/**
+ * Job to update links for a given title.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup JobQueue
+ */
+
+/**
+ * Background job to update links for titles in certain backlink range by page ID.
+ * Newer version for high use templates. This is deprecated by RefreshLinksPartitionJob.
+ *
+ * @ingroup JobQueue
+ * @deprecated 1.23
+ */
+class RefreshLinksJob2 extends Job {
+       function __construct( $title, $params ) {
+               parent::__construct( 'refreshLinks2', $title, $params );
+               // Base jobs for large templates can easily be de-duplicated
+               $this->removeDuplicates = !isset( $params['start'] ) && !isset( $params['end'] );
+       }
+
+       /**
+        * Run a refreshLinks2 job
+        * @return boolean success
+        */
+       function run() {
+               global $wgUpdateRowsPerJob;
+
+               $linkCache = LinkCache::singleton();
+               $linkCache->clear();
+
+               if ( is_null( $this->title ) ) {
+                       $this->error = "refreshLinks2: Invalid title";
+                       return false;
+               }
+
+               // Back compat for pre-r94435 jobs
+               $table = isset( $this->params['table'] ) ? $this->params['table'] : 'templatelinks';
+
+               // Avoid slave lag when fetching templates.
+               // When the outermost job is run, we know that the caller that enqueued it must have
+               // committed the relevant changes to the DB by now. At that point, record the master
+               // position and pass it along as the job recursively breaks into smaller range jobs.
+               // Hopefully, when leaf jobs are popped, the slaves will have reached that position.
+               if ( isset( $this->params['masterPos'] ) ) {
+                       $masterPos = $this->params['masterPos'];
+               } elseif ( wfGetLB()->getServerCount() > 1 ) {
+                       $masterPos = wfGetLB()->getMasterPos();
+               } else {
+                       $masterPos = false;
+               }
+
+               $tbc = $this->title->getBacklinkCache();
+
+               $jobs = array(); // jobs to insert
+               if ( isset( $this->params['start'] ) && isset( $this->params['end'] ) ) {
+                       # This is a partition job to trigger the insertion of leaf jobs...
+                       $jobs = array_merge( $jobs, $this->getSingleTitleJobs( $table, $masterPos ) );
+               } else {
+                       # This is a base job to trigger the insertion of partitioned jobs...
+                       if ( $tbc->getNumLinks( $table, $wgUpdateRowsPerJob + 1 ) <= $wgUpdateRowsPerJob ) {
+                               # Just directly insert the single per-title jobs
+                               $jobs = array_merge( $jobs, $this->getSingleTitleJobs( $table, $masterPos ) );
+                       } else {
+                               # Insert the partition jobs to make per-title jobs
+                               foreach ( $tbc->partition( $table, $wgUpdateRowsPerJob ) as $batch ) {
+                                       list( $start, $end ) = $batch;
+                                       $jobs[] = new RefreshLinksJob2( $this->title,
+                                               array(
+                                                       'table' => $table,
+                                                       'start' => $start,
+                                                       'end' => $end,
+                                                       'masterPos' => $masterPos,
+                                               ) + $this->getRootJobParams() // carry over information for de-duplication
+                                       );
+                               }
+                       }
+               }
+
+               if ( count( $jobs ) ) {
+                       JobQueueGroup::singleton()->push( $jobs );
+               }
+
+               return true;
+       }
+
+       /**
+        * @param $table string
+        * @param $masterPos mixed
+        * @return Array
+        */
+       protected function getSingleTitleJobs( $table, $masterPos ) {
+               # The "start"/"end" fields are not set for the base jobs
+               $start = isset( $this->params['start'] ) ? $this->params['start'] : false;
+               $end = isset( $this->params['end'] ) ? $this->params['end'] : false;
+               $titles = $this->title->getBacklinkCache()->getLinks( $table, $start, $end );
+               # Convert into single page refresh links jobs.
+               # This handles well when in sapi mode and is useful in any case for job
+               # de-duplication. If many pages use template A, and that template itself
+               # uses template B, then an edit to both will create many duplicate jobs.
+               # Roughly speaking, for each page, one of the "RefreshLinksJob" jobs will
+               # get run first, and when it does, it will remove the duplicates. Of course,
+               # one page could have its job popped when the other page's job is still
+               # buried within the logic of a refreshLinks2 job.
+               $jobs = array();
+               foreach ( $titles as $title ) {
+                       $jobs[] = new RefreshLinksJob( $title,
+                               array( 'masterPos' => $masterPos ) + $this->getRootJobParams()
+                       ); // carry over information for de-duplication
+               }
+               return $jobs;
+       }
+
+       /**
+        * @return Array
+        */
+       public function getDeduplicationInfo() {
+               $info = parent::getDeduplicationInfo();
+               // Don't let highly unique "masterPos" values ruin duplicate detection
+               if ( is_array( $info['params'] ) ) {
+                       unset( $info['params']['masterPos'] );
+               }
+               return $info;
+       }
+}
diff --git a/includes/jobqueue/jobs/UploadFromUrlJob.php b/includes/jobqueue/jobs/UploadFromUrlJob.php
new file mode 100644 (file)
index 0000000..2cdac57
--- /dev/null
@@ -0,0 +1,187 @@
+<?php
+/**
+ * Job for asynchronous upload-by-url.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup JobQueue
+ */
+
+/**
+ * Job for asynchronous upload-by-url.
+ *
+ * This job is in fact an interface to UploadFromUrl, which is designed such
+ * that it does not require any globals. If it does, fix it elsewhere, do not
+ * add globals in here.
+ *
+ * @ingroup JobQueue
+ */
+class UploadFromUrlJob extends Job {
+       const SESSION_KEYNAME = 'wsUploadFromUrlJobData';
+
+       /** @var UploadFromUrl */
+       public $upload;
+
+       /** @var User */
+       protected $user;
+
+       public function __construct( $title, $params ) {
+               parent::__construct( 'uploadFromUrl', $title, $params );
+       }
+
+       public function run() {
+               global $wgCopyUploadAsyncTimeout;
+               # Initialize this object and the upload object
+               $this->upload = new UploadFromUrl();
+               $this->upload->initialize(
+                       $this->title->getText(),
+                       $this->params['url'],
+                       false
+               );
+               $this->user = User::newFromName( $this->params['userName'] );
+
+               # Fetch the file
+               $opts = array();
+               if ( $wgCopyUploadAsyncTimeout ) {
+                       $opts['timeout'] = $wgCopyUploadAsyncTimeout;
+               }
+               $status = $this->upload->fetchFile( $opts );
+               if ( !$status->isOk() ) {
+                       $this->leaveMessage( $status );
+
+                       return true;
+               }
+
+               # Verify upload
+               $result = $this->upload->verifyUpload();
+               if ( $result['status'] != UploadBase::OK ) {
+                       $status = $this->upload->convertVerifyErrorToStatus( $result );
+                       $this->leaveMessage( $status );
+
+                       return true;
+               }
+
+               # Check warnings
+               if ( !$this->params['ignoreWarnings'] ) {
+                       $warnings = $this->upload->checkWarnings();
+                       if ( $warnings ) {
+
+                               # Stash the upload
+                               $key = $this->upload->stashFile();
+
+                               // @todo FIXME: This has been broken for a while.
+                               // User::leaveUserMessage() does not exist.
+                               if ( $this->params['leaveMessage'] ) {
+                                       $this->user->leaveUserMessage(
+                                               wfMessage( 'upload-warning-subj' )->text(),
+                                               wfMessage( 'upload-warning-msg',
+                                                       $key,
+                                                       $this->params['url'] )->text()
+                                       );
+                               } else {
+                                       wfSetupSession( $this->params['sessionId'] );
+                                       $this->storeResultInSession( 'Warning',
+                                               'warnings', $warnings );
+                                       session_write_close();
+                               }
+
+                               return true;
+                       }
+               }
+
+               # Perform the upload
+               $status = $this->upload->performUpload(
+                       $this->params['comment'],
+                       $this->params['pageText'],
+                       $this->params['watch'],
+                       $this->user
+               );
+               $this->leaveMessage( $status );
+
+               return true;
+       }
+
+       /**
+        * Leave a message on the user talk page or in the session according to
+        * $params['leaveMessage'].
+        *
+        * @param Status $status
+        */
+       protected function leaveMessage( $status ) {
+               if ( $this->params['leaveMessage'] ) {
+                       if ( $status->isGood() ) {
+                               // @todo FIXME: user->leaveUserMessage does not exist.
+                               $this->user->leaveUserMessage( wfMessage( 'upload-success-subj' )->text(),
+                                       wfMessage( 'upload-success-msg',
+                                               $this->upload->getTitle()->getText(),
+                                               $this->params['url']
+                                       )->text() );
+                       } else {
+                               // @todo FIXME: user->leaveUserMessage does not exist.
+                               $this->user->leaveUserMessage( wfMessage( 'upload-failure-subj' )->text(),
+                                       wfMessage( 'upload-failure-msg',
+                                               $status->getWikiText(),
+                                               $this->params['url']
+                                       )->text() );
+                       }
+               } else {
+                       wfSetupSession( $this->params['sessionId'] );
+                       if ( $status->isOk() ) {
+                               $this->storeResultInSession( 'Success',
+                                       'filename', $this->upload->getLocalFile()->getName() );
+                       } else {
+                               $this->storeResultInSession( 'Failure',
+                                       'errors', $status->getErrorsArray() );
+                       }
+                       session_write_close();
+               }
+       }
+
+       /**
+        * Store a result in the session data. Note that the caller is responsible
+        * for appropriate session_start and session_write_close calls.
+        *
+        * @param string $result the result (Success|Warning|Failure)
+        * @param string $dataKey the key of the extra data
+        * @param mixed $dataValue The extra data itself
+        */
+       protected function storeResultInSession( $result, $dataKey, $dataValue ) {
+               $session =& self::getSessionData( $this->params['sessionKey'] );
+               $session['result'] = $result;
+               $session[$dataKey] = $dataValue;
+       }
+
+       /**
+        * Initialize the session data. Sets the intial result to queued.
+        */
+       public function initializeSessionData() {
+               $session =& self::getSessionData( $this->params['sessionKey'] );
+               $$session['result'] = 'Queued';
+       }
+
+       /**
+        * @param $key
+        * @return mixed
+        */
+       public static function &getSessionData( $key ) {
+               if ( !isset( $_SESSION[self::SESSION_KEYNAME][$key] ) ) {
+                       $_SESSION[self::SESSION_KEYNAME][$key] = array();
+               }
+
+               return $_SESSION[self::SESSION_KEYNAME][$key];
+       }
+}
diff --git a/includes/jobqueue/utils/BacklinkJobUtils.php b/includes/jobqueue/utils/BacklinkJobUtils.php
new file mode 100644 (file)
index 0000000..c8e5df6
--- /dev/null
@@ -0,0 +1,122 @@
+<?php
+/**
+ * Job to update links for a given title.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup JobQueue
+ * @author Aaron Schulz
+ */
+
+/**
+ * Class with Backlink related Job helper methods
+ *
+ * @ingroup JobQueue
+ * @since 1.23
+ */
+class BacklinkJobUtils {
+       /**
+        * Break down $job into approximately ($bSize/$cSize) leaf jobs and a single partition
+        * job that covers the remaining backlink range (if needed). Jobs for the first $bSize
+        * titles are collated ($cSize per job) into leaf jobs to do actual work. All the
+        * resulting jobs are of the same class as $job. No partition job is returned if the
+        * range covered by $job was less than $bSize, as the leaf jobs have full coverage.
+        *
+        * The leaf jobs have the 'pages' param set to a (<page ID>:(<namespace>,<DB key>),...)
+        * map so that the run() function knows what pages to act on. The leaf jobs will keep
+        * the same job title as the parent job (e.g. $job).
+        *
+        * The partition jobs have the 'range' parameter set to a map of the format
+        * (start:<integer>, end:<integer>, batchSize:<integer>, subranges:((<start>,<end>),...)),
+        * the 'table' parameter set to that of $job, and the 'recursive' parameter set to true.
+        * This method can be called on the resulting job to repeat the process again.
+        *
+        * The job provided ($job) must have the 'recursive' parameter set to true and the 'table'
+        * parameter must be set to a backlink table. The job title will be used as the title to
+        * find backlinks for. Any 'range' parameter must follow the same format as mentioned above.
+        * This should be managed by recursive calls to this method.
+        *
+        * The first jobs return are always the leaf jobs. This lets the caller use push() to
+        * put them directly into the queue and works well if the queue is FIFO. In such a queue,
+        * the leaf jobs have to get finished first before anything can resolve the next partition
+        * job, which keeps the queue very small.
+        *
+        * $opts includes:
+        *   - params : extra job parameters to include in each job
+        *
+        * @param Job $job
+        * @param int $bSize BacklinkCache partition size; usually $wgUpdateRowsPerJob
+        * @param int $cSize Max titles per leaf job; Usually 1 or a modest value
+        * @param array $opts Optional parameter map
+        * @return Job[] List of Job objects
+        */
+       public static function partitionBacklinkJob( Job $job, $bSize, $cSize, $opts = array() ) {
+               $class = get_class( $job );
+               $title = $job->getTitle();
+               $params = $job->getParams();
+
+               if ( isset( $params['pages'] ) || empty( $params['recursive'] ) ) {
+                       $ranges = array(); // sanity; this is a leaf node
+                       wfWarn( __METHOD__ . " called on {$job->getType()} leaf job (explosive recursion)." );
+               } elseif ( isset( $params['range'] ) ) {
+                       // This is a range job to trigger the insertion of partitioned/title jobs...
+                       $ranges = $params['range']['subranges'];
+                       $realBSize = $params['range']['batchSize'];
+               } else {
+                       // This is a base job to trigger the insertion of partitioned jobs...
+                       $ranges = $title->getBacklinkCache()->partition( $params['table'], $bSize );
+                       $realBSize = $bSize;
+               }
+
+               $extraParams = isset( $opts['params'] ) ? $opts['params'] : array();
+
+               $jobs = array();
+               // Combine the first range (of size $bSize) backlinks into leaf jobs
+               if ( isset( $ranges[0] ) ) {
+                       list( $start, $end ) = $ranges[0];
+                       $titles = $title->getBacklinkCache()->getLinks( $params['table'], $start, $end );
+                       foreach ( array_chunk( iterator_to_array( $titles ), $cSize ) as $titleBatch ) {
+                               $pages = array();
+                               foreach ( $titleBatch as $tl ) {
+                                       $pages[$tl->getArticleId()] = array( $tl->getNamespace(), $tl->getDBKey() );
+                               }
+                               $jobs[] = new $class(
+                                       $title, // maintain parent job title
+                                       array( 'pages' => $pages ) + $extraParams
+                               );
+                       }
+               }
+               // Take all of the remaining ranges and build a partition job from it
+               if ( isset( $ranges[1] ) ) {
+                       $jobs[] = new $class(
+                               $title, // maintain parent job title
+                               array(
+                                       'recursive'     => true,
+                                       'table'         => $params['table'],
+                                       'range'         => array(
+                                               'start'     => $ranges[1][0],
+                                               'end'       => $ranges[count( $ranges ) - 1][1],
+                                               'batchSize' => $realBSize,
+                                               'subranges' => array_slice( $ranges, 1 )
+                                       ),
+                               ) + $extraParams
+                       );
+               }
+
+               return $jobs;
+       }
+}
index f0f297f..ad8710c 100644 (file)
@@ -3,7 +3,7 @@
  * Contain classes to list log entries
  *
  * Copyright © 2004 Brion Vibber <brion@pobox.com>, 2008 Aaron Schulz
- * http://www.mediawiki.org/
+ * https://www.mediawiki.org/
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
index f5798e2..0e8d1de 100644 (file)
@@ -3,7 +3,7 @@
  * Contain log classes
  *
  * Copyright © 2002, 2004 Brion Vibber <brion@pobox.com>
- * http://www.mediawiki.org/
+ * https://www.mediawiki.org/
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
index 900ece9..e27e28a 100644 (file)
@@ -3,7 +3,7 @@
  * Contain classes to list log entries
  *
  * Copyright © 2004 Brion Vibber <brion@pobox.com>, 2008 Aaron Schulz
- * http://www.mediawiki.org/
+ * https://www.mediawiki.org/
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
index 1197552..e1e7992 100644 (file)
@@ -3,7 +3,7 @@
  * DjVu image handler.
  *
  * Copyright © 2006 Brion Vibber <brion@pobox.com>
- * http://www.mediawiki.org/
+ * https://www.mediawiki.org/
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
index 0602986..5dc9590 100644 (file)
@@ -5,7 +5,7 @@
  * difference. Will run forever until it finds one or you kill it.
  *
  * Copyright (C) 2004 Brion Vibber <brion@pobox.com>
- * http://www.mediawiki.org/
+ * https://www.mediawiki.org/
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
index c5c1be5..61c315f 100644 (file)
@@ -4,7 +4,7 @@
  * http://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt
  *
  * Copyright © 2004 Brion Vibber <brion@pobox.com>
- * http://www.mediawiki.org/
+ * https://www.mediawiki.org/
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
index 5a091af..f6f7dbb 100644 (file)
@@ -3,7 +3,7 @@
  * Unicode normalization routines
  *
  * Copyright © 2004 Brion Vibber <brion@pobox.com>
- * http://www.mediawiki.org/
+ * https://www.mediawiki.org/
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
index 89de929..59a64a3 100644 (file)
@@ -3,7 +3,7 @@
  * Approximate benchmark for some basic operations.
  *
  * Copyright © 2004 Brion Vibber <brion@pobox.com>
- * http://www.mediawiki.org/
+ * https://www.mediawiki.org/
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
index f392df5..676f8f7 100644 (file)
@@ -4,7 +4,7 @@
  * and supplementary files.
  *
  * Copyright (C) 2004 Brion Vibber <brion@pobox.com>
- * http://www.mediawiki.org/
+ * https://www.mediawiki.org/
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
index 9732d76..9ae6f23 100644 (file)
@@ -5,7 +5,7 @@
  * to test regression on mem usage (bug 28146)
  *
  * Copyright © 2004-2011 Brion Vibber <brion@wikimedia.org>
- * http://www.mediawiki.org/
+ * https://www.mediawiki.org/
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
index ad913b1..7be5251 100644 (file)
@@ -4,7 +4,7 @@
  * http://www.unicode.org/Public/UNIDATA/NormalizationTest.txt
  *
  * Copyright © 2004 Brion Vibber <brion@pobox.com>
- * http://www.mediawiki.org/
+ * https://www.mediawiki.org/
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
index e8fec93..443516b 100644 (file)
@@ -4,7 +4,7 @@
  * Should probably merge them for consistency.
  *
  * Copyright © 2004 Brion Vibber <brion@pobox.com>
- * http://www.mediawiki.org/
+ * https://www.mediawiki.org/
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
index f6fe243..4a27692 100644 (file)
@@ -3,7 +3,7 @@
  * Classes to cache objects in PHP accelerators, SQL database or DBA files
  *
  * Copyright © 2003-2004 Brion Vibber <brion@pobox.com>
- * http://www.mediawiki.org/
+ * https://www.mediawiki.org/
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
index a2eb698..cbc060a 100644 (file)
@@ -107,7 +107,7 @@ class CoreTagHooks {
         * Renders a thumbnail list of the given images, with optional captions.
         * Full syntax documented on the wiki:
         *
-        *   http://www.mediawiki.org/wiki/Help:Images#Gallery_syntax
+        *   https://www.mediawiki.org/wiki/Help:Images#Gallery_syntax
         *
         * @todo break Parser::renderImageGallery out here too.
         *
index 340f462..f2c4fbf 100644 (file)
@@ -1293,19 +1293,19 @@ class Parser {
                        if ( substr( $m[0], 0, 3 ) === 'RFC' ) {
                                $keyword = 'RFC';
                                $urlmsg = 'rfcurl';
-                               $CssClass = 'mw-magiclink-rfc';
+                               $cssClass = 'mw-magiclink-rfc';
                                $id = $m[4];
                        } elseif ( substr( $m[0], 0, 4 ) === 'PMID' ) {
                                $keyword = 'PMID';
                                $urlmsg = 'pubmedurl';
-                               $CssClass = 'mw-magiclink-pmid';
+                               $cssClass = 'mw-magiclink-pmid';
                                $id = $m[4];
                        } else {
                                throw new MWException( __METHOD__ . ': unrecognised match type "' .
                                        substr( $m[0], 0, 20 ) . '"' );
                        }
                        $url = wfMessage( $urlmsg, $id )->inContentLanguage()->text();
-                       return Linker::makeExternalLink( $url, "{$keyword} {$id}", true, $CssClass );
+                       return Linker::makeExternalLink( $url, "{$keyword} {$id}", true, $cssClass );
                } elseif ( isset( $m[5] ) && $m[5] !== '' ) {
                        # ISBN
                        $isbn = $m[5];
@@ -1684,6 +1684,7 @@ class Parser {
                wfProfileOut( __METHOD__ );
                return $s;
        }
+
        /**
         * Get the rel attribute for a particular external link.
         *
@@ -1703,6 +1704,7 @@ class Parser {
                }
                return null;
        }
+
        /**
         * Get an associative array of additional HTML attributes appropriate for a
         * particular external link.  This currently may include rel => nofollow
@@ -5922,7 +5924,7 @@ class Parser {
 
                # Strip external link markup
                # @todo FIXME: Not tolerant to blank link text
-               # I.E. [http://www.mediawiki.org] will render as [1] or something depending
+               # I.E. [https://www.mediawiki.org] will render as [1] or something depending
                # on how many empty links there are on the page - need to figure that out.
                $text = preg_replace( '/\[(?i:' . $this->mUrlProtocols . ')([^ ]+?) ([^[]+)\]/', '$2', $text );
 
index 6b2a874..0e7d42a 100644 (file)
@@ -1144,14 +1144,12 @@ class PPFrame_DOM implements PPFrame {
                                                || ( $flags & PPFrame::STRIP_COMMENTS )
                                        ) {
                                                $out .= '';
-                                       }
-                                       # Add a strip marker in PST mode so that pstPass2() can run some old-fashioned regexes on the result
-                                       # Not in RECOVER_COMMENTS mode (extractSections) though
-                                       elseif ( $this->parser->ot['wiki'] && !( $flags & PPFrame::RECOVER_COMMENTS ) ) {
+                                       } elseif ( $this->parser->ot['wiki'] && !( $flags & PPFrame::RECOVER_COMMENTS ) ) {
+                                               # Add a strip marker in PST mode so that pstPass2() can run some old-fashioned regexes on the result
+                                               # Not in RECOVER_COMMENTS mode (extractSections) though
                                                $out .= $this->parser->insertStripItem( $contextNode->textContent );
-                                       }
-                                       # Recover the literal comment in RECOVER_COMMENTS and pre+no-remove
-                                       else {
+                                       } else {
+                                               # Recover the literal comment in RECOVER_COMMENTS and pre+no-remove
                                                $out .= $contextNode->textContent;
                                        }
                                } elseif ( $contextNode->nodeName == 'ignore' ) {
index c2ab54e..deaf288 100644 (file)
@@ -440,9 +440,7 @@ class Preprocessor_Hash implements Preprocessor {
                                        $extNode->addChild( PPNode_Hash_Tree::newWithText( 'close', $close ) );
                                }
                                $accum->addNode( $extNode );
-                       }
-
-                       elseif ( $found == 'line-start' ) {
+                       } elseif ( $found == 'line-start' ) {
                                // Is this the start of a heading?
                                // Line break belongs before the heading element in any case
                                if ( $fakeLineStart ) {
@@ -1065,14 +1063,12 @@ class PPFrame_Hash implements PPFrame {
                                                || ( $flags & PPFrame::STRIP_COMMENTS )
                                        ) {
                                                $out .= '';
-                                       }
-                                       # Add a strip marker in PST mode so that pstPass2() can run some old-fashioned regexes on the result
-                                       # Not in RECOVER_COMMENTS mode (extractSections) though
-                                       elseif ( $this->parser->ot['wiki'] && !( $flags & PPFrame::RECOVER_COMMENTS ) ) {
+                                       } elseif ( $this->parser->ot['wiki'] && !( $flags & PPFrame::RECOVER_COMMENTS ) ) {
+                                               # Add a strip marker in PST mode so that pstPass2() can run some old-fashioned regexes on the result
+                                               # Not in RECOVER_COMMENTS mode (extractSections) though
                                                $out .= $this->parser->insertStripItem( $contextNode->firstChild->value );
-                                       }
-                                       # Recover the literal comment in RECOVER_COMMENTS and pre+no-remove
-                                       else {
+                                       } else {
+                                               # Recover the literal comment in RECOVER_COMMENTS and pre+no-remove
                                                $out .= $contextNode->firstChild->value;
                                        }
                                } elseif ( $contextNode->name == 'ignore' ) {
@@ -1389,6 +1385,7 @@ class PPTemplateFrame_Hash extends PPFrame_Hash {
                $s .= '}';
                return $s;
        }
+
        /**
         * Returns true if there are no arguments in this frame
         *
index 235a5ad..a26ef68 100644 (file)
@@ -227,15 +227,17 @@ class Profiler {
                $bit = array_pop( $this->mWorkStack );
 
                if ( !$bit ) {
-                       $this->debug( "Profiling error, !\$bit: $functionname\n" );
+                       $this->debugGroup( 'profileerror', "Profiling error, !\$bit: $functionname" );
                } else {
                        if ( $functionname == 'close' ) {
-                               $message = "Profile section ended by close(): {$bit[0]}";
-                               $this->debug( "$message\n" );
-                               $this->mStack[] = array( $message, 0, 0.0, 0, 0.0, 0 );
+                               if ( $bit[0] != '-total' ) {
+                                       $message = "Profile section ended by close(): {$bit[0]}";
+                                       $this->debugGroup( 'profileerror', $message );
+                                       $this->mStack[] = array( $message, 0, 0.0, 0, 0.0, 0 );
+                               }
                        } elseif ( $bit[0] != $functionname ) {
                                $message = "Profiling error: in({$bit[0]}), out($functionname)";
-                               $this->debug( "$message\n" );
+                               $this->debugGroup( 'profileerror', $message );
                                $this->mStack[] = array( $message, 0, 0.0, 0, 0.0, 0 );
                        }
                        $bit[] = $time;
@@ -324,7 +326,7 @@ class Profiler {
                                        list( $method, $realtime ) = $info;
                                        $msg .= sprintf( "%d\t%.6f\t%s\n", $i, $realtime, $method );
                                }
-                               wfDebugLog( 'DBPerformance', $msg );
+                               $this->debugGroup( 'DBPerformance', $msg );
                        }
                        unset( $this->mDBTrxHoldingLocks[$name] );
                        unset( $this->mDBTrxMethodTimes[$name] );
@@ -720,6 +722,18 @@ class Profiler {
                }
        }
 
+       /**
+        * Add an entry in the debug log group
+        *
+        * @param string $group Group to send the message to
+        * @param string $s to output
+        */
+       function debugGroup( $group, $s ) {
+               if ( function_exists( 'wfDebugLog' ) ) {
+                       wfDebugLog( $group, $s );
+               }
+       }
+
        /**
         * Get the content type sent out to the client.
         * Used for profilers that output instead of store data.
index e81c6ec..5ecfc21 100644 (file)
@@ -90,7 +90,7 @@ class ProfilerMwprof extends Profiler {
                // Check for unbalanced profileIn / profileOut calls.
                // Bad entries are logged but not sent.
                if ( $inName !== $outName ) {
-                       wfDebugLog( 'ProfilerUnbalanced', json_encode( array( $inName, $outName ) ) );
+                       $this->debugGroup( 'ProfilerUnbalanced', json_encode( array( $inName, $outName ) ) );
                        return;
                }
 
index ee92c17..7d78e36 100644 (file)
@@ -102,17 +102,18 @@ class ProfilerSimple extends Profiler {
                list( $ofname, /* $ocount */, $ortime, $octime ) = array_pop( $this->mWorkStack );
 
                if ( !$ofname ) {
-                       $this->debug( "Profiling error: $functionname\n" );
+                       $this->debugGroup( 'profileerror', "Profiling error: $functionname" );
                } else {
                        if ( $functionname == 'close' ) {
-                               $message = "Profile section ended by close(): {$ofname}";
-                               $functionname = $ofname;
-                               $this->debug( "$message\n" );
-                               $this->mCollated[$message] = $this->errorEntry;
-                       }
-                       elseif ( $ofname != $functionname ) {
+                               if ( $ofname != '-total' ) {
+                                       $message = "Profile section ended by close(): {$ofname}";
+                                       $functionname = $ofname;
+                                       $this->debugGroup( 'profileerror', $message );
+                                       $this->mCollated[$message] = $this->errorEntry;
+                               }
+                       } elseif ( $ofname != $functionname ) {
                                $message = "Profiling error: in({$ofname}), out($functionname)";
-                               $this->debug( "$message\n" );
+                               $this->debugGroup( 'profileerror', $message );
                                $this->mCollated[$message] = $this->errorEntry;
                        }
                        $elapsedcpu = $this->getTime( 'cpu' ) - $octime;
index 207e96b..64fafd7 100644 (file)
@@ -42,7 +42,8 @@ class ResourceLoaderStartUpModule extends ResourceLoaderModule {
                        $wgEnableAPI, $wgEnableWriteAPI, $wgDBname,
                        $wgSitename, $wgFileExtensions, $wgExtensionAssetsPath,
                        $wgCookiePrefix, $wgResourceLoaderMaxQueryLength,
-                       $wgResourceLoaderStorageEnabled, $wgResourceLoaderStorageVersion;
+                       $wgResourceLoaderStorageEnabled, $wgResourceLoaderStorageVersion,
+                       $wgSearchType;
 
                $mainPage = Title::newMainPage();
 
@@ -71,6 +72,7 @@ class ResourceLoaderStartUpModule extends ResourceLoaderModule {
                        'wgScriptPath' => $wgScriptPath,
                        'wgScriptExtension' => $wgScriptExtension,
                        'wgScript' => $wgScript,
+                       'wgSearchType' => $wgSearchType,
                        'wgVariantArticlePath' => $wgVariantArticlePath,
                        // Force object to avoid "empty" associative array from
                        // becoming [] instead of {} in JS (bug 34604)
@@ -149,24 +151,22 @@ class ResourceLoaderStartUpModule extends ResourceLoaderModule {
                        // seem to do that, and custom implementations might forget. Coerce it to TS_UNIX
                        $moduleMtime = wfTimestamp( TS_UNIX, $module->getModifiedTime( $context ) );
                        $mtime = max( $moduleMtime, wfTimestamp( TS_UNIX, $wgCacheEpoch ) );
-                       // Modules without dependencies, a group or a foreign source pass two arguments (name, timestamp) to
-                       // mw.loader.register()
+
                        if ( !count( $deps ) && $group === null && $source === 'local' ) {
+                               // Modules without dependencies, a group or a foreign source pass two arguments (name, timestamp) to
+                               // mw.loader.register()
                                $registrations[] = array( $name, $mtime );
-                       }
-                       // Modules with dependencies but no group or foreign source pass three arguments
-                       // (name, timestamp, dependencies) to mw.loader.register()
-                       elseif ( $group === null && $source === 'local' ) {
+                       } elseif ( $group === null && $source === 'local' ) {
+                               // Modules with dependencies but no group or foreign source pass three arguments
+                               // (name, timestamp, dependencies) to mw.loader.register()
                                $registrations[] = array( $name, $mtime, $deps );
-                       }
-                       // Modules with a group but no foreign source pass four arguments (name, timestamp, dependencies, group)
-                       // to mw.loader.register()
-                       elseif ( $source === 'local' ) {
+                       } elseif ( $source === 'local' ) {
+                               // Modules with a group but no foreign source pass four arguments (name, timestamp, dependencies, group)
+                               // to mw.loader.register()
                                $registrations[] = array( $name, $mtime, $deps, $group );
-                       }
-                       // Modules with a foreign source pass five arguments (name, timestamp, dependencies, group, source)
-                       // to mw.loader.register()
-                       else {
+                       } else {
+                               // Modules with a foreign source pass five arguments (name, timestamp, dependencies, group, source)
+                               // to mw.loader.register()
                                $registrations[] = array( $name, $mtime, $deps, $group, $source );
                        }
                }
@@ -221,7 +221,6 @@ class ResourceLoaderStartUpModule extends ResourceLoaderModule {
                return  wfAppendQuery( wfScript( 'load' ), $query );
        }
 
-
        /**
         * @param $context ResourceLoaderContext
         * @return string
index 0509008..7992882 100644 (file)
@@ -687,6 +687,7 @@ class RevDel_FileItem extends RevDel_Item {
                }
                return '<span class="history-deleted">' . $link . '</span>';
        }
+
        /**
         * Generate a user tool link cluster if the current user is allowed to view it
         * @return string HTML
index eea723b..45d0044 100644 (file)
@@ -439,6 +439,7 @@ class SearchEngine {
                $lc = $this->legalSearchChars();
                return trim( preg_replace( "/[^{$lc}]/", " ", $text ) );
        }
+
        /**
         * Load up the appropriate search engine class for the currently
         * active database backend, and return a configured instance.
@@ -775,6 +776,7 @@ class SearchResult {
                $result->initFromTitle( $title );
                return $result;
        }
+
        /**
         * Return a new SearchResult and initializes it with a row.
         *
@@ -986,23 +988,28 @@ class SearchResult {
                return false;
        }
 }
+
 /**
  * A SearchResultSet wrapper for SearchEngine::getNearMatch
  */
 class SearchNearMatchResultSet extends SearchResultSet {
        private $fetched = false;
+
        /**
         * @param $match mixed Title if matched, else null
         */
        public function __construct( $match ) {
                $this->result = $match;
        }
+
        public function hasResult() {
                return (bool)$this->result;
        }
+
        public function numRows() {
                return $this->hasResults() ? 1 : 0;
        }
+
        public function next() {
                if ( $this->fetched || !$this->result ) {
                        return false;
index aec6a01..c3edf51 100644 (file)
@@ -3,7 +3,7 @@
  * MySQL search engine
  *
  * Copyright (C) 2004 Brion Vibber <brion@pobox.com>
- * http://www.mediawiki.org/
+ * https://www.mediawiki.org/
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
index cea17d2..2603161 100644 (file)
@@ -3,7 +3,7 @@
  * Oracle search engine
  *
  * Copyright © 2004 Brion Vibber <brion@pobox.com>
- * http://www.mediawiki.org/
+ * https://www.mediawiki.org/
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -230,6 +230,7 @@ class SearchOracle extends SearchDatabase {
                $t = preg_replace( '/([-&|])/', '\\\\$1', $t );
                return $t;
        }
+
        /**
         * Create or update the search index record for the given page.
         * Title and text should be pre-processed.
index c9f5466..142e5fd 100644 (file)
@@ -3,7 +3,7 @@
  * PostgreSQL search engine
  *
  * Copyright © 2006-2007 Greg Sabino Mullane <greg@turnstep.com>
- * http://www.mediawiki.org/
+ * https://www.mediawiki.org/
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -140,8 +140,8 @@ class SearchPostgres extends SearchDatabase {
                $searchstring = $this->parseQuery( $term );
 
                ## We need a separate query here so gin does not complain about empty searches
-               $SQL = "SELECT to_tsquery($searchstring)";
-               $res = $this->db->query( $SQL );
+               $sql = "SELECT to_tsquery($searchstring)";
+               $res = $this->db->query( $sql );
                if ( !$res ) {
                        ## TODO: Better output (example to catch: one 'two)
                        die( "Sorry, that was not a valid search string. Please go back and try again" );
@@ -196,10 +196,10 @@ class SearchPostgres extends SearchDatabase {
 
        function update( $pageid, $title, $text ) {
                ## We don't want to index older revisions
-               $SQL = "UPDATE pagecontent SET textvector = NULL WHERE old_id IN " .
+               $sql = "UPDATE pagecontent SET textvector = NULL WHERE old_id IN " .
                                "(SELECT rev_text_id FROM revision WHERE rev_page = " . intval( $pageid ) .
                                " ORDER BY rev_text_id DESC OFFSET 1)";
-               $this->db->query( $SQL );
+               $this->db->query( $sql );
                return true;
        }
 
@@ -217,6 +217,7 @@ class PostgresSearchResult extends SearchResult {
                parent::__construct( $row );
                $this->score = $row->score;
        }
+
        function getScore() {
                return $this->score;
        }
index e5ce48f..91a2de2 100644 (file)
@@ -169,6 +169,7 @@ class SpecialPage {
        function isListed() {
                return $this->mListed;
        }
+
        /**
         * Set whether this page is listed in Special:Specialpages, at run-time
         * @since 1.3
@@ -178,6 +179,7 @@ class SpecialPage {
        function setListed( $listed ) {
                return wfSetVar( $this->mListed, $listed );
        }
+
        /**
         * Get or set whether this special page is listed in Special:SpecialPages
         * @since 1.6
index 2ac34eb..29722c8 100644 (file)
@@ -3,7 +3,7 @@
  * Implements Special:Import
  *
  * Copyright © 2003,2005 Brion Vibber <brion@pobox.com>
- * http://www.mediawiki.org/
+ * https://www.mediawiki.org/
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
index 1d0a302..05c8872 100644 (file)
@@ -66,26 +66,31 @@ class SpecialRevisionDelete extends UnlistedSpecialPage {
                        'check-label' => 'revdelete-hide-text',
                        'success' => 'revdelete-success',
                        'failure' => 'revdelete-failure',
+                       'text' => 'revdelete-text-text',
                ),
                'archive' => array(
                        'check-label' => 'revdelete-hide-text',
                        'success' => 'revdelete-success',
                        'failure' => 'revdelete-failure',
+                       'text' => 'revdelete-text-text',
                ),
                'oldimage' => array(
                        'check-label' => 'revdelete-hide-image',
                        'success' => 'revdelete-success',
                        'failure' => 'revdelete-failure',
+                       'text' => 'revdelete-text-file',
                ),
                'filearchive' => array(
                        'check-label' => 'revdelete-hide-image',
                        'success' => 'revdelete-success',
                        'failure' => 'revdelete-failure',
+                       'text' => 'revdelete-text-file',
                ),
                'logging' => array(
                        'check-label' => 'revdelete-hide-name',
                        'success' => 'logdelete-success',
                        'failure' => 'logdelete-failure',
+                       'text' => 'logdelete-text',
                ),
        );
 
@@ -328,7 +333,7 @@ class SpecialRevisionDelete extends UnlistedSpecialPage {
         * which will allow the user to choose new visibility settings.
         */
        protected function showForm() {
-               $UserAllowed = true;
+               $userAllowed = true;
 
                if ( $this->typeName == 'logging' ) {
                        $this->getOutput()->addWikiMsg( 'logdelete-selected', $this->getLanguage()->formatNum( count( $this->ids ) ) );
@@ -348,7 +353,7 @@ class SpecialRevisionDelete extends UnlistedSpecialPage {
                                if ( !$this->submitClicked ) {
                                        throw new PermissionsError( 'suppressrevision' );
                                }
-                               $UserAllowed = false;
+                               $userAllowed = false;
                        }
                        $numRevisions++;
                        $this->getOutput()->addHTML( $item->getHTML() );
@@ -363,7 +368,7 @@ class SpecialRevisionDelete extends UnlistedSpecialPage {
                $this->addUsageText();
 
                // Normal sysops can always see what they did, but can't always change it
-               if ( !$UserAllowed ) {
+               if ( !$userAllowed ) {
                        return;
                }
 
@@ -431,7 +436,7 @@ class SpecialRevisionDelete extends UnlistedSpecialPage {
         * @todo FIXME: Wikimedia-specific policy text
         */
        protected function addUsageText() {
-               $this->getOutput()->addWikiMsg( 'revdelete-text' );
+               $this->getOutput()->wrapWikiMsg( "<strong>$1</strong>\n$2", $this->typeLabels['text'], 'revdelete-text-others' );
                if ( $this->getUser()->isAllowed( 'suppressrevision' ) ) {
                        $this->getOutput()->addWikiMsg( 'revdelete-suppress-text' );
                }
index f26d1a6..56f3f41 100644 (file)
@@ -151,6 +151,7 @@ class SpecialStatistics extends SpecialPage {
                                                $this->getLanguage()->formatNum( $this->images ),
                                                array( 'class' => 'mw-statistics-files' ) );
        }
+
        private function getEditStats() {
                return Xml::openElement( 'tr' ) .
                        Xml::tags( 'th', array( 'colspan' => '2' ), $this->msg( 'statistics-header-edits' )->parse() ) .
index 27ba78e..35bbf0b 100644 (file)
@@ -315,6 +315,7 @@ class SpecialUpload extends SpecialPage {
                $form->setSubmitText( $this->msg( 'upload-tryagain' )->escaped() );
                $this->showUploadForm( $form );
        }
+
        /**
         * Stashes the upload, shows the main form, but adds a "continue anyway button".
         * Also checks whether there are actually warnings to display.
index aba0d27..d1aef1d 100644 (file)
@@ -220,7 +220,7 @@ class UsercreateTemplate extends BaseTemplate {
                                                                                echo 'checked="checked"';
                                                                        } ?>
                                                                >
-                                                               <?php $this->msg( $inputItem['msg'] ); ?>
+                                                               <?php $this->msgHtml( $inputItem['msg'] ); ?>
                                                        </label>
                                                <?php
                                                } else {
index 68097e3..c416d11 100644 (file)
@@ -146,7 +146,7 @@ class UserloginTemplate extends BaseTemplate {
 
                        <div>
                                <?php
-                               echo Html::input( 'wpLoginAttempt', $this->getMsg( 'pt-login' )->text(), 'submit', array(
+                               echo Html::input( 'wpLoginAttempt', $this->getMsg( 'pt-login-button' )->text(), 'submit', array(
                                        'id' => 'wpLoginAttempt',
                                        'tabindex' => '6',
                                        'class' => 'mw-ui-button mw-ui-big mw-ui-block mw-ui-constructive'
index 01ed044..3fe18ee 100644 (file)
@@ -1145,8 +1145,6 @@ U kan wel hierdie verskil sien. Meer details kan in die [{{fullurl:{{#Special:Lo
 'revdelete-show-file-submit' => 'Ja',
 'revdelete-selected' => "'''Geselekteerde {{PLURAL:$2|wysiging|wysigings}} vir [[:$1]]:'''",
 'logdelete-selected' => "'''Geselekteerde {{PLURAL:$1|logboek aksie|logboek aksies}}:'''",
-'revdelete-text' => "'''Geskrapte wysigings en aksies sal in die geskiedenis en logboeke sigbaar bly, maar dele van die inhoud sal nie publiek toeganklik wees nie.'''
-Ander administrateurs van {{SITENAME}} kan steeds die verborge inhoud sien en die verwydering met behulp van die vorm ongedaan maak, tensy aanvullende beperkinge deur die stelseladministrateur opgelê is.",
 'revdelete-confirm' => 'Bevestig asseblief dat u dit wil doen, dat u die nagevolge verstaan en dat u dit doen in ooreenstemming met die [[{{MediaWiki:Policy-url}}|beleid]].',
 'revdelete-suppress-text' => "Verberging van weergawes mag '''slegs''' in die volgende gevalle gebruik word:
 * Potensieel lasterlike inligting
index 0fcdf7c..acb5d1d 100644 (file)
@@ -104,7 +104,6 @@ $messages = array(
 'tog-ccmeonemails' => 'Më ço kopje të mesazheve qi ua dërgoj të tjerëve',
 'tog-diffonly' => 'Mos e trego përmbajtjen e faqes nën ndryshimin',
 'tog-showhiddencats' => 'Trego kategoritë e mshefta',
-'tog-noconvertlink' => 'Mos lejo konvertimin e titullit vegëz',
 'tog-norollbackdiff' => 'Trego ndryshimin mbas procedurës së kthimit mbrapa',
 'tog-useeditwarning' => 'Paralajmëron mua kur unë të lë një redakto faqe me ndryshimet e para shpëtimit',
 
@@ -796,7 +795,6 @@ Shiko tek [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} regjistr
 'revdelete-no-file' => 'Skeda e dhënë nuk ekziston.',
 'revdelete-selected' => "'''{{PLURAL:$2|Versioni i zgjedhur i|Versionet e zgjedhura të}} [[:$1]]:'''",
 'logdelete-selected' => "'''{{PLURAL:$1|Veprimi i zgjedhur në regjistër|Veprimet e zgjedhura në regjistër}}:'''",
-'revdelete-text' => "'''Përmbajtja dhe pjesët e tjera nuk janë të dukshme për të gjithë, por figurojnë në historikun e versioneve.''' Administratorët munden përmbajtjen e larguar ta shikojnë dhe restaurojnë, përveç në rastet kur një gjë e tillë është ndaluar ekstra.",
 'revdelete-legend' => 'Vendosni kufizimet për versionin:',
 'revdelete-hide-text' => 'Fshihe tekstin e versionit',
 'revdelete-hide-image' => 'Fshih përmbajtjen skedare',
index d4726be..bba364c 100644 (file)
@@ -915,8 +915,6 @@ Encara puet veyer a comparanza; en trobará mas detalles en o [{{fullurl:{{#Spec
 'revdelete-show-file-submit' => 'Sí',
 'revdelete-selected' => "'''{{PLURAL:$2|Versión trigata|Versions trigatas}} de [[:$1]]:'''",
 'logdelete-selected' => "'''{{PLURAL:$1|Escaicimiento d'o rechistro trigato|Escaicimientos d'o rechistro trigatos}}:'''",
-'revdelete-text' => "'''As versions y esdevenimientos borratos encara apareixerán en o historial d'a pachina y en os rechistros, pero bellas partes d'o suyo conteniu serán inaccesibles ta o publico.'''
-Atros admenistradors de {{SITENAME}} encara podrán acceder t'o conteniu amagato y podrán desfer o borrau a traviés d'ista mesma interfaz, fueras de si s'estableixen restriccions adicionals.",
 'revdelete-confirm' => "Por favor confirme que ye mirando de fer ísto, que entiende as conseqüencias, y que lo ye fendo d'alcuerdo con [[{{MediaWiki:Policy-url}}|as politicas]].",
 'revdelete-suppress-text' => "Os borraus de versions '''nomás''' s'habrían de fer en os siguients casos:
 * Información potencialment difamatoria o libelo grieu.
index 689f479..8551bfc 100644 (file)
@@ -1461,8 +1461,6 @@ $2
 'revdelete-show-file-submit' => 'نعم',
 'revdelete-selected' => "'''{{PLURAL:$2|المراجعة المختارة|المراجعات المختارة}} ل[[:$1]]:'''",
 'logdelete-selected' => "'''{{PLURAL:$1|حدث السجل المختار|أحداث السجل المختارة}}:'''",
-'revdelete-text' => "'''المراجعات والأحداث المحذوفة ستظل تظهر في تاريخ الصفحة والسجلات،'''
-لكن أجزاء من محتواها لن يكون مسموحا للعامة برؤيتها.",
 'revdelete-confirm' => 'الإداريون الآخرون في {{SITENAME}} سيظل بإمكانهم رؤية المحتوى المخفي ويمكنهم استرجاعه مجددا من خلال هذه الواجهة نفسها، مالم يتم وضع قيود إضافية.
 من فضلك أكد أنك تنوي فعل هذا، وأنك تفهم العواقب، وأنك تفعل هذا بالتوافق مع [[{{MediaWiki:Policy-url}}|السياسة]].',
 'revdelete-suppress-text' => "ينبغي للإخفاء أن يستخدم '''فقط''' في الحالات التالية:
index 623ba8c..e374ac1 100644 (file)
@@ -1102,8 +1102,6 @@ $2',
 'revdelete-show-file-submit' => 'ايوه',
 'revdelete-selected' => "'''{{PLURAL:$2|المراجعه المختاره|المراجعات المختاره}} بتاعة [[:$1]]:'''",
 'logdelete-selected' => "'''{{PLURAL:$1|حدث السجل المختار|أحداث السجل المختارة}}:'''",
-'revdelete-text' => "'''المراجعات و الاحداث الممسوحه ح تنيها تظهر فى تاريخ الصفحه و فى السجلات, بس فى اجزاء من محتواها مش ح تبقا متاحه لكل الناس .'''
-الاداريين التانيين فى  {{SITENAME}} ح يقدرو يوصول للمحتوى المخفىو كمان ممكن يرجعو المسح عن طريق نفس الواجه دى ، الا اذا اتحطت قيود اضافيه.",
 'revdelete-confirm' => 'لو سمحت اتأكدد انك ناوى تعمل كدا, و انك فاهم اللى ح يترتب على كدا, و انك بتعمل كدا بالتوافق مع مع [[{{MediaWiki:Policy-url}}|السياسه]].',
 'revdelete-suppress-text' => "الكبت لازم ييتعمل '''بس''' فى الحالات دى:
 * معلومات شخصيه مش مناسبه
index 811ae87..ed0d458 100644 (file)
@@ -1143,8 +1143,6 @@ $3 য়ে আগবঢ়োৱা ইয়াৰ কাৰণ হৈছে
 'revdelete-show-file-submit' => 'হয়',
 'revdelete-selected' => "'''[[:$1]]-ৰ {{PLURAL:$2|নিৰ্বাচিত সংশোধন|নিৰ্বাচিত সংশোধনসমূহ}}:'''",
 'logdelete-selected' => "'''{{PLURAL:$1|টা নিৰ্বাচিত ল’গ ভৰ্তি|টা নিৰ্বাচিত ল’গ ভৰ্তি}}:'''",
-'revdelete-text' => "'''বিলোপ কৰা সংশোধনবোৰ আৰু ঘটনাবোৰ পৃষ্ঠাৰ ইতিহাস আৰু ল’গত পোৱা যাব, কিন্তু তাৰ কিছু অংশ সৰ্বসাধাৰণৰ বাবে মুকলি নহ’ব ।''' 
-{{SITENAME}} ৰ অন্য প্ৰশাসকসকলে তথাপিও লুকুৱাই থোৱা বিষয়বস্তু দেখা পাব আৰু কোনো সীমাবদ্ধতা নাথাকিলে একেটা ইণ্টাৰফে’চৰ জৰিয়তে ইয়াক পুনৰুদ্ধাৰ কৰিব পাৰিব ।",
 'revdelete-confirm' => 'অনুগ্ৰহ কৰি সাব্যস্ত কৰক যে আপুনি ইয়াৰ পৰিণাম বুজি আৰু [[{{MediaWiki:Policy-url}}|the policy]] ৰ সৈতে সহমত হৈ এই কামটো কৰিব বিচাৰিছে |',
 'revdelete-suppress-text' => "নিবাৰণ '''কেৱল''' তলত দিয়া কাৰণসমূহত ব্যৱহৃত হ’ব:
 * সম্ভাব্য ক্ষতিকাৰক তথ্য 
index 63a73ff..538fcaf 100644 (file)
@@ -1045,8 +1045,6 @@ Pues ver el diff; los detalles s'alcuentren nel [{{fullurl:{{#Special:Log}}/supr
 'revdelete-show-file-submit' => 'Sí',
 'revdelete-selected' => "'''{{PLURAL:$2|Revisión seleicionada|Revisiones seleicionaes}} de [[:$1]]:'''",
 'logdelete-selected' => "'''{{PLURAL:$1|Socesu del rexistru seleicionáu|Socesos del rexistru seleicionaos}}:'''",
-'revdelete-text' => "'''Les revisiones y socesos desaniciaos van siguir apaeciendo nel historial de la páxina y nos rexistros, pero parte del so conteníu nun va ser accesible pal públicu.'''
-Otros alministradores de {{SITENAME}} van siguir pudiendo acceder al conteníu anubríu y puen restauralu de nuevo al traviés d'esta mesma interfaz, a nun ser que s'establezan otres restricciones.",
 'revdelete-confirm' => "Confirma que quies facer esto, qu'entiendes les consecuencies, y que vas facer esto d'alcuerdo [[{{MediaWiki:Policy-url}}|cola política]].",
 'revdelete-suppress-text' => "La supresión '''namái''' tendría d'usase nos casos darréu:
 * Información que pudiere ser bilordiosa
index 628c8f3..69cc39d 100644 (file)
@@ -15,6 +15,7 @@
  * @author Emperyan
  * @author Erdemaslancan
  * @author Gulmammad
+ * @author Interfase
  * @author Kaganer
  * @author Khan27
  * @author Matma Rex
@@ -204,7 +205,7 @@ $messages = array(
 'category_header' => '"$1" kateqoriyasındakı məqalələr',
 'subcategories' => 'Alt kateqoriyalar',
 'category-media-header' => '"$1" kateqoriyasında mediya',
-'category-empty' => "''Bu kateqoriyanın tərkibi hal-hazırda boşdur.''",
+'category-empty' => '"Bu kateqoriya hal-hazırda boşdur."',
 'hidden-categories' => '{{PLURAL:$1|Gizli kateqoriya|Gizli kateqoriyalar}}',
 'hidden-category-category' => 'Gizli kateqoriyalar',
 'category-subcat-count' => '{{PLURAL:$2|Bu kateqoriya yalnız aşağıdakı altkateqoriyadan ibarətdir.|Cəmi $2 kateqoriyadan {{PLURAL:$1|altkateqoriya|$1 altkateqoriya}} göstərilmişdir.}}',
@@ -225,7 +226,7 @@ $messages = array(
 'moredotdotdot' => 'Daha...',
 'morenotlisted' => 'Bu siyahı tam deyil.',
 'mypage' => 'Səhifə',
-'mytalk' => 'Danışıqlarım',
+'mytalk' => 'Müzakirə',
 'anontalk' => 'Bu IP-yə aid müzakirə',
 'navigation' => 'Naviqasiya',
 'and' => '&#32;və',
@@ -294,7 +295,7 @@ $messages = array(
 'articlepage' => 'Məqaləni nəzərdən keçir',
 'talk' => 'Müzakirə',
 'views' => 'Görünüş',
-'toolbox' => 'Alətlər qutusu',
+'toolbox' => 'Alətlər',
 'userpage' => 'İstifadəçi səhifəsini göstər',
 'projectpage' => 'Layihə səhifəsini göstər',
 'imagepage' => 'Fayl səhifəsini göstər',
@@ -352,10 +353,10 @@ Bax: [[Special:Version|Versiyalar]].',
 'pagetitle' => '$1 - {{SITENAME}}',
 'pagetitle-view-mainpage' => '{{SITENAME}}',
 'retrievedfrom' => 'Mənbə — "$1"',
-'youhavenewmessages' => 'Hal-hazırda $1 var. ($2)',
+'youhavenewmessages' => '{{PLURAL:$3|$3}} $1 var ($2).',
 'youhavenewmessagesfromusers' => '{{PLURAL:$3|Başqa bir istifadəçidən|$3 istifadəçidən}} $1 var ($2).',
-'youhavenewmessagesmanyusers' => 'Bir çox istifadəçidən $1 var ($2).',
-'newmessageslinkplural' => '{{PLURAL:$1|yeni mesajınız|yeni mesajlarınız}}',
+'youhavenewmessagesmanyusers' => 'Bir neçə istifadəçidən $1 var ($2).',
+'newmessageslinkplural' => '{{PLURAL:$1|yeni mesajınız|yeni mesajınız}}',
 'newmessagesdifflinkplural' => 'son {{PLURAL:$1|dəyişiklik|dəyişikliklər}}',
 'youhavenewmessagesmulti' => '"$1"da yeni mesajınız var.',
 'editsection' => 'redaktə',
@@ -427,7 +428,7 @@ Bu vəziyyət səhifənin, silinmiş bir səhifənin keçmiş versiyası olması
 
 Əgər niyə bu deyilsə, proqramda bir səhv ilə qarşılaşmış ola bilərsiniz.
 Xahiş edirik bunu bir [[Special:ListUsers/sysop|İdarəçilərə]], URL not edərək göndərin.',
-'missingarticle-rev' => '(təftiş № $1)',
+'missingarticle-rev' => '(versiya №: $1)',
 'missingarticle-diff' => '(fərq: $1, $2)',
 'readonly_lag' => 'Məlumatlar bazasının ikinci dərəcəli serveri əsas serverlə əlaqə yaradanadək məlumatlar bazası avtomatik olaraq bloklanmışdır',
 'internalerror' => 'Daxili xəta',
@@ -507,7 +508,7 @@ Siz {{SITENAME}} saytını anonim olaraq istifadə etməyə davam edə bilər v
 'userlogin-yourpassword' => 'Parol',
 'userlogin-yourpassword-ph' => 'Parolunuzu daxil edin',
 'createacct-yourpassword-ph' => 'Parol daxil edin',
-'yourpasswordagain' => 'Parolu təkrar yazın:',
+'yourpasswordagain' => 'Parolu təkrar daxil edin:',
 'createacct-yourpasswordagain' => 'Parolu təsdiqlə',
 'createacct-yourpasswordagain-ph' => 'Parolu təkrar daxil edin',
 'remembermypassword' => 'Məni bu kompyuterdə xatırla (maksimum $1 {{PLURAL:$1|gün|gün}})',
@@ -526,10 +527,10 @@ Siz {{SITENAME}} saytını anonim olaraq istifadə etməyə davam edə bilər v
 'notloggedin' => 'Daxil olmamısınız',
 'userlogin-noaccount' => 'İstifadəçi hesabınız yoxdur?',
 'userlogin-joinproject' => '{{SITENAME}} qoşulun',
-'nologin' => "İstifadəçi hesabınız yoxdur? '''$1'''.",
-'nologinlink' => 'hesab açın',
+'nologin' => 'İstifadəçi hesabınız yoxdur? $1.',
+'nologinlink' => 'Hesab yaradın',
 'createaccount' => 'Hesab aç',
-'gotaccount' => "Giriş hesabınız varsa '''$1'''.",
+'gotaccount' => "İstifadəçi hesabınız varmı? '''$1'''.",
 'gotaccountlink' => 'Daxil olun',
 'userlogin-resetlink' => 'Daxilolma məlumatlarınızı unutmusunuz?',
 'userlogin-resetpassword-link' => 'Parolu unutdunuzmu?',
@@ -626,6 +627,9 @@ Yeni cəhd etməzdən əvvəl bir qədər gözləyin.',
 'suspicious-userlogout' => 'Sizin çıxış üçün cəhdiniz uğursuz alındı. Bu, brouzerin yaxud proksi-keşləmənin düzgün işləməməsindən qaynaqlanır.',
 'createacct-another-realname-tip' => 'Gərçək adınız istəyə bağlıdır.
 Əgər gərçək adınızı göstərsəniz, çalışmalarınıza müraciət etmək üçün istifadə ediləcəkdir.',
+'pt-login' => 'Daxil ol',
+'pt-createaccount' => 'Akkaunt yarat',
+'pt-userlogout' => 'Çıxış',
 
 # Email sending
 'php-mail-error-unknown' => 'PHP-nin mail() funksiyasında naməlum xəta',
@@ -642,7 +646,7 @@ Sistemə daxil olmanı yekunlaşdırmaq üçün yeni parolu bura yazmalısınız
 'newpassword' => 'Yeni parol:',
 'retypenew' => 'Yeni parolu təkrar yazın:',
 'resetpass_submit' => 'Parol yaradın və sistemə daxil olun',
-'changepassword-success' => 'Parolunuz dəyişdirldi! Hazırda sistemə daxil olursunuz...',
+'changepassword-success' => 'Sizin parol uğurla dəyişdirildi!',
 'resetpass_forbidden' => 'Parolu dəyişmək mümkün deyil',
 'resetpass-no-info' => 'Bu səhifəni birbaşa açmaq üçün sistemə daxil olmalısınız.',
 'resetpass-submit-loggedin' => 'Parolu dəyiş',
@@ -734,9 +738,8 @@ Belə IP ünvan bir neçə fərd tərəfindən istifadədə ola bilər.
 'noarticletext' => 'Hal-hazırda bu səhifə boşdur. Başqa səhifələrdə eyni adda səhifəni [[Special:Search/{{PAGENAME}}| axtara]], əlaqəli qeydlərə
 <span class="plainlinks">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} baxa],
 və ya səhifəni [{{fullurl:{{FULLPAGENAME}}|action=edit}} redaktə]</span> edə bilərsiniz.',
-'noarticletext-nopermission' => 'Hal-hazırda bu səhifə boşdur. Başqa səhifələrdə eyni adda səhifəni [[Special:Search/{{PAGENAME}}| axtara]], əlaqəli qeydlərə
-<span class="plainlinks">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} baxa],
-və ya səhifəni [{{fullurl:{{FULLPAGENAME}}|action=edit}} redaktə]</span> edə bilərsiniz.',
+'noarticletext-nopermission' => 'Hal-hazırda bu səhifə boşdur. Başqa səhifələrdə eyni adlı səhifəni [[Special:Search/{{PAGENAME}}| axtara]], <span class="plainlinks">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} əlaqəli qeydlərə baxa],
+və ya səhifəni [{{fullurl:{{FULLPAGENAME}}|action=edit}} redaktə edə bilərsiniz]</span>, lakin sizin bu məqaləni yaratmaq hüququnuz yoxdur.',
 'userpage-userdoesnotexist' => '"<nowiki>$1</nowiki>" istifadəçi adı qeydiyyata alınmayıb.
 Əgər siz bu səhifəni yaratmaq/redaktə etmək istəyirsinizsə, xahiş edirik bunu yoxlayın.',
 'userpage-userdoesnotexist-view' => '"$1" istifadəçi hesabı qeydiyyatda deyil',
@@ -754,7 +757,7 @@ Bloklama qeydlərinin sonuncusu aşağıda göstərilmişdir:',
 '''Bu hələ yaddaşda saxlanılmayıb!'''",
 'updated' => '(yeniləndi)',
 'note' => "'''Qeyd:'''",
-'previewnote' => "'''Bu yalnız sınaq göstərişidir; dəyişikliklər hal-hazırda qeyd edilməmişdir!'''",
+'previewnote' => '<strong>Unutmayın ki, bu yalnız sınaq göstərişidir.</strong> Dəyişiklikləriniz hal-hazırda qeyd edilməmişdir!',
 'previewconflict' => 'Bu sınaq göstərişidir və yaddaşda saxlayacağınız təqdirdə mətnin redaktə səhifəsinin yuxarı hissəsində nəticənin necə olacağını göstərir.',
 'session_fail_preview' => "'''Üzr istəyirik! Sizin redaktəniz saxlanılmadı. Serverdə identifikasiyanızla bağlı problemlər yaranmışdır. Lütfən bir daha təkrar edin. Problem həll olunmazsa hesabınızdan çıxın və yenidən daxil olun.'''",
 'editing' => 'Redaktə $1',
@@ -815,6 +818,7 @@ Belə ki, bu adda səhifə artıq mövcuddur.',
 'post-expand-template-inclusion-warning' => "'''DİQQƏT!''' Daxil edilən şablonların həcmi həddindən artıq böyükdür.
 Bəzi şablonlar əlavə olunmayacaq.",
 'post-expand-template-inclusion-category' => 'Şablonun daxil olduğu səhifələrin ölçüsü böyükdür.',
+'post-expand-template-argument-warning' => '<strong>Diqqət:</strong> bu səhifədə açılma ölçüsü həddən artıq böyük olan ən azı bir şablon arqumenti var. Həmin arqumentlər buraxılıb.',
 'post-expand-template-argument-category' => 'Şablonlarda buraxılmış arqumentlərin mövcud olduğu səhifələr',
 'parser-template-loop-warning' => '[[$1]]: Şablonda düyün tapıldı',
 'parser-template-recursion-depth-warning' => '($1) Şablonda dərinlik limiti keçildi',
@@ -840,7 +844,7 @@ $3 tərəfindən verilən səbəb ''$2''",
 'revision-info' => '$2 tərəfindən yaradılmış $1 tarixli dəyişiklik',
 'previousrevision' => '←Əvvəlki versiya',
 'nextrevision' => 'Sonrakı versiya→',
-'currentrevisionlink' => 'Hal-hazırkı versiyanı göstər',
+'currentrevisionlink' => 'Hal-hazırkı versiya',
 'cur' => 'hh',
 'next' => 'sonrakı',
 'last' => 'son',
@@ -859,7 +863,7 @@ Açıqlama: <strong>({{int:cur}})</strong> = hal-hazırkı versiya ilə olan fə
 # Revision feed
 'history-feed-title' => 'Redaktə tarixçəsi',
 'history-feed-description' => 'Vikidə bu səhifənin dəyişikliklər tarixçəsi',
-'history-feed-item-nocomment' => '$1-dən $2-yə',
+'history-feed-item-nocomment' => '$1 $2-də',
 'history-feed-empty' => 'Axtardığınız səhifə mövcud deyil.
 Çox guman ki, bu səhifə silinib və ya onun adı dəyişdirilib.
 Vikidə buna bənzər səhifələri [[Special:Search|axtarmağa]] cəhd edin.',
@@ -969,7 +973,7 @@ $1",
 'shown-title' => 'Səhifə üçün $1 {{PLURAL:$1|nəticə|nəticəyə}} bax',
 'viewprevnext' => 'Göstər ($1 {{int:pipe-separator}} $2) ($3).',
 'searchmenu-exists' => "'''Bu vikidə \"[[:\$1]]\" adında səhifə mövcuddur'''",
-'searchmenu-new' => "'''Bu vikidə \"[[:\$1]]\" səhifəsini yarat!'''",
+'searchmenu-new' => '<strong>Bu vikidə "[[:$1]]" səhifəsini yarat!</strong> {{PLURAL:$2|0=|Həmçinin, axtarışınız əsasında çıxan səhifəyə baxın.|Həmçinin, axtarışınız əsasında çıxan nəticələrə baxın.}}',
 'searchprofile-articles' => 'Məqalələr',
 'searchprofile-project' => 'Kömək və Layihə səhifələri',
 'searchprofile-images' => 'Multimedia',
@@ -991,7 +995,7 @@ $1",
 'search-interwiki-more' => '(yenə)',
 'search-relatedarticle' => 'əlaqədar',
 'searcheverything-enable' => 'Ad aralığında axtar:',
-'searchrelated' => 'əlaqədar',
+'searchrelated' => 'əlaqəli',
 'searchall' => 'bütün',
 'showingresults' => "Aşağıda #'''$2''' ilə başlayan {{PLURAL:$1|'''$1'''-ə qədər}} nəticə göstərilib.",
 'showingresultsnum' => "Aşağıda #'''$2''' ilə başlayan {{PLURAL:$3|'''$3'''}} nəticə göstərilib.",
@@ -1068,7 +1072,7 @@ $1",
 'prefs-custom-js' => 'Xüsusi JavaScript',
 'prefs-common-css-js' => 'Bütün skinlər üçün ümumi CSS/JavaScript:',
 'prefs-emailconfirm-label' => 'E-poçtun təsdiqlənməsi:',
-'youremail' => 'E-məktub *',
+'youremail' => 'E-məktub:',
 'username' => 'İstifadəçi adı:',
 'uid' => 'İstifadəçi ID:',
 'prefs-memberingroups' => 'Üzvü olduğu {{PLURAL:$1|qrup|qrup}}:',
@@ -1090,8 +1094,8 @@ HTML kodu yoxla.',
 'prefs-help-realname' => 'Həqiqi adınızı daxil etmək məcburi deyil.
 Bu seçimi etdiyiniz halda, adınız redaktələrinizə görə müəlliflik hüququnuzun tanınması üçün istifadə ediləcək.',
 'prefs-help-email' => 'E-poçt ünvanınızı daxil etmək məcburi deyil.
-Bu parolunuzu unutduğunuz halda Sizə yeni parol göndərməyə imkan verir.
-Həmçinin kimliyinizi gostərmədən belə, başqalarının sizinlə istifadəçi və ya istifadəçi müzakirəsi səhifələriniz vasitəsi ilə əlaqə yaratmalarını seçə bilərsiniz.',
+Bu, parolunuzu unutduğunuz halda, sizə yeni parol göndərməyə imkan verir.',
+'prefs-help-email-others' => 'Həmçinin, istifadəçi və ya müzakirə səhifənizdəki link vasitəsilə başqa istifadəçilərin sizinlə əlaqə yaratmasını seçə bilərsiniz. Bu halda sizin e-poçt ünvanınız heç kimə görünməyəcək.',
 'prefs-help-email-required' => 'Elektron ünvan tələb olunur.',
 'prefs-info' => 'Əsas məlumatlar',
 'prefs-i18n' => 'Beynəlxalqlaşdırma',
@@ -1264,18 +1268,18 @@ Həmçinin kimliyinizi gostərmədən belə, başqalarının sizinlə istifadə
 'recentchanges-label-bot' => 'Bu redaktə bot tərəfindən edilmişdir',
 'recentchanges-label-unpatrolled' => 'Bu redaktə hələ nəzərdən keçirilməmişdir',
 'recentchanges-legend-newpage' => '$1 - yeni səhifə',
-'rcnotefrom' => "Aşağıda '''$2'''-dən ('''$1'''-ə qədər) dəyişikliklər sadalanmışdır.",
+'rcnotefrom' => 'Aşağıda <strong>$2</strong>-dən bu yana olan dəyişikliklər göstərilib (<strong>$1</strong>-dən çox olmayaraq).',
 'rclistfrom' => '$1 vaxtından başlayaraq yeni dəyişiklikləri göstər',
 'rcshowhideminor' => 'Kiçik redaktələri $1',
 'rcshowhidebots' => 'Botları $1',
 'rcshowhideliu' => 'Qeydiyyatlı istifadəçiləri $1',
 'rcshowhideanons' => 'Anonim istifadəçiləri $1',
-'rcshowhidepatr' => 'Nəzarət edilən redaktələri $1',
+'rcshowhidepatr' => 'Yoxlanılmış redaktələri $1',
 'rcshowhidemine' => 'Mənim redaktələrimi $1',
 'rclinks' => 'Son $2 gün ərzindəki son $1 dəyişikliyi göstər <br />$3',
 'diff' => 'fərq',
 'hist' => 'tarixçə',
-'hide' => 'Gizlət',
+'hide' => 'Gizlə',
 'show' => 'Göstər',
 'minoreditletter' => 'k',
 'newpageletter' => 'Y',
@@ -1286,7 +1290,7 @@ Həmçinin kimliyinizi gostərmədən belə, başqalarının sizinlə istifadə
 'rc-change-size' => '$1',
 'rc-change-size-new' => '$1 üçün dəyişiklikdən sonrakı həcm: {{PLURAL:$1|bayt|bayt|bayt}}',
 'newsectionsummary' => '/* $1 */ yeni bölmə',
-'rc-enhanced-expand' => 'Detalları göstər (JavaScript istifadə edir)',
+'rc-enhanced-expand' => 'Ətraflı göstər',
 'rc-enhanced-hide' => 'Redaktələri gizlət',
 'rc-old-title' => 'Əvvəlcə "$1" kimi yaradılmış',
 
@@ -1324,7 +1328,7 @@ Məqaləyə fayl yerləşdirmək üçün aşağıdaki formalardan birini istifad
 'upload-preferred' => 'İcazə verilən fayl tipləri: $1.',
 'upload-prohibited' => 'İcazə verilməyən fayl tipləri: $1.',
 'uploadlog' => 'yükləmə qeydi',
-'uploadlogpage' => 'Yükləmə qeydi',
+'uploadlogpage' => 'Yükləmə qeydləri',
 'uploadlogpagetext' => 'Aşağıda ən yeni yükləmə jurnal qeydləri verilmişdir.',
 'filename' => 'Fayl adı',
 'filedesc' => 'Xülasə',
@@ -1358,7 +1362,7 @@ Lütfən <strong>[[:$1]]</strong> keçidini yoxlayın və bu faylı yükləmək
 [[$1|thumb]]',
 'uploadwarning' => 'Yükləmə xəbərdarlığı',
 'savefile' => 'Faylı qeyd et',
-'uploadedimage' => 'yükləndi "[[$1]]"',
+'uploadedimage' => '"[[$1]]" yükləndi',
 'overwroteimage' => '"[[$1]]"-in yeni versiyası yükləndi',
 'uploaddisabled' => 'Yükləmə baş tutmadı',
 'copyuploaddisabled' => 'URL-dən yükləmə baş tutmadı.',
@@ -1456,7 +1460,7 @@ $1',
 'filehist-help' => 'Faylın əvvəlki versiyasını görmək üçün gün/tarix bölməsindəki tarixləri tıqlayın.',
 'filehist-deleteall' => 'hamısını sil',
 'filehist-deleteone' => 'sil',
-'filehist-revert' => 'əvvəlki vəziyyətinə',
+'filehist-revert' => 'geri qaytar',
 'filehist-current' => 'indiki',
 'filehist-datetime' => 'Tarix/Vaxt',
 'filehist-thumb' => 'Kiçik şəkil',
@@ -1472,9 +1476,11 @@ $1',
 'nolinkstoimage' => 'Bu fayla keçid verən səhifə yoxdur.',
 'linkstoimage-redirect' => '$1 (fayl istiqamətləndirilir) $2',
 'sharedupload' => 'Bu fayl $1-dandır və ola bilsin ki, başqa layihələrdə də istifadə edilir.',
+'sharedupload-desc-here' => 'Bu fayl $1dandır və başqa layihələrdə də istifadə edilə bilər.
+Faylın [$2 təsvir səhifəsindəki] məlumat aşağıda göstərilib.',
 'uploadnewversion-linktext' => 'Bu faylın yeni versiyasını yüklə',
 'shared-repo-from' => '$1-dən',
-'shared-repo' => 'ümumi anbar',
+'shared-repo' => 'ümumi fayl anbarı',
 'shared-repo-name-wikimediacommons' => 'Wikimedia Commons',
 
 # File reversion
@@ -1694,7 +1700,7 @@ Fərdi hüquqlar haqqında əlavə məlumatı [[{{MediaWiki:Listgrouprights-help
 'listgrouprights-group' => 'Qrup',
 'listgrouprights-rights' => 'Hüquqlar',
 'listgrouprights-helppage' => 'Help:Qrup hüquqları',
-'listgrouprights-members' => '(üzvləri)',
+'listgrouprights-members' => '(üzvlər)',
 'listgrouprights-right-display' => '<span class="listgrouprights-granted">$1 <code>($2)</code></span>',
 'listgrouprights-right-revoked' => '<span class="listgrouprights-revoked">$1 <code>($2)</code></span>',
 'listgrouprights-addgroup' => '{{PLURAL:$2|Qrupu}} əlavə et: $1',
@@ -1708,7 +1714,7 @@ Fərdi hüquqlar haqqında əlavə məlumatı [[{{MediaWiki:Listgrouprights-help
 
 # Email user
 'mailnologin' => 'Ünvan yoxdur',
-'emailuser' => 'İstifadəçiyə e-məktub yolla',
+'emailuser' => 'İstifadəçiyə e-məktub göndər',
 'emailpage' => 'İstifadəçiyə e-məktub yolla',
 'usermailererror' => 'Elektron poçtla məlumat göndərilən zaman xəta baş vermişdir:',
 'defemailsubject' => '"$1" adlı istifadəçidən {{SITENAME}} e-məktubu',
@@ -1736,8 +1742,8 @@ Fərdi hüquqlar haqqında əlavə məlumatı [[{{MediaWiki:Listgrouprights-help
 'usermessage-template' => 'MediaWiki:İstifadəçi müzakirəsi',
 
 # Watchlist
-'watchlist' => 'İzlədiyim səhifələr',
-'mywatchlist' => 'İzlədiyim səhifələr',
+'watchlist' => 'İzləmə siyahısı',
+'mywatchlist' => 'İzləmə siyahısı',
 'watchlistfor2' => '$1 $2 üçün',
 'nowatchlist' => 'İzləmə siyahınız böşdur.',
 'watchlistanontext' => 'Lütfən, izlədiyiniz səhifələri görmək və ya redaktə etmək üçün $1.',
@@ -1753,7 +1759,7 @@ Fərdi hüquqlar haqqında əlavə məlumatı [[{{MediaWiki:Listgrouprights-help
 'unwatchthispage' => 'İzləmə',
 'notanarticle' => 'Səhifə boşdur',
 'notvisiblerev' => 'Başqa istifadıçinin son dəyişikliyi silinib',
-'watchlist-details' => 'Müzakirə səhifələrini çıxmaq şərtilə {{PLURAL:$1|$1 səhifəni|$1 səhifəni}} izləyirsiniz.',
+'watchlist-details' => 'İzləmə siyahınızda, müzakirə səhifələrini çıxmaq şərtilə, {{PLURAL:$1|$1 səhifə|$1 səhifə}} var.',
 'wlheader-enotif' => ' E-məktubla bildiriş aktivdir.',
 'wlheader-showupdated' => "Son ziyarətinizdən sonra edilən dəyişikliklər '''qalın şriftlərlə''' göstərilmişdir.",
 'watchmethod-recent' => 'yeni dəyişikliklər izlənilən səhifələr üçün yoxlanılır',
@@ -1761,7 +1767,7 @@ Fərdi hüquqlar haqqında əlavə məlumatı [[{{MediaWiki:Listgrouprights-help
 'watchlistcontains' => 'İzləmə siyahınızda $1 {{PLURAL:$1|səhifə|səhifə}} var.',
 'iteminvalidname' => "'$1' ilə bağlı problem, adı düzgün deyil...",
 'wlshowlast' => 'Bunları göstər: son $1 saatı $2 günü $3',
-'watchlist-options' => 'İzlədiyim səhifələrin nizamlamaları',
+'watchlist-options' => 'İzləmə siyahısının nizamlamaları',
 
 # Displayed when you click the "watch" button and it is in the process of watching
 'watching' => 'İzlənilir...',
@@ -1841,7 +1847,7 @@ Sonuncu silinmələrə bax: $2.',
 
 # Protect
 'protectlogpage' => 'Mühafizə etmə qeydləri',
-'protectedarticle' => 'mühafizə edildi "[[$1]]"',
+'protectedarticle' => '"[[$1]]" səhifəsi mühafizə edildi',
 'modifiedarticleprotection' => '"[[$1]]" səhifəsi üçün mühafizə səviyyəsi dəyişildi',
 'unprotectedarticle' => 'mühafizə kənarlaşdırıldı "[[$1]]"',
 'protect-title' => '"$1" üçün mühafizə səviyyəsinin dəyişdirilməsi',
@@ -1939,12 +1945,12 @@ $1',
 'blanknamespace' => '(Ana)',
 
 # Contributions
-'contributions' => 'İstifadəçi fəaliyyəti',
+'contributions' => '{{GENDER:$1|İstifadəçinin}} fəaliyyəti',
 'contributions-title' => '$1 istifadəçi fəaliyyətləri',
 'mycontris' => 'Fəaliyyətim',
-'contribsub2' => '$1 ($2)',
+'contribsub2' => '{{GENDER:$3|$1}} ($2) adlı istifadəçinin fəaliyyəti',
 'nocontribs' => 'Bu kriteriyaya uyğun redaktələr tapılmadı',
-'uctop' => '(son)',
+'uctop' => '(hal-hazırkı)',
 'month' => 'Ay',
 'year' => 'Axtarışa bu tarixdən etibarən başla:',
 
@@ -1963,7 +1969,7 @@ Bloklama qeydlərinin sonuncusu aşağıda göstərilmişdir:',
 Bloklama qeydlərinin sonuncusu aşağıda göstərilmişdir:',
 'sp-contributions-search' => 'Fəaliyyətləri axtar',
 'sp-contributions-username' => 'IP-ünvanı və ya istifadəçi adı:',
-'sp-contributions-toponly' => 'Yalnız ən son dəyişiklikləri göstər',
+'sp-contributions-toponly' => 'Son redaktə olan dəyişiklikləri göstər',
 'sp-contributions-submit' => 'Axtar',
 
 # What links here
@@ -1971,7 +1977,7 @@ Bloklama qeydlərinin sonuncusu aşağıda göstərilmişdir:',
 'whatlinkshere-title' => '"$1" məqaləsinə keçid verən səhifələr',
 'whatlinkshere-page' => 'Səhifə:',
 'linkshere' => "'''[[:$1]]''' səhifəsinə istinad edən səhifələr:",
-'nolinkshere' => "'''[[:$1]]''' səhifəsinə keçid verən səhifə yoxdur.",
+'nolinkshere' => '<strong>[[:$1]]</strong> səhifəsinə keçid verən səhifə yoxdur.',
 'nolinkshere-ns' => "Seçilmiş ad aralığında heç bir səhifə '''[[:$1]]''' səhifəsinə keçid vermir.",
 'isredirect' => 'İstiqamətləndirmə səhifəsi',
 'istemplate' => 'daxil olmuş',
@@ -2065,13 +2071,13 @@ $1 adlı istifadəçinin bloklanma səbəbi: "$2"',
 'blocklog-showlog' => 'Bu istifadəçi daha əvvəl bloklanmışdır. Bloklama gündəliyi referans üçün aşağıda göstərilib:',
 'blocklog-showsuppresslog' => 'Bu istifadəçi daha əvvəl bloklanmışdır. Bloklama gündəliyi referans üçün aşağıda göstərilib:',
 'blocklogentry' => 'tərəfindən [[$1]] bloklandı, blok müddəti: $2 $3',
-'reblock-logentry' => '[[$1]] üçün son tarixi $2 $3 olmaq üzərə blok parametrləri dəyişdirildi',
+'reblock-logentry' => '[[$1]] üçün bloklama parametrlərini, başa çatma tarixi $2 $3 olmaqla, dəyişdirdi',
 'blocklogtext' => 'İstifadəçilərin bloklanması və blokun götürülməsi siyahısı.
 Avtomatik bloklanmış IP-ünvanlar burada göstərilmir.
 Hal-hazırkı [[Special:BlockList|qadağaların və bloklamaların siyahısı]]na bax.',
 'unblocklogentry' => '$1 üzərindəki blok götürüldü',
 'block-log-flags-anononly' => 'yalnız qeydiyyatsız istifadəçilər',
-'block-log-flags-nocreate' => 'Yeni hesab yaratma bloklanıb',
+'block-log-flags-nocreate' => 'yeni hesab yaratma bloklanıb',
 'block-log-flags-noautoblock' => 'avtobloklama qeyri-mümkündür',
 'block-log-flags-noemail' => 'E-mail bloklanıb',
 'block-log-flags-nousertalk' => 'Müzakirə səhifəsini redaktə edə bilməz.',
@@ -2243,7 +2249,7 @@ Zəhmət olmasa başqa ad seçin.',
 'tooltip-ca-unprotect' => 'Bu səhifənin mühafizəsini kənarlaşdır',
 'tooltip-ca-delete' => 'Bu səhifəni sil',
 'tooltip-ca-undelete' => 'Bu səhifəni silinmədən əvvəlki halına qaytarın',
-'tooltip-ca-move' => 'Bu səhifənin adını dəyiş',
+'tooltip-ca-move' => 'Səhifənin adını dəyiş',
 'tooltip-ca-watch' => 'Bu səhifəni izlə',
 'tooltip-ca-unwatch' => 'Bu səhifənin izlənməsini bitir',
 'tooltip-search' => '{{SITENAME}} səhifəsində axtar',
@@ -2390,7 +2396,7 @@ $1',
 'file-info-size' => '$1 × $2 piksel, fayl həcmi: $3, MIME növü: $4',
 'file-nohires' => 'Daha dəqiq versiyası yoxdur.',
 'svg-long-desc' => 'SVG fayl, nominal olaraq $1 × $2 piksel, faylın ölçüsü: $3',
-'show-big-image' => 'Daha yüksək keyfiyyətli şəkil',
+'show-big-image' => 'Faylın əsli',
 'show-big-image-preview' => 'Sınaq göstərişi ölçüsü: $1.',
 'show-big-image-other' => "Dig'r {{PLURAL:$2|nəticə|nəticələr}}: $1.",
 'show-big-image-size' => '$1 × $2 piksel',
@@ -2794,7 +2800,7 @@ Variants for Chinese language
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'hamısını',
-'namespacesall' => 'bütün',
+'namespacesall' => 'hamısı',
 'monthsall' => 'hamısı',
 
 # Email address confirmation
@@ -2869,11 +2875,11 @@ Variants for Chinese language
 # Watchlist editing tools
 'watchlisttools-view' => 'Siyahıdakı səhifələrdə edilən dəyişikliklər',
 'watchlisttools-edit' => 'İzlədiyim səhifələri göstər və redaktə et',
-'watchlisttools-raw' => 'Mətn kimi redaktə et',
+'watchlisttools-raw' => 'Adi mətn kimi redaktə et',
 
 # Core parser functions
 'unknown_extension_tag' => '"$1" Naməlum ayırma teqi',
-'duplicate-defaultsort' => '\'\'\'Diqqət:\'\'\' Ehtimal edilən "$2" klassifikasiya açarı əvvəlki "$1" klassifikasiya açarını keçərsiz edir.',
+'duplicate-defaultsort' => '<strong>Diqqət:</strong> Susmaya görə "$2" çeşidləmə açarı susmaya görə əvvəlki "$1" çeşidləmə açarını inkar edir.',
 
 # Special:Version
 'version' => 'Versiya',
@@ -2925,6 +2931,16 @@ Variants for Chinese language
 'blankpage' => 'Boş səhifə',
 'intentionallyblankpage' => 'Bu səhifə xüsusilə boşdur.',
 
+# External image whitelist
+'external_image_whitelist' => ' #Bu sətiri olduğu kimi saxlayın<pre>
+#Burada ardıcıl ifadələrin fraqmentlərini yerləşdirin (// simvolları arasında yerləşən hissələri).
+#Onlar kənar şəkillərin URL ünvanları ilə tutuşdurulacaq.
+#Uyğun gələnlər şəkil kimi, yerdə qalanlar isə şəkillərə keçid kimi göstəriləcək.
+#Sətirlərdən # simvolu ilə başlayanlar şərh hesab ediləcək.
+#Sətirlər böyük-kiçik şriftə həsass deyillər.
+
+#Ardıcıl ifadələrin fraqmentlərini bu sətirdən yuxarıda yerləşdirin. Bu sətiri olduğu kimi saxlayın.</pre>',
+
 # Special:Tags
 'tags' => 'Mümkün dəyişiklik etiketləri',
 'tag-filter' => '[[Special:Tags|Etiket]] süzgəci:',
index a382b8d..427d2d8 100644 (file)
@@ -992,8 +992,6 @@ $3 طرفین‌دن وئریلن سبب '$2",
 'revdelete-show-file-submit' => 'بلی',
 'revdelete-selected' => "[[:$1]] صحیفه‌سی‌نین {{PLURAL:$2|سئچیلمیش نوسخه لری|سئچیلمیش نوسخه لری }}:'",
 'logdelete-selected' => "'ژورنالین {{PLURAL:$1|سئچیلمیش قئیدی|سئچیلمیش قئیدلری}}:'",
-'revdelete-text' => "' 'سیلینئن رئویزیون‌لار و حادثه‌لر هله صحیفه کئچمیشینده و گونده‌لیک‌لرده گؤرونه‌جک، لاکین ترکیبین پارچا‌لاری عمومی اولا‌راق ائریشیلئمئیئجئکتیر.'
-{{SITENAME}} سایتین‌داکی دیگر ایداره‌چی‌لر گیزلی مزمونا چاتا بیلر و علاوه محدودیت‌لر آیارلانمادییسا بو اینتئرفئیس ایله گئری گتیره بیلر.",
 'revdelete-confirm' => 'خاهیش ائدیریک، بونو ائتمک ایستدیگینیزی، نتیجه‌لرینی آنلادیغینیزی، و بونو [[{{MediaWiki:Policy-url}}| پرینسیپ‌لره]] گؤره ائدیر اولدوغونوزو تسدیق ائدین.',
 'revdelete-suppress-text' => "ساخلاما 'یالنیز آشاغی‌داکی حال‌لار اوچون ایستیفاده ائدیلمه‌لی‌دیر:
 * اویگون‌سوز فردی معلومات
index 28ec8bb..23dd3c4 100644 (file)
@@ -1080,8 +1080,6 @@ $3 белдергән сәбәп: ''$2''",
 'revdelete-show-file-submit' => 'Эйе',
 'revdelete-selected' => "'''[[:$1]] битенең {{PLURAL:$2|1=һайланған версияһы|һайланған версиялары}}:'''",
 'logdelete-selected' => "'''Яҙманың {{PLURAL:$1|1=һайланған яҙыуы|һайланған яҙыуҙары}}:'''",
-'revdelete-text' => "'''Биттәрҙең юйылған версиялары һәм ваҡиғалар, бит тарихында һәм яҙмаларҙа күрһәтеләсәк, ләкин уларҙың эстәлектәренең бер өлөшө ябай ҡулланыусыларға асыҡ булмаясаҡ.'''
-{{SITENAME}} проектының хакимдәре йәшерен эстәлеккә керә һәм өҫтәмә сикләүҙәр ҡуйылған осраҡтарҙан тыш, ошо уҡ арайөҙ аша тергеҙә аласаҡтар.",
 'revdelete-confirm' => 'Зинһар, был ғәмәлде үтәргә теләүегеҙҙе, буласаҡ һөҙөмтәләрҙә аңлауығыҙҙы, [[{{MediaWiki:Policy-url}}|ҡағиҙәләр]] буйынса эшләүегеҙҙе раҫлағыҙ.',
 'revdelete-suppress-text' => "Йәшереү '''тик''' киләһе осраҡтарҙа ғына башҡарыла:
 
index 15c9513..4a880f2 100644 (file)
@@ -646,8 +646,6 @@ Du kauhstas auhschauh, waunn du wüst. Nahernte Auhgoom steengern im [{{fullurl:
 Details stehen im [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} Lösch-Logbuch].</div>',
 'rev-delundel' => 'zoagn / vastecka',
 'revdelete-nooldid-title' => 'Koa Version ogem',
-'revdelete-text' => "'''Der Inhalt oder andere Bestandteile gelöschter Versionen sind nicht mehr öffentlich einsehbar, erscheinen jedoch weiterhin als Einträge in der Versionsgeschichte.'''
-{{SITENAME}}-Administratoren können den entfernten Inhalt oder andere entfernte Bestandteile weiterhin einsehen und wiederherstellen, es sei denn, es wurde festgelegt, dass die Zugangsbeschränkungen auch für Administratoren gelten.",
 'revdel-restore' => 'Siachtborkeit endan',
 'pagehist' => 'Versiónsgschicht',
 'deletedhist' => 'Gléschde Versiónen',
index 8077ba6..9a0fa9e 100644 (file)
@@ -835,10 +835,6 @@ Legend: (cur) = تفاوتان گون هنوکین نسخه,
 'revdelete-show-file-submit' => 'بله',
 'revdelete-selected' => "'''{{PLURAL:$2|بازبینی انتخابی|بازبینی ان انتخابی}} چه [[:$1]]:'''",
 'logdelete-selected' => "'''{{PLURAL:$1|رویداد آمار انتخابی|رویداد ان آمار انتخابی}}:'''",
-'revdelete-text' => "'''حذفین بازبینی آن و رویداد ان هنگت ته تاریح و آمار صفحه جاه کاینت، بله لهتی چه محتوا آيان په عام قابل دسترسی نه بنت.'''
-
-دگه مدیران ته {{SITENAME}} هنگت نوننت په پناهین محتوا دسترسیش بیت و توننت آیء چه طریق همی دستبری آی> تریننت، مگر شی که گیشین محدودیت بلیت.
-لطفا تایید کنیت که شما لوٹیت ای کارءَ انجام دهید و چه آیی نتیجه سهی گیت و ای کار هم داب په [[{{MediaWiki:Policy-url}}|سیاست]]انجام دهید",
 'revdelete-suppress-text' => "فرونشانی بایدن '''فقط''' په جهلگین موارد استفاده بیت:
 * اطلاعات نامناسب شخصی
 *: ''نشانی لوگ، شماره تلفن، شماره تامین اجتماعی و دگه.''",
index fd5b391..865611c 100644 (file)
@@ -1051,8 +1051,6 @@ Ika puwedeng makakatanaw kaining diff; mga detalye puwedeng mananagboan sa [{{fu
 'revdelete-show-file-submit' => 'Iyo tabi',
 'revdelete-selected' => "'''{{PLURAL:$2|Selected revision|Mga piniling pagbabago}} kan [[:$1]]'''",
 'logdelete-selected' => "'''{{PLURAL:$1|Selected log event|Mga piniling talaan kan mga pangyayari}}:'''",
-'revdelete-text' => "'''Pinagpurang mga pagbabago asin mga pangyayari mahihiling pa man sa historiyang pahina asin mga talaan, pero an mga parte kan saindang laman dae puwedeng magamit kan publiko.'''
-An ibang administrador sa {{SITENAME}} puwede pa man makagamit sa pinagtagong laman asin balewalaon an pagpura kaini giraray sa paagi nin kaparehong panlaog-olay, laen lang kun may kadagdagang pangilin an inilapat.",
 'revdelete-confirm' => 'Pakikumpirma tabi na ika tuyong gumibo kaini, na saimong naintindihan an mga konsekuwensiya, asin ta ika pinaghihimo ini na uyon sa [[{{MediaWiki:Policy-url}}|an palisiya]].',
 'revdelete-suppress-text' => "An paglulubog dapat '''sana''' magagamit para sa minasunod na mga kaso:
 *Potensiyal na libeloso an impormasyon
index 04af676..54aee58 100644 (file)
@@ -99,9 +99,9 @@ $messages = array(
 'tog-extendwatchlist' => 'Паказваць усе змяненні, а не толькі апошнія',
 'tog-usenewrc' => 'Групаваць змены па старонках у апошніх зменах і спісе назірання',
 'tog-numberheadings' => 'Аўта-нумараваць падзагалоўкі',
-'tog-showtoolbar' => 'Паказваць рэдактарскую стужку (Яваскрыпт)',
-'tog-editondblclick' => 'Ð\9fÑ\80аÑ\9eка Ñ\81Ñ\82аÑ\80онак Ð¿Ð° Ð¿Ð°Ð´Ð²Ð¾Ð¹Ð½Ñ\8bм Ð¿Ñ\81Ñ\82Ñ\80Ñ\8bкÑ\83 (ЯваÑ\81кÑ\80Ñ\8bпÑ\82)',
-'tog-editsectiononrightclick' => 'Праўка падраздзелаў па правым пстрыку на загалоўку (Яваскрыпт)',
+'tog-showtoolbar' => 'Паказваць панэль інструментаў рэдактара',
+'tog-editondblclick' => 'Ð\9fÑ\80аÑ\9eка Ñ\81Ñ\82аÑ\80онак Ð¿Ð° Ð´Ð²Ð°Ð¹Ð½Ñ\8bм Ð¿Ñ\81Ñ\82Ñ\80Ñ\8bкÑ\83',
+'tog-editsectiononrightclick' => 'Правіць падраздзелы па правым пстрыку на загалоўку',
 'tog-rememberpassword' => 'Памятаць уваходныя даныя ў гэтым браўзеры (не даўжэй за $1 {{PLURAL:$1|дзень|дні|дзён}})',
 'tog-watchcreations' => 'Дабаўляць створаныя мною старонкі і файлы ў мой спіс назірання',
 'tog-watchdefault' => 'Дабаўляць старонкі і файлы пасля маіх правак у мой спіс назірання',
@@ -110,14 +110,14 @@ $messages = array(
 'tog-minordefault' => 'Пачынаць кожную праўку як дробную',
 'tog-previewontop' => 'Папярэдні паказ — над рэдактарскім полем',
 'tog-previewonfirst' => 'Папярэдні паказ пры першай праўцы',
-'tog-enotifwatchlistpages' => 'СлаÑ\86Ñ\8c Ð¼Ð½Ðµ Ñ\8dл.поÑ\88Ñ\82Ñ\83, ÐºÐ°Ð»Ñ\96 Ð¼Ñ\8fнÑ\8fеÑ\86Ñ\86а Ñ\81Ñ\82аÑ\80онка Ñ\9e Ð¼Ð°Ñ\96м Ñ\81пÑ\96Ñ\81е Ð½Ð°Ð·Ñ\96Ñ\80анага',
+'tog-enotifwatchlistpages' => 'СлаÑ\86Ñ\8c Ð¼Ð½Ðµ Ñ\8dл.поÑ\88Ñ\82Ñ\83, ÐºÐ°Ð»Ñ\96 Ð¼Ñ\8fнÑ\8fеÑ\86Ñ\86а Ñ\81Ñ\82аÑ\80онка Ñ\9e Ð¼Ð°Ñ\96м Ñ\81пÑ\96Ñ\81е Ð½Ð°Ð·Ñ\96Ñ\80аннÑ\8f',
 'tog-enotifusertalkpages' => 'Слаць эл.пошту пра мены ў маёй размоўнай старонцы',
-'tog-enotifminoredits' => 'СлаÑ\86Ñ\8c Ñ\8dл.поÑ\88Ñ\82Ñ\83 Ð¿Ñ\80а Ð´Ñ\80обнÑ\8bÑ\8f Ð¿Ñ\80аÑ\9eкÑ\96',
+'tog-enotifminoredits' => 'Ð\9fаведамÑ\8fÑ\86Ñ\8c Ð¼Ð½Ðµ Ð½Ð° Ñ\8dл.поÑ\88Ñ\82Ñ\83 Ð¿Ñ\80а Ð´Ñ\80обнÑ\8bÑ\8f Ð¿Ñ\80аÑ\9eкÑ\96 Ñ\81Ñ\82аÑ\80онак Ñ\96 Ñ\84айлаÑ\9e',
 'tog-enotifrevealaddr' => 'Не скрываць майго адрасу эл.пошты ў паведамленнях',
 'tog-shownumberswatching' => 'Паказваць колькасць назіральнікаў',
 'tog-oldsig' => 'Існуючы подпіс:',
 'tog-fancysig' => 'Апрацоўваць подпіс як вікі-тэкст (без аўтаматычнай спасылкі)',
-'tog-uselivepreview' => 'Жывы перадпаказ (Яваскрыпт, эксперыментальн.)',
+'tog-uselivepreview' => 'Жывы перадпаказ (эксперыментальн.)',
 'tog-forceeditsummary' => 'Папярэджваць пра пустое поле тлумачэння праўкі',
 'tog-watchlisthideown' => 'Не паказваць у назіраным сваіх правак',
 'tog-watchlisthidebots' => 'Не паказваць у назіраным правак, зробленых робатамі',
@@ -130,6 +130,7 @@ $messages = array(
 'tog-showhiddencats' => 'Паказаць схаваныя катэгорыі',
 'tog-norollbackdiff' => 'Не паказваць розніцу ў выніку адкату',
 'tog-useeditwarning' => 'Папярэдзіць мяне, калі я пакідаю старонку з незахаванымі праўкамі',
+'tog-prefershttps' => 'Заўсёды выкарыстоўваць абароненае злучэнне пасля ўваходу ў сістэму',
 
 'underline-always' => 'Заўсёды',
 'underline-never' => 'Ніколі',
@@ -230,7 +231,7 @@ $messages = array(
 'newwindow' => '(адкрыецца ў новым акне)',
 'cancel' => 'Нічога',
 'moredotdotdot' => 'Яшчэ...',
-'morenotlisted' => 'Ð\91олÑ\8cÑ\88 Ð½Ñ\96Ñ\87ога Ð½Ñ\8fма...',
+'morenotlisted' => 'Ð\93Ñ\8dÑ\82Ñ\8b Ñ\81пÑ\96Ñ\81 Ð½Ðµ Ð¿Ð¾Ñ\9eнÑ\8b.',
 'mypage' => 'Старонка',
 'mytalk' => 'Размовы',
 'anontalk' => 'Размова для гэтага IP',
@@ -452,7 +453,8 @@ $1',
 'protectedpagetext' => 'Старонка ахоўваецца, каб нельга было яе правіць.',
 'viewsourcetext' => 'Можна бачыць і капіраваць зыходны тэкст гэтай старонкі:',
 'viewyourtext' => "Вы можаце праглядзець і скапіяваць зыходны тэкст '''вашых правак''' на гэтай старонцы:",
-'protectedinterface' => 'Старонка ахоўваецца, таму што ўваходзіць у склад інтэрфейсу гэтай праграмы.',
+'protectedinterface' => 'Старонка ўтрымлівае інтэрфейснае паведамленне праграмнага забеспячэння гэтага вікі-праекта і ахоўваецца, каб прадухіліць вандалізм.
+Каб дабавіць ці змяніць пераклады ва ўсіх вікі-праектах, калі ласка, выкарыстоўвайце сайт лакалізацыі MediaWiki [//translatewiki.net/ translatewiki.net].',
 'editinginterface' => "'''Увага:''' Вы правіце старонку, якая ўтрымлівае тэкст карыстальніцкага інтэрфейсу.
 Яе змяненне паўплывае на вонкавы выгляд праграмы для ўсіх удзельнікаў.
 Праект лакалізацыі MediaWiki: [//translatewiki.net/wiki/Main_Page?setlang=be translatewiki.net].",
@@ -829,8 +831,8 @@ $2
 'postedit-confirmation' => 'Вашая праўка была захаваная.',
 'edit-already-exists' => 'Не ўдалося стварыць новую старонку.
 Такая ўжо існуе.',
-'editwarning-warning' => 'Ð\92Ñ\8bÑ\85ад Ð· Ð³Ñ\8dÑ\82ай Ñ\81Ñ\82аÑ\80онкÑ\96 Ð¿Ñ\80Ñ\8bвÑ\8fдзе Ð´Ð° Ñ\81Ñ\82Ñ\80аÑ\82Ñ\8b Ð¿Ñ\80авак, Ñ\8fкÑ\96Ñ\8f Ð²Ñ\8b Ð·Ñ\80абÑ\96лі. 
-Калі Вы зарэгістраваныя ў сістэме, Вы можаце адключыць гэта папярэджанне ў закладцы "Праца" Вашых настаўленняў.',
+'editwarning-warning' => 'Ð\9fеÑ\80аÑ\85од Ð½Ð° Ñ\96нÑ\88Ñ\83Ñ\8e Ñ\81Ñ\82аÑ\80онкÑ\83 Ð¼Ð¾Ð¶Ð° Ð¿Ñ\80Ñ\8bвеÑ\81Ñ\86Ñ\96 Ð´Ð° Ñ\81Ñ\82Ñ\80аÑ\82Ñ\8b Ð¿Ñ\80авак, Ð·Ñ\80обленÑ\8bÑ\85 Ð\92амі. 
+Калі Вы ўвайшлі ў сістэму, Вы можаце адключыць гэта папярэджанне ў раздзеле "{{int:prefs-editing}}" Вашых настроек.',
 
 # Content models
 'content-model-wikitext' => 'вікі-тэкст',
@@ -936,8 +938,6 @@ $2
 'revdelete-show-file-submit' => 'Так',
 'revdelete-selected' => "'''{{PLURAL:$2|Выбраная версія|Выбраныя версіі}} [[:$1]]:'''",
 'logdelete-selected' => "'''{{PLURAL:$1|Выбраны запіс|Выбраныя запісы}} журналу:'''",
-'revdelete-text' => "'''Сцёртыя версіі і падзеі надалей будуць паказвацца ў гісторыі старонкі і ў журналах, але часткі іх зместу не будуць даступныя для публікі.'''
-Іншыя адміністратары пляцоўкі {{SITENAME}} надалей змогуць бачыць схаваны змест і аднаўляць яго праз гэты самы інтэрфейс, калі не будзе ўведзена дадатковых абмежаванняў.",
 'revdelete-confirm' => 'Пацвердзіце, што вы жадаеце гэта зрабіць, што вы разумееце наступствы, і што вы робіце гэта ў адпаведнасці з [[{{MediaWiki:Policy-url}}|арганізацыйнымі правіламі]].',
 'revdelete-suppress-text' => "Заглушэнне належыць ужываць '''выключна''' ў наступных выпадках:
 * Недапушчальная асабістая інфармацыя
@@ -1349,14 +1349,25 @@ $1",
 'recentchanges-label-bot' => 'Праўка была зробленая праграмай-робатам',
 'recentchanges-label-unpatrolled' => 'Праўка яшчэ не атрымала адзнакі ўхваленасці (за ёй не сочыць "патруль")',
 'recentchanges-legend-newpage' => '$1 - новая старонка',
-'rcnotefrom' => 'Ð\9dÑ\96жÑ\8dй Ð·Ð½Ð°Ñ\85одзÑ\8fÑ\86Ñ\86а Ð·Ð¼ÐµÐ½Ñ\8b Ð· <b>$2</b> (да <b>$1</b> Ð½Ð° Ñ\81Ñ\82аÑ\80онкÑ\83).',
+'rcnotefrom' => 'Ð\9dÑ\96жÑ\8dй Ð·Ð½Ð°Ñ\85одзÑ\8fÑ\86Ñ\86а Ð·Ð¼ÐµÐ½Ñ\8b Ð· <b>$2</b> (паказана Ð½Ðµ Ð±Ð¾Ð»Ñ\8cÑ\88 Ñ\87Ñ\8bм <b>$1</b>).',
 'rclistfrom' => 'Паказаць змены з $1',
-'rcshowhideminor' => '$1 дробных правак',
+'rcshowhideminor' => '$1 дробныя праўкі',
+'rcshowhideminor-hide' => 'Схаваць',
 'rcshowhidebots' => '$1 робатаў',
+'rcshowhidebots-show' => 'Паказаць',
+'rcshowhidebots-hide' => 'Схаваць',
 'rcshowhideliu' => '$1 пазнаных удзельнікаў',
+'rcshowhideliu-show' => 'Паказаць',
+'rcshowhideliu-hide' => 'Схаваць',
 'rcshowhideanons' => '$1 ананімных удзельнікаў',
-'rcshowhidepatr' => '$1 ухваленых правак',
-'rcshowhidemine' => '$1 ўласных правак',
+'rcshowhideanons-show' => 'Паказаць',
+'rcshowhideanons-hide' => 'Схаваць',
+'rcshowhidepatr' => '$1 ухваленыя праўкі',
+'rcshowhidepatr-show' => 'Паказаць',
+'rcshowhidepatr-hide' => 'Схаваць',
+'rcshowhidemine' => '$1 уласныя праўкі',
+'rcshowhidemine-show' => 'Паказаць',
+'rcshowhidemine-hide' => 'Схаваць',
 'rclinks' => 'Паказаць апошнія $1 змен за мінулыя $2 дзён<br />$3',
 'diff' => 'розн.',
 'hist' => 'гіст.',
@@ -1370,8 +1381,8 @@ $1",
 'rc_categories_any' => 'Усе',
 'rc-change-size-new' => '$1 {{PLURAL:$1|байт|байта|байтаў}} пасля змены',
 'newsectionsummary' => '/* $1 */ новы падраздзел',
-'rc-enhanced-expand' => 'Ð\9fаказваÑ\86Ñ\8c Ð¿Ð°Ð´Ñ\80абÑ\8fзнаÑ\81Ñ\86Ñ\96 (паÑ\82Ñ\80абÑ\83еÑ\86Ñ\86а Ð¯Ð²Ð°Ñ\81кÑ\80Ñ\8bпÑ\82)',
-'rc-enhanced-hide' => 'Не паказваць падрабязнасцяў',
+'rc-enhanced-expand' => 'Ð\9fаказаÑ\86Ñ\8c Ð¿Ð°Ð´Ñ\80абÑ\8fзнаÑ\81Ñ\86Ñ\96',
+'rc-enhanced-hide' => 'Не паказваць падрабязнасцей',
 
 # Recent changes linked
 'recentchangeslinked' => 'Звязаныя праўкі',
@@ -1599,8 +1610,7 @@ $1',
 'upload_source_file' => ' (файл на вашай машыне)',
 
 # Special:ListFiles
-'listfiles-summary' => 'Гэтая службовая старонка паказвае ўсе загружаныя файлы.
-Пры адборы па ўдзельніку, паказваюцца толькі нядаўнія загрузкі гэтага ўдзельніка.',
+'listfiles-summary' => 'Гэтая службовая старонка паказвае ўсе загружаныя файлы.',
 'listfiles_search_for' => 'Знайсці назву выявы:',
 'imgfile' => 'файл',
 'listfiles' => 'Усе файлы',
@@ -1785,6 +1795,7 @@ $1',
 'protectedpages' => 'Старонкі пад аховай',
 'protectedpages-indef' => 'Толькі бестэрміновыя аховы',
 'protectedpages-cascade' => 'Толькі каскадныя засцераганні',
+'protectedpages-noredirect' => 'Схаваць перанакіраванні',
 'protectedpagesempty' => 'Ніякія старонкі такім чынам не ахоўваюцца.',
 'protectedtitles' => 'Назвы пад аховай',
 'protectedtitlesempty' => 'Няма назваў, якія зараз бы ахоўваліся з такімі параметрамі.',
@@ -1840,6 +1851,7 @@ $1',
 'allpagesprefix' => 'Паказваць старонкі з прэфіксам:',
 'allpagesbadtitle' => 'Гэтая назва старонкі недапушчальная або ўтрымлівае між-моўны або між-вікавы прэфікс. Магчыма, у назве ёсць знак ці знакі, якія нельга ўжываць у назвах.',
 'allpages-bad-ns' => 'На {{SITENAME}} прастора назваў "$1" не падтрымліваецца.',
+'allpages-hide-redirects' => 'Схаваць перанакіраванні',
 
 # Special:Categories
 'categories' => 'Катэгорыі',
index 0ae4846..2d3298d 100644 (file)
@@ -801,6 +801,7 @@ $2',
 'createacct-another-realname-tip' => 'Сапраўднае імя паведамляць неабавязкова.
 Калі Вы яго пазначыце, яно будзе выкарыстоўвацца для пазначэньня Вашай працы.',
 'pt-login' => 'Увайсьці',
+'pt-login-button' => 'Увайсьці',
 'pt-createaccount' => 'Стварыць рахунак',
 'pt-userlogout' => 'Выйсьці',
 
@@ -1213,8 +1214,8 @@ $2
 'revdelete-show-file-submit' => 'Так',
 'revdelete-selected' => "'''{{PLURAL:$2|1=Выбраная вэрсія|Выбраныя вэрсіі}} старонкі [[:$1]]:'''",
 'logdelete-selected' => "'''{{PLURAL:$1|1=Выбраны запіс|Выбраныя запісы}} журнала:'''",
-'revdelete-text' => "'''Выдаленыя вэрсіі і падзеі будуць паказвацца ў гісторыі старонкі і журналах, але частка іх зьместу ня будзе даступная для звычайных удзельнікаў.'''
-Іншыя адміністратары {{GRAMMAR:родны|{{SITENAME}}}} будуць мець магчымасьць прагляду зьместу і аднаўленьня старонкі праз гэты інтэрфэйс, калі ня будуць уведзеныя дадатковыя абмежаваньні.",
+'revdelete-text-text' => 'Выдаленыя вэрсіі будуць па-ранейшаму бачныя ў гісторыі старонкі, але некаторыя часткі іх зьместу будуць недаступныя для ўдзельнікаў.',
+'revdelete-text-file' => 'Выдаленыя вэрсіі файла будуць па-ранейшаму бачныя ў гісторыі старонкі, але часткі іх зьместу будуць недаступныя для ўдзельнікаў.',
 'revdelete-confirm' => 'Калі ласка, пацьвердзіце, што Вы сапраўды жадаеце зрабіць гэта, разумееце наступствы і робіце гэта ў адпаведнасьці з [[{{MediaWiki:Policy-url}}|правіламі]].',
 'revdelete-suppress-text' => "Скрываньне можа выкарыстоўвацца '''толькі''' ў наступных выпадках:
 * патэнцыйна паклёпніцкая інфармацыя
@@ -1351,7 +1352,7 @@ $1",
 'search-file-match' => '(супадае зь зьмесьцівам файла)',
 'search-suggest' => 'Магчыма, вы мелі на ўвазе: $1',
 'search-interwiki-caption' => 'Сумежныя праекты',
-'search-interwiki-default' => 'вынікі з $1:',
+'search-interwiki-default' => 'Ð\92ынікі з $1:',
 'search-interwiki-more' => '(яшчэ)',
 'search-relatedarticle' => 'Зьвязаны',
 'searcheverything-enable' => 'Шукаць ва ўсіх прасторах назваў',
index 051831d..b3d43ad 100644 (file)
@@ -1155,8 +1155,6 @@ $2
 'revdelete-show-file-submit' => 'Да',
 'revdelete-selected' => "'''{{PLURAL:$2|Избрана версия|Избрани версии}} от '''$1:''''''",
 'logdelete-selected' => "'''{{PLURAL:$1|Избрано събитие|Избрани събития}}:'''",
-'revdelete-text' => "'''Изтритите версии ше се показват в историята на страницата, но тяхното съдържание ще бъде недостъпно за обикновенните потребители.'''
-Администраторите на {{SITENAME}} ще имат достъп до скритото съдържание и ще могат да го възстановят, с изключение на случаите, когато има наложено допълнително ограничение.",
 'revdelete-confirm' => 'Необходимо е да потвърдите, че велаете да извършите действието, разбирате последствията и го правите според [[{{MediaWiki:Policy-url}}|политиката]].',
 'revdelete-suppress-text' => "Премахването трябва да се използва '''само''' при следните случаи:
 *Неподходяща или неприемлива лична информация
index 71f8d24..3845388 100644 (file)
@@ -999,8 +999,6 @@ Sawagai saurang pambakal Pian kawa nang balain ini; rarincian kawa diugai dalam
 'revdelete-show-file-submit' => 'Iya-ai',
 'revdelete-selected' => "'''{{PLURAL:$2|Ralatan tapilih|Raralatan tapilih}} matan [[:$1]]:'''",
 'logdelete-selected' => "'''{{PLURAL:$1|Log kajadian tapilih|Log kakajadian tapilih}}:'''",
-'revdelete-text' => "'''Raralatan tahapus wan kakajadian akan magun cungul dalam halam tungkaran wan log, tagal hagian matan isinya akan kada kawa diungkai umum.'''
-Pambakal lain pada {{SITENAME}} akan magun kawa maungkai isi tasungkup wan kawa mambulikakan hapusan pulang mangguna'akan antarmuha sama, kacuali ada panambahan pahalatan lain nang disetél.",
 'revdelete-confirm' => 'Muhun yakinakan bahwasa Pian handak manggawi ini, bahwasa Pian paham sabab akibat, wan bahwasa Pian manggawi ini bapandal awan [[{{MediaWiki:Policy-url}}|kaaripan]].',
 'revdelete-suppress-text' => "Panikinan parlu dipuruk gasan kakasus baumpat ini:
 * Pina kawa jadi panjalasan pitnah
index 4c6801b..bf1c681 100644 (file)
@@ -1018,9 +1018,6 @@ $3-এর দেয়া কারণ হল ''$2''",
 'revdelete-show-file-submit' => 'হ্যাঁ',
 'revdelete-selected' => "'''[[:$1]] পাতার {{PLURAL:$2|নির্বাচিত সংশোধন|নির্বাচিত সংশোধনসমূহ}}:'''",
 'logdelete-selected' => "'''{{PLURAL:$1|টি নির্বাচিত লগ-ঘটনা|টি নির্বাচিত লগ-ঘটনা}}:'''",
-'revdelete-text' => "'''মুছে ফেলা সংশোধনগুলো এবং ঘটনাগুলি এখনও পাতার ইতিহাস ও লগগুলোতে দেখাবে, কিন্তু তাদের বিষয়বস্তুর অংশবিশেষ সর্বোসাধারণের জন্য উন্মুক্ত থাকবে না।'''
-
-{{SITENAME}} এর অন্যান্য প্রশাসকগণ লুকানো এই বিষয়বস্তু দেখতে পাবেন এবং বাড়তি কোনো সীমাবদ্ধতা না থাকলে একই ইন্টারফেসের মাধ্যমে এটি পুনরুদ্ধার করতে পারবেন।",
 'revdelete-confirm' => 'অনুগ্রহ করে নিশ্চিত করুন যে আপনি এটি করতে চাচ্ছিলেন, আপনি এর ফলাফল সম্পর্কে অবগত আছেন, এবং [[{{MediaWiki:Policy-url}}|নীতিমালার]] উপর ভিত্তি করেই এই কাজটি করছেন।',
 'revdelete-suppress-text' => "নিচের বিষয়গুলোর ক্ষেত্রেই '''কেবলমাত্র'''  চাপাচাপি করা যাবে:
 * সম্ভাব্য মানহানিকর তথ্য
@@ -2434,7 +2431,8 @@ $1',
 'sp-contributions-search' => 'অবদানসমূহের জন্য অনুসন্ধান',
 'sp-contributions-suppresslog' => 'মুছে ফেলা ব্যবহারকারী অবদান',
 'sp-contributions-username' => 'আইপি (IP) ঠিকানা অথবা ব্যবহারকারীর নাম:',
-'sp-contributions-toponly' => 'শুধুমাত্র সেই সম্পাদনাগুলি দেখাও যেগুলো সাম্প্রতিক সংস্করণের অন্তর্ভুক্ত।',
+'sp-contributions-toponly' => 'শুধুমাত্র সেই সম্পাদনাগুলি দেখাও যেগুলো সাম্প্রতিক সংস্করণের অন্তর্ভুক্ত',
+'sp-contributions-newonly' => 'শুধুমাত্র পাতা সৃষ্টি করা সম্পাদনাগুলি দেখাও',
 'sp-contributions-submit' => 'অনুসন্ধান',
 
 # What links here
index 37183a6..e769e62 100644 (file)
@@ -53,12 +53,19 @@ $messages = array(
 'tog-enotifrevealaddr' => 'ངའི་གློག་འཕྲིན་ཁ་བྱང་འདི་བརྡ་ཐོའི་ཁ་བྱང་ནང་གསལ་སྟོན་བྱེད་རོགས།',
 'tog-shownumberswatching' => 'ཤོག་ངོས་ལ་ལྟ་བཞིན་པའི་སྤྱོད་མིའི་ཁ་གྲངས་སྟོན།',
 'tog-oldsig' => 'ད་ཡོད་མིང་རྟགས།',
+'tog-fancysig' => 'མིང་རྟགས་རྣམས་ཝེ་ཁེ་ཡི་གེར་བརྩིས་རོགས། (རང་འགུལ་གྱི་སྦྲེལ་མཐུད་མེད་པ།)',
+'tog-uselivepreview' => 'འཆར་བཞིན་པའི་སྔོན་ལྟ་སྟོན་རོགས། (ཚོད་ལྟའི་ཆེད།)',
+'tog-forceeditsummary' => 'རྩོམ་སྒྲིག་ཀྱི་བསྡུས་དོན་སྟོང་པ་ནང་འཇུག་བྱེད་སྐབས་ང་ལ་དྲན་སྐུལ་བྱེད་རོགས།',
 'tog-watchlisthideown' => 'ངའི་རྩོམ་སྒྲིག་རྣམས་ལྟ་ཞིབ་ཐོ་ལས་སྦས་རོགས།',
 'tog-watchlisthidebots' => 'རང་འགུལ་འཕྱུལ་ཆས་ཀྱི་བཟོ་འཅོས་བྱས་པ་རྣམས་ངའི་ལྟ་ཞིབ་ཐོ་ལས་སྦས་རོགས།',
 'tog-watchlisthideminor' => 'རྩོམ་སྒྲིག་ཕལ་བ་རྣམས་ལྟ་ཞིབ་ཐོ་ལས་སྦས་རོགས།',
 'tog-watchlisthideliu' => 'ཐོ་འཛུལ་སྤྱོད་མིའི་རྩོམ་སྒྲིག་རྣམས་ལྟ་ཐོ་ལས་སྦས་རོགས།',
+'tog-watchlisthideanons' => 'མིང་མེད་པའི་སྤྱོད་མིས་རྩོམ་སྒྲིག་བྱས་པ་རྣམས་ལྟ་ཐོ་ལས་སྦས་རོགས།',
+'tog-watchlisthidepatrolled' => 'མྱལ་ཞིབ་བྱས་པའི་རྩོམ་སྒྲིག་རྣམས་ལྟ་ཐོ་ལས་སྦས་རོགས།',
 'tog-ccmeonemails' => 'ངས་གཞན་ལ་བཏང་བའི་གློག་འཕྲིན་གྱི་འདྲ་བཤུས་སྐུར་རོགས།',
+'tog-diffonly' => 'ཁྱད་པར་འཚོལ་སྐབས་ཤོག་ངོས་གྱི་ནང་དོན་མ་སྟོན་རོགས།',
 'tog-showhiddencats' => 'སྦས་བའི་དཀར་ཆག་སྟོན་རོགས།',
+'tog-norollbackdiff' => 'སྒྲེ་ལོག་རྒྱག་སྐབས་ཁྱད་པར་རྣམས་སྐྱུར་རོགས།',
 'tog-useeditwarning' => 'ངས་རྩོམ་སྒྲིག་ཤོག་ངོས་གང་རུང་ཐོག་བཟོ་འཅོས་རྣམས་ཉར་གཆོག་མ་བྱས་པར་འདོར་ན་ཉེན་བརྡ་གཏོང་རོགས།',
 'tog-prefershttps' => 'རྒྱན་དུ་ནང་འཛུལ་བྱས་བའི་སྐབས་བདེ་འཇགས་འབྲེལ་ལམ་བརྒྱུད་རོགས།',
 
@@ -276,6 +283,8 @@ $messages = array(
 'privacypage' => 'Project: གསང་དོན་གན་རྒྱ།',
 
 'badaccess' => 'ཆོག་ཆན་ལ་ནོར་འཁྲུལ།',
+'badaccess-group0' => 'ཁྱེད་ཀྱི་རེ་ཞུ་བྱས་པའི་བྱ་བ་འདི་ཁྱེད་ཉིད་ནས་ལག་ལེན་བསྟར་མི་ཆོག།',
+'badaccess-groups' => 'ཁྱེད་ཀྱི་རེ་ཞུ་བྱས་པའི་བྱ་བ་འདི་ {{PLURAL:$2|ཚོགས་པ་|ཚོགས་པ་གཅིག་}}: $1 གྱི་སྤྱིད་མི་ཚད་གཞི་ངེས་ཅན་རྣམས་ལ་ཡོད་',
 
 'versionrequired' => 'ཝེ་ཁེ་བརྒྱུད་ལམ་གྱི་འགྱུར།  MediaWiki Version $1 དེ་དགོས་འདུག།',
 'versionrequiredtext' => 'ཤོག་ངོས་འདི་བེད་སྤྱོད་པར་ཝེ་ཁེ་བརྒྱུད་ལམ་གྱི་འགྱུར་ $1 འདི་དགོས། [[Special:Version|version page]] འདིར་གཟིགས་རོགས།',
@@ -283,6 +292,9 @@ $messages = array(
 'ok' => 'འགྲིག',
 'retrievedfrom' => '"$1"ལས་སླར་རྙེད་སོང།',
 'youhavenewmessages' => 'ཁྱེད་ལ་འཕྲིན་གསར་$1($2)ཡོད།',
+'youhavenewmessagesmanyusers' => 'ཁྱེད་ལ་ $1 སྤྱོད་མི་མང་པོ་ཞིག་ནས་ ($2)འདུག།',
+'newmessageslinkplural' => '{{PLURAL:$1|འཕྲིན་ཐུང་གསར་པ་ཞིག་|999= འཕྲིན་ཐུང་གསར་པ།}}',
+'newmessagesdifflinkplural' => 'མཐའ་མའི་ {{PLURAL:$1|འགྱུར་བཅོས།|999=འགྱུར་བཅོས།}}',
 'youhavenewmessagesmulti' => 'ཁྱེད་ལ་ $1 སྟེང་དུ་འཕྲིན་ཡིག་འདུག',
 'editsection' => 'རྩོམ་སྒྲིག།',
 'editold' => 'རྩོམ་སྒྲིག',
@@ -297,7 +309,9 @@ $messages = array(
 'collapsible-expand' => 'རྒྱ་སྐྱེད།',
 'thisisdeleted' => '$1 ལ་ལྟ་བའམ་རང་ལོགས་བྱེད་རོགས།',
 'viewdeleted' => ' $1 ལ་ལྟ་དགོས་སམ།',
+'restorelink' => '{{PLURAL:$1|བསུབས་པའི་རྩོམ་སྒྲིག|$1 བསུབས་པའི་རྩོམ་སྒྲིག}}',
 'feedlinks' => 'འདྲན་ཆས། :',
+'feed-invalid' => 'རྒྱུན་མངགས་ཡ་ལན་ཕན་མེད་རེད་འདུག།',
 'site-rss-feed' => '$1 ཡི་RSS འབྱུང་ཁུངས།',
 'site-atom-feed' => '$1 ཡི་ཆ་ཤས་ཡ་ལན།',
 'page-rss-feed' => '$1 ཡི་RSS འབྱུང་ཁུངས།',
@@ -320,11 +334,28 @@ $messages = array(
 
 # Main script and global functions
 'nosuchaction' => 'བྱ་འགུལ་འདི་འདྲ་མེད།',
+'nosuchactiontext' => 'དྲ་ཚིགས་གཞིར་གཟུངས་ཀྱི་བྱ་བ་ཕན་མེད་རེད་འདུག།
+ཁྱེད་ཀྱི་དྲ་ཚིགས་ཁ་བྱང་འབྲི་སྟངས་ནོར་བ་ཡིན་སྲིད། ཡང་ན་དྲ་ཚིགས་ཁ་བྱང་ནོར་བ་ཞིག་ལ་སྦྲེལ་མཐུད་བྱེད་འདུག།
+{{SITENAME}} འདིར་གཉེན་ཆས་ཀྱི་ལས་རྩོལ་ཡིན་སྲིད།',
 'nosuchspecialpage' => 'དམིགས་བསལ་ཤོག་ངོས་འདི་འདྲ་ཞིག་མི་འདུག',
+'nospecialpagetext' => '<strong>ཁྱེད་ཀྱི་ལུགས་མཐུན་མིན་པའི་དམིགས་བསལ་ཤོག་ངོས་ཞིག་ལ་རེ་ཞུ་བྱས་འདུག།</strong>
+ལུགས་མཐུན་གྱི་དམིགས་བསལ་ཤོག་ངོས་རྣམས་འདིར་གཟིགས་རོགས།
+[[Special:SpecialPages|{{int:specialpages}}]]',
 
 # General errors
 'error' => 'ནོར་འཁྲུལ།',
+'databaseerror' => 'རྨང་གཞིའི་གྲངས་མཛོད་ལ་ནོར་འཁྲུལ་འདུག།',
+'databaseerror-text' => 'རྨང་གཞིའི་གྲངས་མཛོད་ལ་ནོར་འཁྲུལ་འདོན་སོང།
+འདི་ཕལ་ཆེར་གཉེན་ཆས་ཀྱི་ལས་རྩོལ་ཡིན་སྲིད།',
+'databaseerror-textcl' => 'རྨང་གཞིའི་གྲངས་མཛོད་ལ་ནོར་འཁྲུལ་འདོན་སོང།',
+'databaseerror-query' => 'འཚོལ་འདྲི། $1',
+'databaseerror-function' => 'རྩོལ་ནུས། $1',
+'databaseerror-error' => 'ནོར་སྐྱོན། $1',
+'laggedslavemode' => '<strong>ཉེན་བརྡ།</strong> ཤོག་ངོས་འདི་ཐོག་ཉེ་ཆར་གྱི་དུས་བསྟུན་ཁ་གསབ་བྱས་མེད།',
 'readonly' => 'གཞི་གྲངས་མཛོད་ཟྭ་བརྒྱབ་པ།',
+'enterlockreason' => 'བཀག་སྡོམ་བྱས་དགོས་རྐྱེན་བཀོད་རོགས དེ་མིན་བཀག་སྡོམ་འདི་དུས་ཚོད་ནམ་ཞིག་ལ་བཀྲོལ་རྒྱུ་ཡིན་མིན་སོགས་བཀོད་རོགས།',
+'readonlytext' => 'རྨང་གཞི་གྲངས་མཛོད་འདི་གནས་སྐབས་བཀག་སྡོམ་བྱས་འདུག། ཕལ་ཆེར་རྨང་གཞི་གྲངས་མཛོད་འདི་ཉར་འཚག་བྱད་བཞིན་འདུག། 
+$1 རྒྱུ་རྐྱེན་འདི་འོག་དོ་དམ་པས་བཀག་སྡོམ་བྱས་འདུག།',
 'missing-article' => 'གཞི་གྲངས་མཛོད་ནང་ཤོག་ངོས་ཀྱི་ཡི་གེ་བཙལ་ཐུབ་ཀྱི་མི་འདུག་པས། "$1" $2 
 ཕལ་ཆེར་འདི་གཤམ་ཀྱི་འགོག་རྐྱེན་ལོ་རྒྱུས་སུབ་པ་འམ་དུས་ཡོལ་ཀྱི་ཁྱད་པར་སོགས་ཀྱི་རྒྱུ་རྐྱེན་ཡིན།
 གལ་སྲིད་དེ་ལྟར་མིན་ཚེ། ཕལ་ཆེར་ཁྱེད་ཀྱི་ནོར་སྐྱོན་འཙལ་རྙེད་བྱང་བས།  [[Special:ListUsers/sysop|administrator]], དྲ་རྒྱའི་ས་ཚིགས་འདི་ཐོག་ཞུ་ཡིག་འབུལ་གནང་ཡོང་བ་མཁྱེན།',
@@ -389,7 +420,7 @@ $messages = array(
 'newpassword' => 'ལམ་ཡིག་གསར་བ།',
 'retypenew' => 'ལམ་ཡིག་གསར་བ་བསྐྱར་འཇུག་བྱོས།',
 'resetpass_submit' => 'ལམ་ཡིག་བསྒྲིགས་ནས་ནང་འཛུལ་བྱེད་པ།',
-'changepassword-success' => 'ལà½\98à¼\8bཡིà½\82à¼\8bà½\96à½\91ེà¼\8bལེà½\82སà¼\8bà½\84à½\84à¼\8bà½\96རà¾\97ེསà¼\8bà½\9fིà½\93à¼\8d à½\91à¼\8bà½\93ིà¼\8bà½\93à½\84à¼\8bའà½\9bུལà¼\8bà½\96ྱེà½\91à¼\8bà½\96à½\9eིà½\93à¼\8bà½\94à¼\8bà¼\8bà¼\8b',
+'changepassword-success' => 'à½\81ྱེà½\91à¼\8bà½\80ྱིà¼\8bà½\82སà½\84à¼\8bà½\96འིà¼\8bཨà½\84à¼\8bà½\96རà¾\97ེà¼\8bའà½\82ྱུརà¼\8bལེà½\82སà¼\8bà½\82ྲུà½\96à¼\8bà½\96ྱུà½\84à¼\8bསོà½\84à¼\8d',
 'resetpass_forbidden' => 'ལམ་ཡིག་བརྗེ་མི་ཐུབ།',
 'resetpass-submit-loggedin' => 'ལམ་ཡིག་བརྗེ་བ།',
 'resetpass-submit-cancel' => 'རྩིས་མེད་ཐོངས།',
@@ -490,6 +521,8 @@ $messages = array(
 'rev-delundel' => 'སྟོན། / སྦས།',
 'rev-showdeleted' => 'སྟོན།',
 'revdelete-show-file-submit' => 'ཡིན།',
+'logdelete-text' => 'སུབས་ཚར་པའི་ཐོ་འགོད་རྣམས་ད་དུང་ཡང་ཐོ་འགོད་རེའུ་མིག་ནང་འཆར་འདུག། ཡིན་ན་འང་ནང་དོན་ཆ་ཤས་རྣམས་ལ་ཚོགས་མི་གཞན་གྱི་འཛུལ་ཞུགས་བྱེད་མི་ཐུབ།',
+'revdelete-text-others' => 'ནང་དོན་ལ་ཁ་སྣོན་གྱི་བཀག་སྡོམས་བྱས་ན་མ་གཏོགས།{{SITENAME}}ནང་ཡོད་པའི་དོ་དམ་པ་གཞན་རྣམས་ནས་སྦས་སྐུང་བྱས་པའི་ནང་དོན་ལ་ད་དུང་ཡང་འཛུལ་ཞུགས་བྱེད་ལ། མ་ཟད་བསྐྱར་དུ་མི་བསུབས་པ་འཟོ་ཐུབ།',
 'revdelete-radio-same' => 'བཟོ་བཅོས་མ་བྱེད།',
 'revdelete-radio-set' => 'མངོན་མེད་ཀྱི།',
 'revdel-restore' => 'བཅོས་སུ་རུང་བ།',
@@ -534,7 +567,7 @@ $messages = array(
 'search-section' => '(ཚན་པ $1)',
 'search-suggest' => '$1 ལ་ཟེར་བ་ཡིན་ནམ།',
 'search-interwiki-caption' => 'སྲིང་མོའི་ལས་འཆར།',
-'search-interwiki-default' => '$1ལས་རྙེད་པ།',
+'search-interwiki-default' => '$1 ནས་འབྱུང་བའི་གྲུབ་འབྲས།',
 'search-interwiki-more' => '(དེ་ལས་མང་བ།)',
 'search-relatedarticle' => 'འབྲེལ་ཡོད།',
 'searchrelated' => 'འབྲེལ་ཡོད།',
@@ -991,7 +1024,7 @@ $messages = array(
 'specialpages' => 'ཆེད་ལས་ཤོག་ངོས།',
 
 # Special:Tags
-'tag-filter' => '[[Special:མཆན་བུ་|མཆན་བུ།]] འདེམས་འཚག།:',
+'tag-filter' => 'འདེམས་འཚག། [[Special:Tags|Tag]]',
 
 # New logging system
 'rightsnone' => '(སྟོང་པ།)',
index 074feb0..e79c9cf 100644 (file)
@@ -1113,8 +1113,6 @@ Gallout a ri gwelet an diforc'h-mañ ; titouroù zo war [{{fullurl:{{#Special:Lo
 'revdelete-show-file-submit' => 'Ya',
 'revdelete-selected' => "'''{{PLURAL:$2|Stumm dibabet|Stummoù dibabet}} eus [[:$1]] :'''",
 'logdelete-selected' => "'''{{PLURAL:$1|Darvoud eus ar marilh diuzet|Darvoud eus ar marilh diuzet}} :'''",
-'revdelete-text' => "'''Derc'hel a raio ar stummoù ha darvoudoù diverket da zont war wel war istor ar bajenn hag er marilhoù, met dazrn eus ar boued n'hallo ket bezañ gwelet gant an dud.'''
-Gouest e vo merourien all {{SITENAME}} da dapout krog en testennoù kuzhet ha da ziziverkañ anezho en-dro dre an hevelep etrefas, nemet e vije bet lakaet e plas strishadurioù ouzhpenn.",
 'revdelete-confirm' => "Kadarnait eo mat an dra-se a fell deoc'h ober, e komprenit mat ar pezh a empleg, hag en grit en ur zoujañ d'ar [[{{MediaWiki:Policy-url}}|reolennoù]].",
 'revdelete-suppress-text' => "Ne zlefe an dilemel bezañ implijet '''nemet''' abalamour d'an abegoù da-heul :
 * Titouroù personel dizere
index 4b6ab4c..d23f8b9 100644 (file)
@@ -812,6 +812,8 @@ Molimo Vas da sačekate $1 prije nego što pokušate ponovo.',
 'suspicious-userlogout' => 'Vaš zahtjev za odjavu je odbijen jer je poslan preko pokvarenog preglednika ili keširanog proksija.',
 'createacct-another-realname-tip' => 'Pravo ime nije obavezno.
 Ako izaberete da date ime, biće korišteno za pripisivanje za vaš rad.',
+'pt-login-button' => 'Prijavi me',
+'pt-createaccount' => 'Napravi korisnički račun',
 
 # Email sending
 'php-mail-error-unknown' => 'Nepoznata greška u PHP funkciji mail()',
@@ -1213,8 +1215,6 @@ Vi možete vidjeti ovu razliku; detalji se mogu vidjeti u [{{fullurl:{{#Special:
 'revdelete-show-file-submit' => 'Da',
 'revdelete-selected' => "'''{{PLURAL:$2|Odabrana revizija|Odabrane revizije}} od [[:$1]]:'''",
 'logdelete-selected' => "'''{{PLURAL:$1|Označena stavka zapisa|Označene stavke zapisa}}:'''",
-'revdelete-text' => "'''Obrisane revizije i događaji će i dalje biti vidljivi u historiji stranice i zapisima, ali dijelovi njenog sadržaja neće biti dostupni javnosti.'''
-Drugi administratori projekta {{SITENAME}} će i dalje moći pristupiti sakrivenom sadržaju i mogu ga ponovo vratiti kroz ovaj interfejs, osim ako nisu postavljena dodatna ograničenja.",
 'revdelete-confirm' => 'Molimo potvrdite da namjeravate ovo učiniti, da razumijete posljedice i da to činite u skladu s [[{{MediaWiki:Policy-url}}|pravilima]].',
 'revdelete-suppress-text' => "Ograničenja bi trebala biti korištena '''samo''' u slijedećim slučajevima:
 * Osjetljive korisničke informacije
index f5237c9..b4d6089 100644 (file)
@@ -1153,8 +1153,6 @@ funció, la revisió especificada no existeix, o bé esteu provant d'amagar l'ac
 'revdelete-show-file-submit' => 'Sí',
 'revdelete-selected' => "'''{{PLURAL:$2|Revisió seleccionada|Revisions seleccionades}} de [[:$1]]:'''",
 'logdelete-selected' => "'''{{PLURAL:$1|Esdeveniment del registre seleccionat|Esdeveniments del registre seleccionats}}:'''",
-'revdelete-text' => "'''Les revisions esborrades es mostraran encara als historials de les pàgines i als registres, si bé part del seu contingut serà inaccessible al públic.'''
-Els altres administradors de {{SITENAME}} encara podran accedir al contingut amagat i restituir-lo de nou mitjançant aquesta mateixa interfície, si no hi ha cap altra restricció addicional.",
 'revdelete-confirm' => "Si us plau, confirmeu que és això el que desitgeu fer, que enteneu les conseqüències, i que esteu fent-ho d'acord amb [[{{MediaWiki:Policy-url}}|les polítiques acordades]].",
 'revdelete-suppress-text' => "Les supressions '''només''' han de ser portades a terme en els següents casos:
 * Informació potencialment difamatòria
index 37210cd..0d10bc3 100644 (file)
@@ -624,7 +624,7 @@ $1',
 'nstab-main' => 'Яззам',
 'nstab-user' => 'Декъашхо',
 'nstab-media' => 'Медиа агӀо',
-'nstab-special' => 'Белха агlо',
+'nstab-special' => 'Белха агӀо',
 'nstab-project' => 'Проектах лаьцна',
 'nstab-image' => 'Файл',
 'nstab-mediawiki' => 'Хаам',
@@ -694,7 +694,7 @@ URL язъеш гӀалат даьлла хила мега.
 'viewsource-title' => 'Агӏона $1 дуьххьарлера йозане хьажар',
 'actionthrottled' => 'Сиххалин доза тохар',
 'actionthrottledtext' => 'Спам цахилийта хӀара дешдерг кӀезиг хенахь дукху ца дайта дихкина ду. Дехар до массийта минот яьлча гӀорта.',
-'protectedpagetext' => 'ХӀара агӀо дӀакъойлина йу рé цадаккхийта.',
+'protectedpagetext' => 'ХӀара агӀо дӀакъоьвлина ю тадарш ца дайта.',
 'viewsourcetext' => 'Хьоьга далундерг хьажар а дезахь хlокху агlон чура йоза хьаэцар:',
 'viewyourtext' => "Хьан йиш ю '''хьой нисдинчу''' дӀадолалун йозе хьажа а цуна копи ян а:",
 'protectedinterface' => 'ХӀара схьгайтарна гӀирса хаамаш латтош йолу агӀо ю. Куьйгалхошна бен иза хийца цало.',
@@ -777,7 +777,7 @@ URL язъеш гӀалат даьлла хила мега.
 'createacct-another-email-ph' => 'ДӀаязде электронан почтан адрес',
 'createaccountmail' => 'хааман зӀене хула',
 'createacct-realname' => 'Хьан цӀе (ца язйича мега)',
-'createaccountreason' => 'Ð\91аÑ\85Ñ\8cан:',
+'createaccountreason' => 'Ð\91аÑ\85Ñ\8cна:',
 'createacct-reason' => 'Бахьна',
 'createacct-reason-ph' => 'Стен кхуллуш ду ахьа керла декъашхочун дӀаяздар',
 'createacct-captcha' => 'Кхерамзалла хьажар',
@@ -834,6 +834,7 @@ URL язъеш гӀалат даьлла хила мега.
 'login-abort-generic' => 'Сестемин довзийта тарцаделира',
 'loginlanguagelabel' => 'Мотт: $1',
 'pt-login' => 'ЧугӀо',
+'pt-login-button' => 'ЧугӀо',
 'pt-createaccount' => 'Кхолла декъашхочун дӀаяздар',
 'pt-userlogout' => 'Болх дӀаберзор',
 
@@ -1126,8 +1127,6 @@ URL язъеш гӀалат даьлла хила мега.
 'revdelete-show-file-submit' => 'Хlаъ',
 'revdelete-selected' => "'''АгӀона [[:$1]] {{PLURAL:$2|1=къастина верси|къастина версеш}}:'''",
 'logdelete-selected' => '<strong>Тептар чура {{PLURAL:$1|хаьржина дӀаяздар|хаьржина дӀаяздарш}}:</strong>',
-'revdelete-text' => "'''ДӀаяхна агӀонашан версеш а хелларш а гуш хир ду агӀона истори а тептаран а чохь, амма цара чулацам куьйгалхошна бен тӀекхочу чохь хир бац.'''
-{{SITENAME}} проектан куьйгалхойн йиш хир ю хӀокху интерфейс чухула дӀааьхинарш меттахӀотта я.",
 'revdelete-confirm' => 'Дехар до, бакъдар ахьа деш дерг [[{{MediaWiki:Policy-url}}|бакъонашца]] деш хилар.',
 'revdelete-legend' => 'Доза тохар',
 'revdelete-hide-text' => 'Къайладаккха хӀокху агӀона чура йоза',
@@ -1141,7 +1140,7 @@ URL язъеш гӀалат даьлла хила мега.
 'revdelete-radio-unset' => 'Гуш ерг',
 'revdelete-suppress' => 'Къайлабаха хаамаш куьйгалхойх а',
 'revdelete-unsuppress' => 'МеттахӀоьттина версешан дихкар къайладаккха',
-'revdelete-log' => 'Ð\91аÑ\85Ñ\8cан:',
+'revdelete-log' => 'Ð\91аÑ\85Ñ\8cна:',
 'revdelete-submit' => 'Кхочушде {{PLURAL:$1|1=къастина версин|къастина версийн}}',
 'revdelete-success' => "'''Версеш гуш хилар кхиамца хийцина.'''",
 'revdelete-failure' => "'''Версеш гуш хилар хийца йиш яц:'''
@@ -1159,7 +1158,7 @@ $1",
 ** Бита йиш йоцу шех лаьцна хаам
 ** Бакъдоцург зуламан хаам',
 'revdelete-otherreason' => 'Кхин бахьна/тӀетохар:',
-'revdelete-reasonotherlist' => 'Ð\9aÑ\85ин Ð±Ð°Ñ\85Ñ\8cан',
+'revdelete-reasonotherlist' => 'Ð\9aÑ\85ин Ð±Ð°Ñ\85Ñ\8cна',
 'revdelete-edit-reasonlist' => 'Бахьанин список нисяр',
 'revdelete-offender' => 'АгӀона версен автор:',
 
@@ -1183,7 +1182,7 @@ $1",
 'mergehistory-invalid-destination' => 'Юзийна агӀона нийса корта хила еза.',
 'mergehistory-autocomment' => 'Дехьа яьккхина [[:$1]] [[:$2]] чу',
 'mergehistory-comment' => 'Дехьа яьккхина [[:$1]] [[:$2]] чу: $3',
-'mergehistory-reason' => 'Ð\91аÑ\85Ñ\8cан:',
+'mergehistory-reason' => 'Ð\91аÑ\85Ñ\8cна:',
 
 # Merge log
 'mergelog' => 'Цхьаьнатохаршан тептар',
@@ -1435,8 +1434,8 @@ $1",
 'right-bigdelete' => 'еха хийцаман истори йолу агӀонаш дӀаяхар',
 'right-deletelogentry' => 'тептар чура билгала дӀаяздарш дӀадахар а меттахӀиттадар а.',
 'right-deleterevision' => 'агӀонийн билгала версеш дӀаяхар а меттахӀиттаяр а',
-'right-deletedhistory' => 'дӀаяхна агӀонийн исторега хьажар дӀадаьккхина йоза тӀекхочехь доцуш',
-'right-deletedtext' => 'дӀадаьккхина йозане а хийцамашка а хьажар агӀонийн дӀаяхна версин юккъахь',
+'right-deletedhistory' => 'дÓ\80аÑ\8fÑ\8cÑ\85на Ð°Ð³Ó\80онийн Ð¸Ñ\81Ñ\82оÑ\80ега Ñ\85Ñ\8cажаÑ\80 Ð´Ó\80адаÑ\8cккÑ\85ина Ð¹Ð¾Ð·Ð° Ñ\82Ó\80екÑ\85оÑ\87еÑ\85Ñ\8c Ð´Ð¾Ñ\86Ñ\83Ñ\88',
+'right-deletedtext' => 'дÓ\80адаÑ\8cккÑ\85ина Ð¹Ð¾Ð·Ð°Ð½Ðµ Ð° Ñ\85ийÑ\86амаÑ\88ка Ð° Ñ\85Ñ\8cажаÑ\80 Ð°Ð³Ó\80онийн Ð´Ó\80аÑ\8fÑ\8cÑ\85на Ð²ÐµÑ\80Ñ\81ин Ñ\8eккÑ\8aаÑ\85Ñ\8c',
 'right-browsearchive' => 'дӀаяхна агӀонаш лахар',
 'right-undelete' => 'АгӀонаш меттахӀоттор',
 'right-suppressrevision' => 'куьйгалхойх хьулйина йолу агӀонийн версеш меттахӀиттаяр а хьажар а',
@@ -1535,7 +1534,7 @@ $1",
 'recentchanges-summary' => 'Лахахь гайтина хене хьаьжна Википедин агӀонашкахь тӀаьхьара бина хийцамаш',
 'recentchanges-noresult' => 'Билгал йинчу хенахь цхьа хийцамаш бина бац.',
 'recentchanges-feed-description' => 'Тергам бе тlаьхьара вики хийцаман хlокху ларца.',
-'recentchanges-label-newpage' => 'Оцу нисдарца кхоллина керла агlо.',
+'recentchanges-label-newpage' => 'Оцу нисдарца кхоьллина керла агӀо.',
 'recentchanges-label-minor' => 'Хlара нисдинарг къастийна жимо долушсан',
 'recentchanges-label-bot' => 'ХӀара нисдар шаболх бечо дина',
 'recentchanges-label-unpatrolled' => 'ХӀара нисдар хӀинца цхьано патрулировать дина дац',
@@ -1611,7 +1610,7 @@ $1",
 'upload-prohibited' => 'Магийна доцу файлийн тайпанаш: $1.',
 'uploadlog' => 'Чуяхаран тéптар',
 'uploadlogpage' => 'Чуяхаран тéптар',
-'uploadlogpagetext' => 'Лахахьа гойтуш бу тӀаьххьара чуяхна файлийн могӀам.
+'uploadlogpagetext' => 'Ð\9bаÑ\85аÑ\85Ñ\8cа Ð³Ð¾Ð¹Ñ\82Ñ\83Ñ\88 Ð±Ñ\83 Ñ\82Ó\80аÑ\8cÑ\85Ñ\85Ñ\8cаÑ\80а Ñ\87Ñ\83Ñ\8fÑ\8cÑ\85на Ñ\84айлийн Ð¼Ð¾Ð³Ó\80ам.
 Ишта хьажа [[Special:NewFiles|керлачу файлийн галерей]].',
 'filename' => 'Файлан цӀе',
 'filedesc' => 'Файлах лаьцна',
@@ -1768,13 +1767,13 @@ $1',
 'filepage-nofile-link' => 'Ишта цӀе йолуш файл яц. Хьа йиш ю и [$1 чуяккха].',
 'uploadnewversion-linktext' => 'Чуяккха керла верси хӀокху файлан',
 'shared-repo-from' => '$1 чура',
-'shared-repo-name-wikimediacommons' => 'Ð\92икидlайÑ\83ллÑ\83Ñ\87е',
+'shared-repo-name-wikimediacommons' => 'Ð\92икигÑ\83лам',
 
 # File reversion
 'filerevert' => 'Тохарлера верси юхаерзор $1',
 'filerevert-legend' => 'Файлан верси юхаерзо',
 'filerevert-intro' => '<span class="plainlinks">Файл юхаерзош ю \'\'\'[[Media:$1|$1]]\'\'\' оцу [$4 верси $3, $2].</span>',
-'filerevert-comment' => 'Ð\91аÑ\85Ñ\8cан:',
+'filerevert-comment' => 'Ð\91аÑ\85Ñ\8cна:',
 'filerevert-defaultcomment' => 'Юхаерзош ю оцу $2, $1 хенахь хила верси',
 'filerevert-submit' => 'Юхаяккха',
 'filerevert-success' => "Юхаерзина файл '''[[Media:$1|$1]]''' оцу [$4 верси $3, $2].",
@@ -1784,13 +1783,13 @@ $1',
 'filedelete-legend' => 'ДӀаяккха файл',
 'filedelete-intro' => "Хьо файл '''[[Media:$1|$1]]''' дӀаяккха гӀерта цунна массо истори цхьан.",
 'filedelete-intro-old' => '<span class="plainlinks">Ахьа дӀайоккхуш ю верси \'\'\'[[Media:$1|$1]]\'\'\' цу [$4 $3, $2].</span>',
-'filedelete-comment' => 'Ð\91аÑ\85Ñ\8cан:',
+'filedelete-comment' => 'Ð\91аÑ\85Ñ\8cна:',
 'filedelete-submit' => 'ДӀаяккха',
 'filedelete-success' => '$1 дӀаяккхи.',
 'filedelete-success-old' => "Верси '''[[Media:$1|$1]]''' цу $3 $2 дӀаяьккхина.",
 'filedelete-nofile' => "'''$1''' яц.",
-'filedelete-otherreason' => 'Ð\9aÑ\85ин Ð±Ð°Ñ\85Ñ\8cан:',
-'filedelete-reason-otherlist' => 'Ð\9aÑ\85ин Ð±Ð°Ñ\85Ñ\8cан',
+'filedelete-otherreason' => 'Ð\9aÑ\85ин Ð±Ð°Ñ\85Ñ\8cна:',
+'filedelete-reason-otherlist' => 'Ð\9aÑ\85ин Ð±Ð°Ñ\85Ñ\8cна',
 'filedelete-reason-dropdown' => '* Даржина долу дӀаяккхаран баьхьанаш 
 ** Авторан бакъонаш талхор
 ** ЦхӀатера файлаш хилар',
@@ -1917,7 +1916,7 @@ $1',
 'protectedpages-expiry' => 'Чекхйолу',
 'protectedpages-performer' => 'Декъашхо ларор',
 'protectedpages-params' => 'ГӀаролийн параметраш',
-'protectedpages-reason' => 'Ð\91аÑ\85Ñ\8cан',
+'protectedpages-reason' => 'Ð\91аÑ\85Ñ\8cна',
 'protectedpages-unknown-timestamp' => 'Хууш дац',
 'protectedpages-unknown-performer' => 'Хууш доцу декъашхо',
 'protectedtitles' => 'ГIаролла дина цIераш',
@@ -2116,9 +2115,9 @@ $1',
 'dellogpage' => 'ДӀадаьхнарш долу тéптар',
 'dellogpagetext' => 'Лахахь гойтуш ду дӀадахаршан тептар.',
 'deletionlog' => 'дӀадаьхнарш долу тéптар',
-'deletecomment' => 'Ð\91аÑ\85Ñ\8cан:',
-'deleteotherreason' => 'Ð\9aÑ\85ин Ð±Ð°Ñ\85Ñ\8cан/Ñ\82lетохар:',
-'deletereasonotherlist' => 'Ð\9aÑ\85ин Ð±Ð°Ñ\85Ñ\8cан',
+'deletecomment' => 'Ð\91аÑ\85Ñ\8cна:',
+'deleteotherreason' => 'Ð\9aÑ\85ин Ð±Ð°Ñ\85Ñ\8cна/Ñ\82Ó\80етохар:',
+'deletereasonotherlist' => 'Ð\9aÑ\85ин Ð±Ð°Ñ\85Ñ\8cна',
 'deletereason-dropdown' => '* Даржина долу дӀаяккхаран баьхьанаш 
 ** зулма  
 ** авторан лаамца
@@ -2153,7 +2152,7 @@ $1',
 'protect-title' => 'Оцунна «$1» гӀоралла дар',
 'prot_1movedto2' => '«[[$1]]» цӀе хийцина оцу «[[$2]]»',
 'protect-legend' => 'Бакъде гӀоралла дар',
-'protectcomment' => 'Ð\91аÑ\85Ñ\8cан:',
+'protectcomment' => 'Ð\91аÑ\85Ñ\8cна:',
 'protectexpiry' => 'Чекхйолу:',
 'protect_expiry_invalid' => 'Нийса йоцу хан гlаролла дlайаларехь.',
 'protect_expiry_old' => 'Хан чаккхе — хьалхалера.',
@@ -2174,7 +2173,7 @@ $1',
 'protect-othertime' => 'Кхин хан:',
 'protect-othertime-op' => 'кхин хан',
 'protect-otherreason' => 'Кхин бахьна/тӀетохар:',
-'protect-otherreason-op' => 'Ð\9aÑ\85ин Ð±Ð°Ñ\85Ñ\8cан',
+'protect-otherreason-op' => 'Ð\9aÑ\85ин Ð±Ð°Ñ\85Ñ\8cна',
 'protect-dropdown' => '* ГӀоралла дарна баьхьаш 
 ** сих-сиха зулам дар 
 ** дуккха спам хилар
@@ -2199,10 +2198,10 @@ $1',
 'restriction-level-all' => 'массо барам',
 
 # Undelete
-'undelete' => 'ДӀаяхна агӀонашка хьажар',
-'undeletepage' => 'Ð\94Ó\80аÑ\8fÑ\85ина агӀонашка хьажар а меттахӀоттор а',
+'undelete' => 'Ð\94Ó\80аÑ\8fÑ\8cÑ\85на Ð°Ð³Ó\80онаÑ\88ка Ñ\85Ñ\8cажаÑ\80',
+'undeletepage' => 'Ð\94Ó\80аÑ\8fÑ\8cÑ\85на агӀонашка хьажар а меттахӀоттор а',
 'undeletepagetitle' => "'''Лахахь гайтина хӀокху [[:$1]] агӀона дӀаяхина версеш'''.",
-'viewdeletedpage' => 'ДӀаяхна йолу агӀонашка хьажар',
+'viewdeletedpage' => 'Ð\94Ó\80аÑ\8fÑ\8cÑ\85на Ð¹Ð¾Ð»Ñ\83 Ð°Ð³Ó\80онаÑ\88ка Ñ\85Ñ\8cажаÑ\80',
 'undelete-fieldset-title' => 'МеттахӀоттае версеш',
 'undeleteextrahelp' => "Ерриге агӀонан истори меттахӀоттая массо а билгалонаш еса а йити '''«{{int:undeletebtn}}»''' тӀетаӀае.
 ЦхӀайолу агӀонан версеш меттахӀоттая хьалха меттахӀоттош йолу версеш билгалъяьхна тӀетагӀе '''«{{int:undeletebtn}}»'''.",
@@ -2215,7 +2214,7 @@ $1',
 'undeletelink' => 'хьажа/меттахӀоттае',
 'undeleteviewlink' => 'хьажа',
 'undeleteinvert' => 'Къастае массо',
-'undeletecomment' => 'Ð\91аÑ\85Ñ\8cан:',
+'undeletecomment' => 'Ð\91аÑ\85Ñ\8cна:',
 'undeletedrevisions' => '{{PLURAL:$1|меттахӀоттайина}} $1 {{PLURAL:$1|хийцам}}',
 'undeletedfiles' => '$1 {{PLURAL:$1|файл меттахӀоттайина|файлаш меттахӀоттайина|файлаш меттахӀоттайина}}',
 'undeletedpage' => "'''МеттахӀоттайина агӀо «$1».'''
@@ -2294,7 +2293,7 @@ $1',
 Лахахь билгалде блоктохарна бахьна.',
 'ipadressorusername' => 'IP-адрес я декъашхочун цӀе:',
 'ipbexpiry' => 'Хан чекхйолу:',
-'ipbreason' => 'Ð\91аÑ\85Ñ\8cан:',
+'ipbreason' => 'Ð\91аÑ\85Ñ\8cна:',
 'ipbreason-dropdown' => '* Белхан некъ дӀакъовлар бахьанаш:
 ** Харца хаам бар
 ** АгӀонан чураниг дӀаяккхар
@@ -2339,7 +2338,7 @@ $1',
 'blocklist-expiry' => 'Чекхйолу',
 'blocklist-by' => 'Цунна блоктоьхана куьйгалхо',
 'blocklist-params' => 'Блоктохаран параметраш',
-'blocklist-reason' => 'Ð\91аÑ\85Ñ\8cан:',
+'blocklist-reason' => 'Ð\91аÑ\85Ñ\8cна:',
 'ipblocklist-submit' => 'Лаха',
 'infiniteblock' => 'хан чаккхе йоцуш',
 'expiringblock' => 'чекхйолу $1 $2',
@@ -2425,7 +2424,7 @@ $1',
 'movesubpage' => '{{PLURAL:$1|1=Бухара агӀо|Бухара агӀонаш}}',
 'movesubpagetext' => 'ХӀокху агӀона $1 {{PLURAL:$1|1=бухара агӀо ю|бухара агӀонаш ю}}.',
 'movenosubpage' => 'ХӀокху агӀона бухара агӀонаш яц.',
-'movereason' => 'Ð\91аÑ\85Ñ\8cан:',
+'movereason' => 'Ð\91аÑ\85Ñ\8cна:',
 'revertmove' => 'юхаяккха',
 'delete_and_move' => 'Цle а хуьйцуш дӀаяккха',
 'delete_and_move_text' => '== ДӀаяккха хьокъ ю ==
@@ -2500,7 +2499,7 @@ $1',
 'tooltip-pt-userpage' => 'Декъашхочуьна агlо',
 'tooltip-pt-mytalk' => 'Сан дийцаре агlо',
 'tooltip-pt-preferences' => 'Хьан гlирс нисбар',
-'tooltip-pt-watchlist' => 'Ахьа тергам бо агlонаши хийцаман могlам',
+'tooltip-pt-watchlist' => 'Ахьа тергам бо агӀонийн хийцаман могӀам',
 'tooltip-pt-mycontris' => 'Хьан нисдаран могlам',
 'tooltip-pt-login' => 'Хlокху гlирса чохь дlавазвала/яла мега, амма иза тlедожош дац.',
 'tooltip-pt-logout' => 'Дlадерзадо болх бар',
@@ -2533,7 +2532,7 @@ $1',
 'tooltip-t-contributions' => 'ХӀокху декъашхочо хийцина йолу агӀонийн могӀам',
 'tooltip-t-emailuser' => 'ДӀабахьийта хаам оцу декъашхона',
 'tooltip-t-upload' => 'Чуйаха файлаш',
-'tooltip-t-specialpages' => 'Белха агlонаши могlам',
+'tooltip-t-specialpages' => 'Белха агӀонанийн могӀам',
 'tooltip-t-print' => 'Хlокху агlонна зорба туху башхо',
 'tooltip-t-permalink' => 'Даима йолу хьажораг хӀокху башха агӀонна',
 'tooltip-ca-nstab-main' => 'Яззамна чулацам',
@@ -2552,7 +2551,7 @@ $1',
 'tooltip-compareselectedversions' => 'Хlокху шина хаьржина агlона башхо муха ю хьажа.',
 'tooltip-watch' => 'ТӀетоха хӀара агӀо сан тергаме могӀанан юкъа',
 'tooltip-rollback' => 'Цхьоз тlетаlийча дlабаккха кхечо бина болу тlаьххьара хийцам',
-'tooltip-undo' => 'Дlабаккха бина болу хийцам а хьалхьажар гойтуш, дlайаккхарна бахьан гайта аьтту беш',
+'tooltip-undo' => 'ДӀабаккха бина болу хийцам а хьалхьажар гойтуш, дӀаяккхарна бахьна гайта аьтту беш',
 'tooltip-summary' => 'Язъе йоца цӀе',
 
 # Stylesheets
@@ -2921,7 +2920,7 @@ MediaWiki яржош ю и шуна пайдане хир яц те аьлла,
 'specialpages-group-media' => 'Жамlаш оцу медиа-гlирсашан а чуяхарш',
 'specialpages-group-users' => 'Декъашхой а бакъонаш',
 'specialpages-group-highuse' => 'Уггаре дукха лелайо агlонаш',
-'specialpages-group-pages' => 'Агlонаши могlамаш',
+'specialpages-group-pages' => 'АгӀонийн могӀанаш',
 'specialpages-group-pagetools' => 'ГӀирсаш оцу агӀонашан',
 'specialpages-group-wiki' => 'Хаамаш а гӀирсаш а',
 'specialpages-group-redirects' => 'Дlасахьажош йолу гlуллакхан агlонаш',
index 2c9743e..7325b13 100644 (file)
@@ -705,6 +705,8 @@ $2',
 'login-throttled' => 'ژمارەیەکی زۆر هەوڵت داوە بۆ چوونە ژوورەوە.
 تکایە پێش هەوڵی دووبارە، نەختێک بوەستە.',
 'loginlanguagelabel' => 'زمان: $1',
+'pt-login' => 'بچۆ ژوورەوە',
+'pt-createaccount' => 'ھەژمار دروست بکە',
 'pt-userlogout' => 'بچۆ دەرەوە',
 
 # Change password dialog
@@ -1074,8 +1076,6 @@ $3 هۆکاری "$2" خستوەتەڕوو',
 'revdelete-show-file-submit' => 'بەڵێ',
 'revdelete-selected' => "'''{{PLURAL:$2|پێداچوونەوەی هەڵبژێراوی|پێداچوونەوەکانی هەڵبژێراوی}} [[:$1]]:'''",
 'logdelete-selected' => "'''{{PLURAL:$1|لۆگی ڕووداوەی هەڵبژێراو|لۆگی ڕووداوە هەڵبژێراوەکان}}:'''",
-'revdelete-text' => "'''پێداچوون و ڕووداوە سڕاوەکان هێشتا لە لاپەڕەی مێژوو و لۆگەکان دەست دەکەون، بەڵام ناوەڕۆکی ھێندێکیان بەرچاوی گشتیی ناکەون.'''<br />
-بەڕێوبەرانی دیکە لە {{SITENAME}}دا، هێشتا دەتوانن دەستکارییە شاراوەکان ببینن و لە ڕێگەی ھەر ئەم فۆڕمەوە بیانگەڕێننەوە، مەگەر ئەوەی بەربەستی دیکە داندرابێت.",
 'revdelete-confirm' => 'تکایە بەڵێن بدە کە دەتەوێ ئەوە بکەی و لە ئەنجامەکانی ئەوە ئاگاداریت و بە پێی [[{{MediaWiki:Policy-url}}|سیاسەتنامە]] ئەنجامی ئەدەی.',
 'revdelete-suppress-text' => "بەرگری دەبێ '''تەنها''' بۆ ئەم بابەتانە بەکاربهێندرێت:<br />
 * سووکایەتیکردن بە کەسایەتییەک<br />
@@ -1499,6 +1499,7 @@ $1",
 'recentchanges' => 'دوایین گۆڕانکارییەکان',
 'recentchanges-legend' => 'ھەڵبژاردەکانی دوایین گۆڕانکارییەکان',
 'recentchanges-summary' => 'لەم پەڕەیەدا شوێنی دوایین گۆڕانکارییەکانی ویکی بکەوە.',
+'recentchanges-noresult' => 'ھیچ گۆڕانکارییەک لە نێوان ماوەی پێدراو لەگەڵ ئەم پێوەرانە وێک نەھاتەوە.',
 'recentchanges-feed-description' => 'دوای دوایین گۆڕانکارییەکانی ئەم ویکیە بکەوە لەم «فید»ەوە.',
 'recentchanges-label-newpage' => 'ئەم دەستکارییە پەڕەیەکی نوێی دروست کرد',
 'recentchanges-label-minor' => 'ئەمە دەستکارییەکی بچووکە',
index 68d79ca..b2eaaeb 100644 (file)
@@ -904,6 +904,7 @@ Než to zkusíte znovu, musíte počkat na vypršení lhůty $1.',
 'createacct-another-realname-tip' => 'Skutečné jméno je nepovinné.
 Pokud se ho rozhodnete uvést, bude použito pro označení autorství vaší práce.',
 'pt-login' => 'Přihlášení',
+'pt-login-button' => 'Přihlásit se',
 'pt-createaccount' => 'Vytvoření účtu',
 'pt-userlogout' => 'Odhlásit se',
 
@@ -1316,9 +1317,10 @@ Můžete si toto porovnání prohlédnout; podrobnosti jsou uvedeny v [{{fullurl
 'revdelete-show-file-submit' => 'Ano',
 'revdelete-selected' => "'''{{PLURAL:$2|Vybraná|Vybrané}} revize stránky [[:$1]]:'''",
 'logdelete-selected' => "'''{{PLURAL:$1|Vybraná protokolovaná událost|Vybrané protokolované události}}:'''",
-'revdelete-text' => "'''Smazané verze a události budou nadále zobrazeny v historii stránky a protokolovacích záznamech, ale některé jejich části nebudou veřejně dostupné.'''
-Ostatní správci {{GRAMMAR:2sg|{{SITENAME}}}} si budou moci skrytý obsah prohlížet a pomocí stejného rozhraní jej také obnovit,
-pokud nebyla nastavena další omezení.",
+'revdelete-text-text' => 'Smazané editace se budou i nadále zobrazovat v historii stránky, ale části jejich obsahu nebudou veřejně přístupné.',
+'revdelete-text-file' => 'Smazané verze souborů se budou i nadále zobrazovat v historii stránky, ale části jejich obsahu nebudou veřejně přístupné.',
+'logdelete-text' => 'Smazané protokolovací záznamy se budou i nadále zobrazovat v historii stránky, ale části jejich obsahu nebudou veřejně přístupné.',
+'revdelete-text-others' => 'Ostatní správci {{grammar:2sg|{{SITENAME}}}} budou i nadále moci ke skrytému obsahu přistupovat a mohou ho pomocí stejného rozhraní obnovit, pokud nejsou nastavena dodatečná omezení.',
 'revdelete-confirm' => 'Prosím potvrďte, že to opravdu chcete učinit, že si uvědomujete důsledky a že je to v souladu s [[{{MediaWiki:Policy-url}}|pravidly]].',
 'revdelete-suppress-text' => "Utajování by se mělo používat '''pouze''' v následujících případech:
 * Potenciálně pomlouvačné informace
@@ -1328,7 +1330,7 @@ pokud nebyla nastavena další omezení.",
 'revdelete-hide-text' => 'Text revize',
 'revdelete-hide-image' => 'Skrýt obsah souboru',
 'revdelete-hide-name' => 'Skrýt událost a cíl',
-'revdelete-hide-comment' => 'Editační komentář',
+'revdelete-hide-comment' => 'Shrnutí editace',
 'revdelete-hide-user' => 'Uživatelské jméno / IP adresa',
 'revdelete-hide-restricted' => 'Utajit data i před správci',
 'revdelete-radio-same' => '(neměnit)',
index f7b8ee5..65fba14 100644 (file)
@@ -1058,8 +1058,6 @@ Serch hyn, gallwch eu cymharu o hyd; cewch weld y manylion ar y [{{fullurl:{{#Sp
 'revdelete-show-file-submit' => 'Ydw',
 'revdelete-selected' => "'''Y {{PLURAL:$2|golygiad|golygiad|golygiadau|golygiadau|golygiadau|golygiadau}} dewisedig o [[:$1]]:'''",
 'logdelete-selected' => "'''{{PLURAL:$1|Digwyddiad|Digwyddiad|Digwyddiadau|Digwyddiadau|Digwyddiadau|Digwyddiadau}} a ddewiswyd o'r lòg:'''",
-'revdelete-text' => "'''Fe fydd y golygiadau a'r digwyddiadau sydd wedi eu diddymu i'w gweld o hyd yn hanes y dudalen ac yn y logiau, ond ni fydd y cyhoedd yn gallu gweld y cynnwys i gyd.'''
-Fe fydd gweinyddwyr eraill {{SITENAME}} o hyd yn gallu gweld yr hyn a guddiwyd. Fe allant ei ddatguddio trwy ddefnyddio'r dudalen arbennig hon, cyhyd ag nad oes cyfyngiadau ychwanegol wedi eu gosod.",
 'revdelete-confirm' => "Byddwch gystal â chadarnhau eich bod yn bwriadu gwneud hyn, eich bod yn deall yr effaith a gaiff, a'ch bod yn ei wneud yn ôl y [[{{MediaWiki:Policy-url}}|y polisi]].",
 'revdelete-suppress-text' => "'''Dim ond''' yn yr achosion sy'n dilyn y dylech fentro cuddio gwybodaeth:
 * Gwybodaeth a all fod yn enllib
index 8908de6..4a76432 100644 (file)
@@ -1144,8 +1144,6 @@ Du kan se denne forskel; der kan findes detaljer i [{{fullurl:{{#Special:Log}}/s
 'revdelete-show-file-submit' => 'Ja',
 'revdelete-selected' => "'''{{PLURAL:$2|Valgte version|Valgte versioner}} af '''$1:''''''",
 'logdelete-selected' => "'''{{PLURAL:$1|Valgt logindførsel|Valgte logindførsler}}:'''",
-'revdelete-text' => "'''Slettede versioner vil fortsat vises i sidehistorik og på logsider, men dele af deres indhold vil ikke være offentligt tilgængeligt.'''
-Andre administratorer på {{SITENAME}} vil fortsat være i stand til at se det skjulte indhold og kan gendanne det igen, medmindre der laves yderligere restriktioner.",
 'revdelete-confirm' => 'Vær venlig at bekræfte at du vil gøre dette, at du forstår konsekvenserne, og at du gør det i overensstemmelse med [[{{MediaWiki:Policy-url}}|retningslinjerne]].',
 'revdelete-suppress-text' => "Der bør '''kun''' skjules i de følgende tilfælde:
 * Potentielt injurierende oplysninger
index 293de6d..5b1774f 100644 (file)
@@ -69,6 +69,7 @@
  * @author Tischbeinahe
  * @author UV
  * @author Umherirrender
+ * @author Useopensource tobias
  * @author Vogone
  * @author W (aka Wuzur)
  * @author Wikifan
@@ -429,7 +430,7 @@ $messages = array(
 'tog-hideminor' => 'Kleine Änderungen in den „Letzten Änderungen“ ausblenden',
 'tog-hidepatrolled' => 'Kontrollierte Änderungen in den „Letzten Änderungen“ ausblenden',
 'tog-newpageshidepatrolled' => 'Kontrollierte Seiten bei den „Neuen Seiten“ ausblenden',
-'tog-extendwatchlist' => 'Erweiterte Beobachtungsliste zur Anzeige aller Änderungen',
+'tog-extendwatchlist' => 'Beobachtungsliste erweitern, um statt nur der letzten Änderung alle Änderungen anzuzeigen.',
 'tog-usenewrc' => 'Änderungen auf „Letzte Änderungen“ und Beobachtungsliste nach Seite gruppieren',
 'tog-numberheadings' => 'Überschriften automatisch nummerieren',
 'tog-showtoolbar' => 'Bearbeiten-Werkzeugleiste anzeigen',
@@ -966,6 +967,7 @@ Bitte warte $1, bevor du es erneut probierst.',
 'createacct-another-realname-tip' => 'Der bürgerliche Name ist optional.
 Wenn du ihn angibst, wird er für die Zuordnung der Beiträge verwendet.',
 'pt-login' => 'Anmelden',
+'pt-login-button' => 'Anmelden',
 'pt-createaccount' => 'Benutzerkonto erstellen',
 'pt-userlogout' => 'Abmelden',
 
@@ -1379,8 +1381,10 @@ Du kannst diesen Versionsunterschied einsehen, sofern du möchtest. Nähere Anga
 'revdelete-show-file-submit' => 'Ja',
 'revdelete-selected' => "'''{{PLURAL:$2|Gewählte Version|Gewählte Versionen}} von [[:$1]]:'''",
 'logdelete-selected' => "'''{{PLURAL:$1|Gewählter Logbucheintrag|Gewählte Logbucheinträge}}:'''",
-'revdelete-text' => "'''Gelöschte Versionen und Aktionen verbleiben in der Versionsgeschichte und den Logbüchern, jedoch sind Teile davon für die Öffentlichkeit unzugänglich.'''
-Andere Administratoren auf {{SITENAME}} haben Zugriff auf den versteckten Inhalt und können ihn mit der gleichen Seite wiederherstellen, sofern nicht zusätzliche Einschränkungen bestehen.",
+'revdelete-text-text' => 'Gelöschte Versionen verbleiben noch in der Versionsgeschichte, jedoch sind Teile ihres Inhalts für die Öffentlichkeit nicht zugänglich.',
+'revdelete-text-file' => 'Gelöschte Dateiversionen verbleiben noch in der Datei-Versionsgeschichte, jedoch sind Teile ihres Inhalts für die Öffentlichkeit nicht zugänglich.',
+'logdelete-text' => 'Gelöschte Logbucheinträge verbleiben noch in den Logbüchern, jedoch sind Teile ihres Inhalts für die Öffentlichkeit nicht zugänglich.',
+'revdelete-text-others' => 'Andere Administratoren auf {{SITENAME}} haben noch Zugriff auf den versteckten Inhalt und können ihn auch mithilfe dieser Spezialseite wiederherstellen, solange keine zusätzlichen Beschränkungen festgelegt werden.',
 'revdelete-confirm' => 'Bitte bestätige, dass du beabsichtigst, dies zu tun, die Konsequenzen verstehst und es in Übereinstimmung mit den [[{{MediaWiki:Policy-url}}|Richtlinien]] tust.',
 'revdelete-suppress-text' => "Unterdrückungen sollten '''nur''' in den folgenden Fällen vorgenommen werden:
 * Potentiell beleidigende Informationen
@@ -1515,7 +1519,7 @@ Einzelheiten sind im [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}}
 'search-file-match' => '(treffende Dateiinhalte)',
 'search-suggest' => 'Meintest du „$1“?',
 'search-interwiki-caption' => 'Schwesterprojekte',
-'search-interwiki-default' => '$1 Ergebnisse:',
+'search-interwiki-default' => 'Ergebnisse von $1:',
 'search-interwiki-more' => '(weitere)',
 'search-relatedarticle' => 'Verwandte',
 'searcheverything-enable' => 'In allen Namensräumen suchen',
index 925491c..4f0a35e 100644 (file)
@@ -1277,8 +1277,6 @@ Eke şıma serkari u devam bıkeri [$1 no vurnayiş şıma eşkeni bıvini].",
 'revdelete-show-file-submit' => 'E',
 'revdelete-selected' => "'''[[:$1]]: ra {{PLURAL:$2|çımraviyarnayışo weçinıte|çımraviyarnayışê weçinıtey}}'''",
 'logdelete-selected' => "'''{{PLURAL:$1|Qeydbiyayışo weçinıte|Qeydbiyayışê weçinıtey}}:'''",
-'revdelete-text' => "'''Çımraviyarnayışê esterıtey u kerdışi hewna tarixê pele u qeydan de asenê, hema parçeyê zerrekê dinan areze nêbenê.'''
-Eke şertê ilawekerdey ke niyê ro, idarekerê bini {{SITENAME}} de nêşenê hewna bıresê zerrekê nımıtey u şenê ey anciya na eyni miyanpele ra peyser biarê.",
 'revdelete-confirm' => 'Ma rica keno testiq bike ti ena hereket keno u ti zano neticeyanê herketanê xo u ti ena hereket pê ena [[{{MediaWiki:Policy-url}}|polici]] ra keno.',
 'revdelete-suppress-text' => "Wedardış gani '''tenya''' nê halanê cêrênan de bıxebıtiyo:
 * Melumatê kıfırio mıhtemel
@@ -2439,7 +2437,7 @@ qey heqê şexsi de [[{{MediaWiki:Listgrouprights-helppage}}|hema malumato ziyed
 Ena deme ra, ma qe vurnayışan ser ena pele tı haberdar keni.',
 'removewatch' => 'Listedê mınê seyr kerdışi ra hewad',
 'removedwatchtext' => 'Ena pela "[[:$1]]" biya wedariya [[Special:Watchlist|listeyê seyr-kerdışi şıma]].',
-'watch' => 'Temaşe ke',
+'watch' => 'Seyr ke',
 'watchthispage' => 'Ena pele seyr ke',
 'unwatch' => 'Teqib mekerê',
 'unwatchthispage' => 'temaşa kerdışê peli vındarn.',
@@ -4322,7 +4320,7 @@ satır ê ke pê ney # # destpêkenê zey mışore/mıjore muamele vineno.
 
 # Feedback
 'feedback-bugornote' => 'Jew mersela teferruato teknik esta şıma reca malumatê şıma hazıro se [ $1  jew xırab rapor] bıvinê.Zewbi zi, formê cerê xo rê şenê karfiyê. Vatışê xo pela da "[ $3  $2 ]", namey karber dê xoya piya u wasteriya karfiye.',
-'feedback-subject' => 'Mersel:',
+'feedback-subject' => 'Mewzu:',
 'feedback-message' => 'Mesac:',
 'feedback-cancel' => 'Bıtexelne',
 'feedback-submit' => 'Peyxeberdar Bırşe',
index e2351d6..ed07328 100644 (file)
@@ -683,6 +683,7 @@ Móžoš toś te zdźělenje ignorowaś, jolic toś te konto jo se jano zamólnj
 'createacct-another-realname-tip' => 'Napšawdne mě jo opcionalne.
 Jolic jo pódajoš, buźo se to wužywaś, aby pśinoski pśirědowało.',
 'pt-login' => 'Pśizjawiś',
+'pt-login-button' => 'Pśizjawiś',
 'pt-createaccount' => 'Konto załožyś',
 'pt-userlogout' => 'Wótzjawiś',
 
@@ -1083,8 +1084,6 @@ Móžoš se toś ten rozdźěl woglědaś; drobnostki glědaj w [{{fullurl:{{#Sp
 'revdelete-show-file-submit' => 'Jo',
 'revdelete-selected' => "'''{{PLURAL:$2|Wuzwólona wersija|Wuzwólonej wersiji|Wuzwólone wersije}} wót [[:$1]].'''",
 'logdelete-selected' => "'''{{PLURAL:$1|Wuzwólony protokolowe tšojenje|Wuzwólonej protokolowe tšojeni|wuzwólone protokolowe tšojenja}}:'''",
-'revdelete-text' => "'''Wulašowane wersije a tšojenja budu se dalej w stawiznach boka a w protokolach pokazaś, ale źěle jich wopśimjeśa njebudu pśistupne za zjawnosć.'''
-Dalšne administratory na {{GRAMMAR:lokatiw|{{SITENAME}}}} mógu ale pśecej hyšći pśistup na schowane wopśimjeśe měś a mógu jo pśez samki interfejs wótnowiś,  snaźkuli su pśidatne wobgranicowanja.",
 'revdelete-confirm' => 'Pšosym wobkšuś, až coš to cyniś, až rozmějoš konsekwence a až cyniš to pó [[{{MediaWiki:Policy-url}}|pšawidłach]].',
 'revdelete-suppress-text' => "Pódtłocenje by dejało se '''jano''' za slědujuce pady wužywaś:
 * Potencielnje ranjece informacije
@@ -1218,7 +1217,7 @@ Drobnostki móžoš w [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}
 'search-file-match' => '(wótpowědujo datajowemu wopśimjeśeju)',
 'search-suggest' => 'Měnjašo $1?',
 'search-interwiki-caption' => 'Sotšine projekty',
-'search-interwiki-default' => '$1 wuslědki:',
+'search-interwiki-default' => 'Wuslědki z $1:',
 'search-interwiki-more' => '(wěcej)',
 'search-relatedarticle' => 'swójźbne',
 'searcheverything-enable' => 'We wšych mjenjowych rumach pytaś',
@@ -2332,7 +2331,7 @@ Pšašanja a dalšna pomoc:
 'delete-toobig' => 'Toś ten bok ma z wěcej nježli $1 {{PLURAL:$1|wersiju|wersijomaj|wersijami|wersijami}} dłujku historiju. Lašowanje takich bokow bu wobgranicowane, aby wobškoźenju {{GRAMMAR:genitiw|{{SITENAME}}}} z pśigódy zajźowało.',
 'delete-warning-toobig' => 'Toś ten bok ma z wěcej ako $1 {{PLURAL:$1|wersiju|wersijomaj|wersijami|wersijami}} dłujke stawizny. Jich wulašowanje móžo źěło datoweje banki na {{SITENAME}} kazyś;
 póstupujśo z glědanim.',
-'deleting-backlinks-warning' => "'''Warnowanje:''' Druge boki wótkazuju k bokoju abo bok jo hynźi zapśěgnjony, kótaryž coš wulašowaś.",
+'deleting-backlinks-warning' => "'''Warnowanje:''' [[Special:WhatLinksHere/{{FULLPAGENAME}}|Druge boki]] wótkazuju k bokoju abo bok jo hynźi zapśěgnjony, kótaryž coš wulašowaś.",
 
 # Rollback
 'rollback' => 'Wobźěłanja slědk wześ',
index 897ea5c..f293c95 100644 (file)
@@ -529,6 +529,7 @@ Se l'inscrisiòun l'é stêda fâta per şbâli, es pōl scanşlêr sté mesâg.
 'suspicious-userlogout' => "La tó dmânda per destachêret l'é stēda rifiutêda perchè la sèmbra spidîda da un navigadōr ch' al funsiòuna mìa o da un proxy di caching.",
 'createacct-another-realname-tip' => "Druvêr al nòm vèira l'é 'na siēlta personêla; s' es pèinsa 'd ruvêrel al gnirâ uşê per dêr la paternitê di lavōr spidî.",
 'pt-login' => 'Và dèinter',
+'pt-login-button' => 'Và dèinter',
 'pt-createaccount' => 'Fà la tó inscrisiòun',
 'pt-userlogout' => 'Và fōra',
 
@@ -728,7 +729,13 @@ Al tō mudéfichi în MIA incòra stêdi salvêdi.",
 'explainconflict' => "Un êter utèint l'à salvê 'na nōva versiòun ed la pàgina mèinter t'ēr adrē fêr dal mudéfichi. Int la caşèla 'd mudéfica ché 'd sōver a gh'é al tèst ed la pàgina che adès l'é in lénia, acsé cme l'é stêda salvêda da cl'êter utèint. La versiòun cun al tō mudéfichi invēci l'é int la caşèla dal mudéfichi ché sòta. S' ét vō cunfermêri, ét dēv purtêr al tō mudéfichi int al tèst che gh'é bèle (caşèla ché 'd sōver). Se té schés al ptòun '{{int:savearticle}}', a gnirà salvê '''sōl''' al tèst dèinter a la caşèla 'd mudéfica ché 'd sōver.",
 'yourtext' => 'Al tó tèst',
 'storedversion' => 'La versiòun in memôria',
+'nonunicodebrowser' => "'''Atèinti: a s'é drē druvêr un navigadōr ch' al và mìa d' acôrdi cun i carâter ''Unicode''. Per permèter la mudéfica dal pàgini sèinsa fêr d' incunveniĵnt, int la caşèla ed mudéfica i carâter mia ASCII a vînen fât vèder cme côdis eşadecimêl.'''",
+'editingold' => "<strong>Atèinti: a s'é drē mudifichêr 'na versiòun mìa arnuvêda 'd la pàgina.</strong> 
+S'es pèinsa ed salvêrla, tót i cambiamèint fât dōp cla mudéfica ché andrân pêrs.",
 'yourdiff' => 'Diferèinsi',
+'copyrightwarning' => "Per piaşèir tîn cûnt che tót al colaborasiòun a {{SITENAME}} a vînen cunsidrêdi publichêdi sòta la licèinsa $2 (per i particulêr guêrda $1). S' an 't vō mìa che i tō tèst a pôsen èser cambiê e turnê a publichêr da tót sèinsa lémit, an publichêri mìa ché.<br /> In pió, se 't  i póblich ché, a 't dichiâr, sòta la tó responsabilitê, che còl ch' è stê scrét a 't l'ê scrét té personalmèint opór l'é ste cupiê da documèint sèinsa ch' al sìa quacê da nisûn dirét 'd autōr. <strong> Ché insém an pubblichêr mìa materiêl quacê da dirét 'd autōr sèinsa autorişâsiòun! </strong>",
+'copyrightwarning2' => "Per piaşèir tîn cûnt che tót al colaborasiòun a {{SITENAME}} a pōlen èser mudifichê, arversê o scanşlê da êtra gînta cla dà 'na mân. S' an 't vō mìa che i tō tèst a pôsen èser cambiê alōra an publichêri mìa ché.<br />In pió, se 't  i póblich ché, a 't dichiâr, sòta la tó responsabilitê, che còl ch' è stê scrét a 't l'ê scrét té personalmèint opór l'é ste cupiê da documèint sèinsa ch' al sìa quacê da nisûn dirét 'd autōr (per i particulêr guêrda $1). <strong> Ché insém an pubblichêr mìa materiêl quacê da dirét 'd autōr sèinsa autorişâsiòun! </strong>",
+'longpageerror' => "<strong> Erōr: al tèst spidî l'é lòngh {{PLURAL:$1|1|$1}} kilobyte, ch'l'é pió grôs ed l'amzûra mâsima permésa ({{PLURAL:$2|1|$2}} kilobyte). </strong> Al tèst al pôl mìa èser salvê.",
 'templatesused' => '{{PLURAL:$1|Mudèl druvê|Mudē druvê}} in cla pàgina ché:',
 'template-protected' => '(prutèt)',
 'template-semiprotected' => '(mèz-prutèt)',
index b3c1c39..d216f69 100644 (file)
@@ -1309,8 +1309,6 @@ Mπορείτε να δείτε αυτή την διαφορά. Λεπτομέρ
 'revdelete-show-file-submit' => 'Ναι',
 'revdelete-selected' => "'''{{PLURAL:$2|Επιλεγμένη έκδοση|Επιλεγμένες εκδόσεις}} της [[:$1]]:'''",
 'logdelete-selected' => "'''{{PLURAL:$1|Επιλεγμένο γεγονός αρχείου καταγραφής|Επιλεγμένα γεγονότα αρχείου καταγραφής}}:'''",
-'revdelete-text' => "'''Οι διεγραμμένες αναθεωρήσεις και τα γεγονότα θα εμφανίζονται ακόμα στο ιστορικό της σελίδας και στα αρχεία καταγραφών, αλλά μέρη του περιεχομένου τους θα είναι απροσπέλαστα στο κοινό.'''
-Άλλοι διαχειριστές στον ιστότοπο {{SITENAME}} θα είναι ακόμα ικανοί να προσπελάσουν το κρυμμένο περιεχόμενο και μπορούν να το επαναφέρουν ξανά μέσω αυτής της διεπαφής, εκτός αν τεθούν πρόσθετοι περιορισμοί.",
 'revdelete-confirm' => 'Παρακαλούμε επιβεβαιώστε ότι σκοπεύετε να το κάνετε αυτό, ότι αντιλαμβάνεσθε τις συνέπειες, και ότι το κάνετε σύμφωνα με την [[{{MediaWiki:Policy-url}}|πολιτική]].',
 'revdelete-suppress-text' => 'Η καταστολή μπορεί να χρησιμοποιηθεί <strong> μόνο </strong> για τις ακόλουθες περιπτώσεις:
 * Ενδεχόμενη συκοφαντική δυσφήμιση
index 31da2a2..df17d8f 100644 (file)
@@ -1252,6 +1252,7 @@ Please wait $1 before trying again.',
 'createacct-another-realname-tip' => 'Real name is optional.
 If you choose to provide it, this will be used for giving the user attribution for their work.',
 'pt-login'                        => 'Log in',
+'pt-login-button'                 => 'Log in',
 'pt-createaccount'                => 'Create account',
 'pt-userlogout'                   => 'Log out',
 
@@ -1709,8 +1710,10 @@ function, the specified revision does not exist, or you are attempting to hide t
 'revdelete-show-file-submit'  => 'Yes',
 'revdelete-selected'          => '<strong>{{PLURAL:$2|Selected revision|Selected revisions}} of [[:$1]]:</strong>',
 'logdelete-selected'          => '<strong>{{PLURAL:$1|Selected log event|Selected log events}}:</strong>',
-'revdelete-text'              => '<strong>Deleted revisions and events will still appear in the page history and logs, but parts of their content will be inaccessible to the public.</strong>
-Other administrators on {{SITENAME}} will still be able to access the hidden content and can undelete it again through this same interface, unless additional restrictions are set.',
+'revdelete-text-text'         => 'Deleted revisions will still appear in the page history, but parts of their content will be inaccessible to the public.',
+'revdelete-text-file'         => 'Deleted file versions will still appear in the file history, but parts of their content will be inaccessible to the public.',
+'logdelete-text'              => 'Deleted log events will still appear in the logs, but parts of their content will be inaccessible to the public.',
+'revdelete-text-others'       => 'Other administrators on {{SITENAME}} will still be able to access the hidden content and can undelete it again through this same interface, unless additional restrictions are set.',
 'revdelete-confirm'           => 'Please confirm that you intend to do this, that you understand the consequences, and that you are doing this in accordance with [[{{MediaWiki:Policy-url}}|the policy]].',
 'revdelete-suppress-text'     => 'Suppression should <strong>only</strong> be used for the following cases:
 * potentially libelous information
@@ -1850,7 +1853,7 @@ Details can be found in the [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENA
 'search-file-match'                => '(matches file content)',
 'search-suggest'                   => 'Did you mean: $1',
 'search-interwiki-caption'         => 'Sister projects',
-'search-interwiki-default'         => '$1 results:',
+'search-interwiki-default'         => 'Results from $1:',
 'search-interwiki-custom'          => '', # do not translate or duplicate this message to other languages
 'search-interwiki-more'            => '(more)',
 'search-relatedarticle'            => 'Related',
index e2405f4..0a3d717 100644 (file)
@@ -1280,8 +1280,6 @@ funkcion, la specifita versio ne ekzistas, aŭ vi estas provanta kaŝi la nunan
 'revdelete-show-file-submit' => 'Jes',
 'revdelete-selected' => "'''{{PLURAL:$2|Selektata versio|Selektataj versioj}} de [[:$1]]:'''",
 'logdelete-selected' => "'''{{PLURAL:$1|Selektata protokola evento|Selektataj protokolaj eventoj}}:'''",
-'revdelete-text' => "'''Forigitaj versioj kaj eventoj plu aperos en la historipaĝoj, sed iliaj tekstoj ne estos alireblaj de la publiko.'''
-Aliaj administrantoj ĉe {{SITENAME}} plu povos aliri la kaŝitan entenon kaj restarigi ĝin per la sama interfaco, krom se plia limigo estas metita de la paĝaradministrantoj.",
 'revdelete-confirm' => 'Bonvolu konfirmi ke vi intencias fari ĉi tion, ke vi komprenas la konsekvencojn kaj ke vi faras ĉi tion laŭ [[{{MediaWiki:Policy-url}}|la regularo]].',
 'revdelete-suppress-text' => "Subpremo '''nur''' estu uzata por la jenaj kazoj:
 * Ebla kalumnia informo
index ad82636..2f5279a 100644 (file)
@@ -509,7 +509,7 @@ $messages = array(
 'subcategories' => 'Subcategorías',
 'category-media-header' => 'Archivos multimedia en la categoría «$1»',
 'category-empty' => "''La categoría no contiene ninguna página o archivo.''",
-'hidden-categories' => '{{PLURAL:$1|Categoría escondida|Categorías escondidas}}',
+'hidden-categories' => '{{PLURAL:$1|Categoría oculta|Categorías ocultas}}',
 'hidden-category-category' => 'Categorías ocultas',
 'category-subcat-count' => '{{PLURAL:$2|Esta categoría solo contiene la siguiente subcategoría.|Esta categoría contiene {{PLURAL:$1|la siguiente subcategoría|las siguientes $1 subcategorías}}, de un total de $2.}}',
 'category-subcat-count-limited' => 'Esta categoría contiene {{PLURAL:$1|la siguiente subcategoría|las siguientes $1 subcategorías}}.',
@@ -679,7 +679,7 @@ $1',
 'site-rss-feed' => 'Canal RSS de $1',
 'site-atom-feed' => 'Canal Atom de $1',
 'page-rss-feed' => 'Canal RSS «$1»',
-'page-atom-feed' => 'Canal Atom «$1»',
+'page-atom-feed' => 'Canal Atom de «$1»',
 'red-link-title' => '$1 (la página no existe)',
 'sort-descending' => 'Orden descendente',
 'sort-ascending' => 'Orden ascendente',
@@ -1350,8 +1350,6 @@ Aún tiene la posibilidad de verla; puede ampliar los detalles en el [{{fullurl:
 'revdelete-show-file-submit' => 'Sí',
 'revdelete-selected' => "'''{{PLURAL:$2|Revisión seleccionada|Revisiones seleccionadas}} de [[:$1]]:'''",
 'logdelete-selected' => "'''{{PLURAL:$1|Seleccionado un evento|Seleccionados eventos}}:'''",
-'revdelete-text' => "Las revisiones borradas aún aparecerán en el historial de la página y en los registros, pero sus contenidos no serán accesibles al público.'''
-Otros administradores de {{SITENAME}} aún podrán acceder al contenido oculto y podrán deshacer el borrado a través de la misma interfaz, a menos que se establezcan restricciones adicionales.",
 'revdelete-confirm' => 'Por favor confirma que deseas realizar la operación, que entiendes las consecuencias y que estás ejecutando dicha acción acorde con [[{{MediaWiki:Policy-url}}|las políticas]].',
 'revdelete-suppress-text' => "La herramienta de supresión '''solo''' debería usarse en los siguientes casos:
 * información potencialmente injuriosa o calumniante.
@@ -3179,7 +3177,7 @@ No hay un directorio temporal.',
 'tooltip-pt-logout' => 'Salir de la sesión',
 'tooltip-ca-talk' => 'Discusión acerca del artículo',
 'tooltip-ca-edit' => 'Puedes editar esta página. Utiliza el botón de previsualización antes de guardar',
-'tooltip-ca-addsection' => 'Inicia una nueva sección',
+'tooltip-ca-addsection' => 'Iniciar una sección nueva',
 'tooltip-ca-viewsource' => 'Esta página está protegida.
 Puedes ver su código fuente',
 'tooltip-ca-history' => 'Versiones anteriores de esta página y sus autores',
@@ -3202,7 +3200,7 @@ Puedes ver su código fuente',
 'tooltip-n-randompage' => 'Cargar una página al azar',
 'tooltip-n-help' => 'El lugar para aprender',
 'tooltip-t-whatlinkshere' => 'Lista de todas las páginas del wiki que enlazan aquí',
-'tooltip-t-recentchangeslinked' => 'Cambios recientes en las páginas que enlazan con ésta',
+'tooltip-t-recentchangeslinked' => 'Cambios recientes en las páginas que enlazan con esta',
 'tooltip-feed-rss' => 'Sindicación RSS de esta página',
 'tooltip-feed-atom' => 'Sindicación Atom de esta página',
 'tooltip-t-contributions' => 'Lista de contribuciones de este usuario',
index b145235..fa4c165 100644 (file)
@@ -1254,8 +1254,6 @@ Saad seda muudatust vaadata. [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAG
 'revdelete-show-file-submit' => 'Jah',
 'revdelete-selected' => "'''Valitud {{PLURAL:$2|redaktsioon|redaktsioonid}} leheküljest [[:$1]]:'''",
 'logdelete-selected' => "'''Valitud {{PLURAL:$1|logisissekanne|logisissekanded}}:'''",
-'revdelete-text' => "'''Kustutatud redaktsioonid ja sündmused kajastuvad endiselt lehekülje ajaloos ja logides, kuid osa nende sisust pole avalikult nähtav.'''
-{{GRAMMAR:genitive|{{SITENAME}}}} administraatorid saavad peidetud sisu siiski vaadata ning seda vajadusel selle liidese kaudu taastada, kui see pole just täiendavalt keelatud.",
 'revdelete-confirm' => 'Kinnita, et soovid tõesti seda teha ning et saad aru tagajärgedest ja tegevus on kooskõlas [[{{MediaWiki:Policy-url}}|siinsete kokkulepetega]].',
 'revdelete-suppress-text' => "Andmed tuleks varjata '''ainult''' järgmistel juhtudel:
 * võimalik laim
@@ -1392,7 +1390,7 @@ Harilikult tähendab see seda, et sind siia juhatanud link on vananenud ja siin
 'search-file-match' => '(vastab faili sisule)',
 'search-suggest' => 'Kas mõtlesid: $1',
 'search-interwiki-caption' => 'Sõsarprojektid',
-'search-interwiki-default' => '$1 tulemused:',
+'search-interwiki-default' => 'Tulemused asukohast $1:',
 'search-interwiki-more' => '(veel)',
 'search-relatedarticle' => 'Seotud',
 'searcheverything-enable' => 'Otsi kõigist nimeruumidest',
@@ -2496,7 +2494,7 @@ Palun kinnita, et tahad seda tõepoolest teha, et sa mõistad tagajärgi ja et s
 Selle kustutamine on keelatud, et ära hoida ekslikku {{GRAMMAR:genitive|{{SITENAME}}}} töö häirimist.',
 'delete-warning-toobig' => 'See lehekülg on pika redigeerimislooga – üle {{PLURAL:$1|ühe muudatuse|$1 muudatuse}}.
 Ettevaatust, selle kustutamine võib esile kutsuda häireid {{GRAMMAR:genitive|{{SITENAME}}}} andmebaasi töös.',
-'deleting-backlinks-warning' => "'''Hoiatus:''' Teised leheküljed viitavad leheküljele, mida oled kustutamas, või see lehekülg on kasutuses mallina.",
+'deleting-backlinks-warning' => "'''Hoiatus:''' [[Special:WhatLinksHere/{{FULLPAGENAME}}|Teised leheküljed]] viitavad leheküljele, mida oled kustutamas, või see lehekülg on kasutuses mallina.",
 
 # Rollback
 'rollback' => 'Tühista muudatused',
index 06891a3..0a2d226 100644 (file)
@@ -1043,8 +1043,6 @@ Administratzailea zarenez, diff hau ikus dezakezu. Xehetasunak ikusgai daude [{{
 'revdelete-show-file-submit' => 'Bai',
 'revdelete-selected' => "'''{{PLURAL:$2|[[:$1]](r)en hautatutako berrikuspena:|[[:$1]](r)en hautatutako berrikuspenak}}'''",
 'logdelete-selected' => "'''{{PLURAL:$1|Aukeratutako log gertakaria|Aukeratutako log gertakariak}}:'''",
-'revdelete-text' => "'''Ezabatutako berrikuspenek orrialdearen historian agertzen jarraituko dute, baina bere edukiak ez dira publikoki eskuratu ahal izango.'''
-{{SITENAME}}ko administratzaileek ezkutuko eduki hau ikusteko aukera izango dute, eta baita leheneratzeko ere, gunearen arduradunek beste mugapenen bat ezartzen ez badute behintzat.",
 'revdelete-confirm' => 'Baiezta ezazu hori dela zure asmoa, ulertzen dituzula ondorioak, eta [[{{MediaWiki:Policy-url}}|irizpideak]] errespetatuz egiten ari zarela hau.',
 'revdelete-suppress-text' => "Ezabaketa '''bakarrik''' arrazoi hauek direla eta erabili beharko litzateke:
 * Informazio pertsonal desegokia
index 8a40873..bc78731 100644 (file)
@@ -665,9 +665,6 @@ puei bel detallis nel [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}
 'revdelete-show-file-submit' => 'Sí',
 'revdelete-selected' => "'''{{PLURAL:$2|Revisión aseñalá e|Revisionis aseñalás de}} '''[[:$1]]''':'''",
 'logdelete-selected' => "'''{{PLURAL:$1|Eventu el rustrihu aseñalau|Eventus del rustrihu aseñalaus}}:'''",
-'revdelete-text' => "'''Las revisionis esborrás entovia apaicirán nel estorial la páhina, peru el su continiu nu sedrá acesibri pal púbricu.'''
-
-El restu e çahorilis desti güiqui sí tendrán premisu pa visoreal el continiu açonchau, i revertil el esborrau si es mestel, a nu sel que los alministraoris del güiqui crein una restrición aicional.",
 'revdelete-legend' => 'Establecel restricionis de visibiliá',
 'revdelete-hide-text' => 'Açonchal el testu la revisión',
 'revdelete-hide-image' => 'Açonchal el continiu el archivu',
index dd79ead..648653b 100644 (file)
@@ -1006,7 +1006,8 @@ $2',
 'suspicious-userlogout' => 'درخواست شما برای خروج از سامانه رد شد زیرا به نظر می‌رسد که این درخواست توسط یک مرورگر معیوب یا پروکسی میانگیر ارسال شده باشد.',
 'createacct-another-realname-tip' => 'نام واقعی اختیاری است.
 اگر آن را وارد کنید هنگام ارجاع به آثارتان و انتساب آن‌ها به شما از نام واقعی‌تان استفاده خواهد شد.',
-'pt-login' => 'ورود به سامانه',
+'pt-login' => 'ورود',
+'pt-login-button' => 'ورود به سامانه',
 'pt-createaccount' => 'ایجاد حساب کاربری',
 'pt-userlogout' => 'خروج',
 
@@ -1431,8 +1432,6 @@ $2
 'revdelete-show-file-submit' => 'بله',
 'revdelete-selected' => "'''{{PLURAL:$2|نسخهٔ|نسخه‌های}} انتخاب شده از [[:$1]]:'''",
 'logdelete-selected' => "'''{{PLURAL:$1|مورد|موارد}} انتخاب شده از سیاهه:'''",
-'revdelete-text' => "'''نسخه‌ها و موارد حذف شده کماکان از طریق تاریخچهٔ صفحه و سیاهه‌ها قابل مشاهده هستند، اما بخش‌هایی از محتوای آن‌ها توسط عموم قابل مشاهده نخواهد بود.'''
-سایر مدیران {{SITENAME}} هنوز می‌توانند این محتوای پنهان را ببینند و از همین طریق موارد حذف شده را احیا کنند، مگر آن که محدودیت‌های دیگری اعمال گردد.",
 'revdelete-confirm' => 'لطفاً تأیید کنید که می‌خواهید این کار را انجام دهید، عواقب آن را درک می‌کنید و این کار را طبق [[{{MediaWiki:Policy-url}}|سیاست‌ها]] انجام می‌دهید.',
 'revdelete-suppress-text' => "فرونشانی باید '''تنها''' برای موارد زیر استفاده شود:
 * اطلاعات به طور بالقوه افتراآمیز
@@ -1566,7 +1565,7 @@ $1",
 'search-file-match' => '(تشابه محتوی پرونده)',
 'search-suggest' => 'آیا منظورتان این بود: $1',
 'search-interwiki-caption' => 'پروژه‌های خواهر',
-'search-interwiki-default' => '$1 نتیجه:',
+'search-interwiki-default' => 'نتایج از $1 :',
 'search-interwiki-more' => '(بیشتر)',
 'search-relatedarticle' => 'مرتبط',
 'searcheverything-enable' => 'جستجو در تمام فضاهای نام',
index 9ae59ec..b50bc8c 100644 (file)
@@ -594,7 +594,7 @@ $1',
 'youhavenewmessagesmulti' => 'Sinulla on uusia viestejä sivuilla $1',
 'editsection' => 'muokkaa',
 'editold' => 'muokkaa',
-'viewsourceold' => 'näytä lähdekoodi',
+'viewsourceold' => 'näytä wikiteksti',
 'editlink' => 'muokkaa',
 'viewsourcelink' => 'näytä lähdekoodi',
 'editsectionhint' => 'Muokkaa osiota $1',
@@ -853,6 +853,7 @@ Odota $1 ennen kuin yrität uudelleen.',
 'createacct-another-realname-tip' => 'Vapaaehtoinen.
 Nimesi näytetään käyttäjätunnuksesi sijasta sivun tekijäluettelossa.',
 'pt-login' => 'Kirjaudu sisään',
+'pt-login-button' => 'Kirjaudu sisään',
 'pt-createaccount' => 'Luo tunnus',
 'pt-userlogout' => 'Kirjaudu ulos',
 
@@ -1261,8 +1262,6 @@ Voit silti nähdä tämän muutoksen. Lisätietoja löytyy [{{fullurl:{{#Special
 'revdelete-show-file-submit' => 'Kyllä',
 'revdelete-selected' => "'''{{PLURAL:$2|Valittu versio|Valitut versiot}} sivusta [[:$1]]'''",
 'logdelete-selected' => "'''{{PLURAL:$1|Valittu lokimerkintä|Valitut lokimerkinnät}}:'''",
-'revdelete-text' => "'''Poistetut versiot ja lokitapahtumat näkyvät edelleen sivun historiassa ja lokeissa, mutta osa niiden sisällöstä ei ole julkisesti saatavilla.'''
-Muut ylläpitäjät {{GRAMMAR:inessive|{{SITENAME}}}} voivat silti tarkastella piilotettua sisältöä, ja he voivat palauttaa sen näkyviin tämän käyttöliittymän kautta, ellei tätä ole erikseen rajoitettu.",
 'revdelete-confirm' => 'Varmista, että haluat tehdä tämän – ymmärrät seuraukset ja teet tämän [[{{MediaWiki:Policy-url}}|käytäntöjen]] mukaisesti.',
 'revdelete-suppress-text' => "Häivytystä pitäisi käyttää '''vain''' seuraavissa tapauksissa:
 * Mahdollisesti henkilön kunniaa loukkaavia tietoja
index e71d267..8f2425a 100644 (file)
@@ -66,6 +66,7 @@
  * @author Lucyin
  * @author Manohisoa
  * @author Mattho69
+ * @author Maxim21
  * @author Maxime Corbin
  * @author McDutchie
  * @author Meithal
@@ -542,7 +543,7 @@ $messages = array(
 'category_header' => 'Pages dans la catégorie « $1 »',
 'subcategories' => 'Sous-catégories',
 'category-media-header' => 'Fichiers multimédias dans la catégorie « $1 »',
-'category-empty' => "''Cette catégorie ne contient aucune page, sous-catégorie ou fichier multimédia.''",
+'category-empty' => '<em>Cette catégorie ne contient aucune page, sous-catégorie ou fichier multimédia.</em>',
 'hidden-categories' => '{{PLURAL:$1|Catégorie cachée|Catégories cachées}}',
 'hidden-category-category' => 'Catégories cachées',
 'category-subcat-count' => 'Cette catégorie comprend {{PLURAL:$2|la sous-catégorie|$2 sous-catégories, dont {{PLURAL:$1|celle|les $1}}}} ci-dessous.',
@@ -960,6 +961,7 @@ Veuillez attendre $1 avant d'essayer à nouveau.",
 'createacct-another-realname-tip' => 'Le vrai nom est optionnel.
 Si vous décidez de le fournir, il sera utilisé pour attribuer à l’utilisateur ses travaux.',
 'pt-login' => 'Se connecter',
+'pt-login-button' => 'Se connecter',
 'pt-createaccount' => 'Créer un compte',
 'pt-userlogout' => 'Se déconnecter',
 
@@ -1371,8 +1373,10 @@ Vous pouvez voir ce diff ; des détails sont disponibles dans le [{{fullurl:{{#S
 'revdelete-show-file-submit' => 'Oui',
 'revdelete-selected' => "'''{{PLURAL:$2|Version sélectionnée|Versions sélectionnées}} de '''[[:$1]]''' :'''",
 'logdelete-selected' => "'''{{PLURAL:$1|Événement d'historique sélectionné|Événements d'historique sélectionnés}} :'''",
-'revdelete-text' => "'''Les versions et événements supprimés seront encore présents dans l'historique de la page et dans les journaux, mais leur contenu textuel sera inaccessible au public.'''
-Les autres administrateurs de {{SITENAME}} pourront toujours accéder au contenu caché et le restaurer à travers cette même interface, à moins que des restrictions supplémentaires ne soient mises en place.",
+'revdelete-text-text' => "Les révisions supprimées continueront à apparaître dans l'historique de la page, mais une partie de leur contenu sera inaccessible au public.",
+'revdelete-text-file' => "Les versions de fichier supprimées continueront à apparaître dans l'historique des fichiers, mais une partie de leur contenu sera indisponible au public.",
+'logdelete-text' => 'Les évènements du journal supprimés continueront à apparaître dans les journaux, mais une partie de leur contenu sera indisponible au public.',
+'revdelete-text-others' => "Les autres administrateurs de {{SITENAME}} seront toujours capables d'accéder au contenu caché et peuvent le restaurer à nouveau par cette interface, à moins que des restrictions additionnelles soient définies.",
 'revdelete-confirm' => 'Confirmez que vous voulez effectuer cette action, que vous en comprenez les conséquences, et que vous le faites en accord avec [[{{MediaWiki:Policy-url}}|les règles]].',
 'revdelete-suppress-text' => "La suppression ne doit être utilisée '''que''' dans les cas suivants :
 * Informations potentiellement diffamatoires
@@ -1507,7 +1511,7 @@ Vous pouvez trouver des détails dans le [{{fullurl:{{#Special:Log}}/delete|page
 'search-file-match' => '(correspond au contenu du fichier)',
 'search-suggest' => 'Essayez avec cette orthographe : $1',
 'search-interwiki-caption' => 'Projets frères',
-'search-interwiki-default' => 'Résultats sur $1 :',
+'search-interwiki-default' => 'Résultats de $1 :',
 'search-interwiki-more' => '(plus)',
 'search-relatedarticle' => 'Reliés',
 'searcheverything-enable' => 'Rechercher dans tous les espaces de noms',
index fae921b..81edf41 100644 (file)
@@ -1260,8 +1260,6 @@ fonccion, la vèrsion spècifiâye ègziste pas ou ben vos èprovâd de cachiér
 'revdelete-show-file-submit' => 'Ouè',
 'revdelete-selected' => "'''{{PLURAL:$2|Vèrsion chouèsia|Vèrsions chouèsies}} de [[:$1]] :'''",
 'logdelete-selected' => "'''{{PLURAL:$1|Èvènement du jornal chouèsi|Èvènements du jornal chouèsis}} :'''",
-'revdelete-text' => "'''Les vèrsions et los èvènements suprimâ(ye)s aparètront adés dedens l’historico de la pâge et pués sur los jornals, mas quârques parties de lor contegnu seront inaccèssibles u publico.'''
-Los ôtros administrators de {{SITENAME}} porront tojorn arrevar u contegnu cachiê et lo refâre per cela mém’entèrface, du muens que des rèstriccions de ples seyont pas dèfenies.",
 'revdelete-confirm' => 'Se vos plét, confirmâd qu’o est franc cen que vos voléd fâre, que vos en compregnéd les consèquences et pués que vos o féte en acôrd avouéc les [[{{MediaWiki:Policy-url}}|règlles de dedens]].',
 'revdelete-suppress-text' => "La rèprèssion dêt étre empleyêe '''ren que''' dens cetos câs :
 * Enformacions que pôvont étre difamatouères
index f8e60e6..6e04bee 100644 (file)
@@ -966,9 +966,6 @@ Dü könst di ferskeel uunluke. Wan dü muar wed wel, luke iin uun't [{{fullurl:
 'revdelete-show-file-submit' => 'Ja',
 'revdelete-selected' => "'''{{PLURAL:$2|Ütjsoocht werjuun|Ütjsoocht werjuunen}} faan [[:$1]]:'''",
 'logdelete-selected' => "'''{{PLURAL:$1|Ütjsoocht logbukiindrach|Ütjsoocht logbukiindracher}}:'''",
-'revdelete-text' => "'''Stregen werjuunen an aktjuunen bliiw uun di ferluup an uun a logbuken, man det koon ei arken efterlees.'''
-
-Ööder administratooren üüb {{SITENAME}} kön oober üüb di ferbürgen ferluup tugrip an tu nuad en ual werjuun weder iinstel.",
 'revdelete-confirm' => 'Ferseekre noch ans, dat dü det würelk du wel, dat dü witjst, wat dü dääst, an dat det mä a [[{{MediaWiki:Policy-url}}|bestemangen]] auerian stemet.',
 'revdelete-suppress-text' => "Det skul '''bluas''' onertrakt wurd bi:
 * Persöönelk informatsjuunen, diar näämen wat uungung
index 7eb33c5..6263bb3 100644 (file)
@@ -873,8 +873,6 @@ der kinne details wêze yn it [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPA
 'revdelete-show-file-submit' => 'Ja',
 'revdelete-selected' => "'''Spesifisearre {{PLURAL:$2|ferzje|ferzjes}} fan [[:$1]]:'''",
 'logdelete-selected' => "'''{{PLURAL:$1|keazen lochboekregel|keazen lochboekregels}}:'''",
-'revdelete-text' => "'''Fuorthelle bewurkings binne sichtber yn 'e skiednis, mar de ynhâld is net langer publyk tagonklik.'''
-Oare behearders fan {{SITENAME}} kinne de ferburgen ynhâld benaderje en it fuortheljen ûngedien meitsje mei help fan dit skerm, of der moatte oanfoljende beheinings jilde dy't ynsteld binne troch de systeembehearder.",
 'revdelete-legend' => 'Sichtberensbeheinings ynstelle.',
 'revdelete-hide-text' => 'De bewurke tekst ferskûlje',
 'revdelete-hide-image' => 'Triem ynhâld ferskûlje',
index 62b8e38..ee6a2ff 100644 (file)
@@ -651,9 +651,6 @@ $2',
 'revdelete-nooldid-text' => '倷冇话个只操作𠮶目标修改。',
 'revdelete-selected' => "'''拣[[:$1]]𠮶$2回修订:'''",
 'logdelete-selected' => "'''拣'''$1'''𠮶$2只日志事件:'''",
-'revdelete-text' => "'''删吥𠮶改动哈会到页面历史里头显示, 但公众浏览伓正佢𠮶内容。'''
-
-个站别𠮶管理员哈系能眵吖弆到𠮶内容,同到通过同佢一样𠮶界面恢复删除,除非设正嘞附加𠮶限制。",
 'revdelete-legend' => '设置可见性𠮶限制',
 'revdelete-hide-text' => '弆到修改内容',
 'revdelete-hide-image' => '弆到档内容',
index cc3c174..1636f61 100644 (file)
@@ -672,9 +672,6 @@ $2',
 'revdelete-nooldid-text' => '倷冇话箇隻操作嗰目标修改。',
 'revdelete-selected' => "'''揀[[:$1]]嗰$2回修訂:'''",
 'logdelete-selected' => "'''揀'''$1'''嗰$2隻日誌事件:'''",
-'revdelete-text' => "'''刪吥嗰改動哈會到頁面歷史裡頭顯示, 但公眾瀏覽伓正佢嗰內容。'''
-
-箇站別嗰管理員哈係能眵吖弆到嗰內容,同到通過同佢一樣嗰界面恢復刪除,除非設正嘞附加嗰限制。",
 'revdelete-legend' => '設置可見性嗰限制',
 'revdelete-hide-text' => '弆到修改內容',
 'revdelete-hide-image' => '弆到檔內容',
index 70f2314..8166554 100644 (file)
@@ -994,8 +994,6 @@ Gheibh thu mion-fhiosrachadh air [{{fullurl:{{#Special:Log}}/suppress|page={{FUL
 'revdelete-show-file-submit' => 'Tha',
 'revdelete-selected' => "'''{{PLURAL:$2|Lèirmheas|Lèirmheasan}} de [[:$1]] a thagh thu:'''",
 'logdelete-selected' => "'''{{PLURAL:$1|An tachartas loga|Na tachartasan loga}} a thagh thu:'''",
-'revdelete-text' => "'''Nochdaidh lèirmheasan is tachartasan fhathast ann an eachdraidh 's logaichean na duilleige ach bidh cuid a shusbaint ann nach fhaic am poball.'''
-Gheibh rianairean eile air {{SITENAME}} greim fhathast air an t-susbaint fhalaichte agus gabhaidh an sguabadh às a neo-dhèanamh a-rithist san aon eadar-aghaidh mur an deach cuingeachaidhean eile a shuidheachadh.",
 'revdelete-confirm' => "Dearbh gu bheil thu airson seo a dhèanamh, gu bheil thu a' tuigsinn na thachras ri linn agus gu bheil thu a' dèanamh seo a-rèir [[{{MediaWiki:Policy-url}}|a' phoileasaidh]].",
 'revdelete-suppress-text' => "Cha bu chòir dhut mùchadh a chleachdadh '''ach''' ann an suidheachaidhean mar seo:
 * Fiosrachadh a dh'fhaodadh a bhith dìteachail
index 9c74e8b..81b3448 100644 (file)
@@ -1265,8 +1265,6 @@ función, a revisión especificada non existe ou está intentando agochar a revi
 'revdelete-show-file-submit' => 'Si',
 'revdelete-selected' => "'''{{PLURAL:\$2|Revisión seleccionada|Revisións seleccionadas}} de \"[[:\$1]]\":'''",
 'logdelete-selected' => "'''{{PLURAL:$1|Rexistro de evento seleccionado|Rexistro de eventos seleccionados}}:'''",
-'revdelete-text' => "'''As revisións borradas seguirán aparecendo no historial da páxina e nos rexistros, pero partes do seu contido serán inaccesibles de cara ao público.'''
-Os demais administradores de {{SITENAME}} poderán acceder ao contido agochado e poderán restaurar a páxina de novo a través desta mesma interface, a non ser que se estableza algunha restrición adicional.",
 'revdelete-confirm' => 'Por favor, confirme que quere levar a cabo esta acción, que comprende as consecuencias e que o fai de acordo [[{{MediaWiki:Policy-url}}|coas políticas]].',
 'revdelete-suppress-text' => "A eliminación '''unicamente''' debería utilizarse nos seguintes casos:
 * Información potencialmente difamatoria
index e5c248c..722e27c 100644 (file)
@@ -675,8 +675,6 @@ $2',
 'revdelete-show-file-submit' => 'Ναί',
 'revdelete-selected' => "'''{{PLURAL:$2|Ἐπειλεγμένη ἀναθεώρησις|Ἐπειλεγμέναι ἀναθεωρήσεις}} τοῦ [[:$1]]:'''",
 'logdelete-selected' => "'''{{PLURAL:$1|Ἐπειλεγμένον γεγονὸς καταλόγου|Ἐπειλεγμένα γεγονὀτα καταλόγου}}:'''",
-'revdelete-text' => "'''Αἱ διαγεγραμμέναι ἀναθεωρήσεις καὶ τὰ γεγονότα ἐμφανίσονται ἐν τῷ ἱστορικῷ τῆς δέλτου καὶ τοῖς καταλόγοις, ὰλλὰ μέρη τοῦ περιεχομένου σφῶν ἔσονται δημοσίως ἀπροσπέλαστα.'''
-Ἐξέσται δὲ ἑτέροις ἐπιτρόποις ἐν τῷ ἱστοτόπῳ {{SITENAME}} προσπελάζειν τῷ κρυμμένῳ περιεχομένῳ καὶ ἐπανιστάναι τόδε δία αὐτῆς τῆς διεπαφῆς ἐὰν μὴ θῶνται πρόσθετοι περιορισμοί τινές.",
 'revdelete-legend' => 'Θέτειν περιορισμοῦς ὁρατότητος',
 'revdelete-hide-text' => 'Κρύπτειν κείμενον ἀναθεωρήσεως',
 'revdelete-hide-image' => 'Κρύπτειν περιεχόμενον ἀρχείου',
index 5dc065b..ef31e0f 100644 (file)
@@ -1068,8 +1068,6 @@ Du chasch dää Unterschid allno aaluege; Details het's im [{{fullurl:{{#Special
 'revdelete-show-file-submit' => 'Jo',
 'revdelete-selected' => "'''{{PLURAL:$2|Usgwehlti Version|Usgwehlti Versione}} vu [[:$1]]:'''",
 'logdelete-selected' => "'''{{PLURAL:$1|Usgwehlte Logbuechyytrag|Usgwehlti Logbuechyytreg}}:'''",
-'revdelete-text' => "'''Dr Inhalt oder anderi Bstandteil vu gleschte Versione chenne nimi aagluegt wäre, si erschyyne aber alno as Yytreg in dr Versiongschicht.'''
-{{SITENAME}}-Ammanne chenne dr Inhalt, wu glescht isch, oder di andre gleschte Bstandteil alno aaluege un au widerherstelle, user s isch feschtgleit, ass d Zuegangsbschränkige au fir Ammanne gälte.",
 'revdelete-confirm' => 'Bitte tue bstetige, ass Du vor hesch, des z mache, d Konsequänze drus verstohsch un s machsch in Inbereinstimmig mit dr [[{{MediaWiki:Policy-url}}|Richtlinie]].',
 'revdelete-suppress-text' => "Unterdruckige sotte '''nume''' in däne Fäll bruucht wäre:
 * Nit aabrochti Informatione
index 25415ce..b35daa7 100644 (file)
@@ -1096,8 +1096,6 @@ $3 દ્વારા અપાયેલ કારણ છે ''$2''",
 'revdelete-show-file-submit' => 'હા',
 'revdelete-selected' => "''' [[:$1]] ના {{PLURAL:$2|પસંદ કરેલ ફેરફાર |પસંદ કરેલ ફેરફારો}}: '''",
 'logdelete-selected' => "'''{{PLURAL:$1|પસંદગી કરેલ લોગ ઘટના | પસંદગી કરેલ લોગ ઘટનાઓ }}:'''",
-'revdelete-text' => "''' રદ્દ કરાયેલ ફેરફારો અને ઘટનાઓ પાનાના ઈતિહાસ અને લોગમાં દેખાશે , પણ તેની અંદરની માહિતી જન સમુદાયથી અદ્રશ્ય રહેશે. '''
-{{SITENAME}} પરના અન્ય પ્રબંધકો આ અદ્રશ્ય માહિતે જોઇ શકશે અને તેને પુનઃ જીવિત કરી શકશે સિવાય કે તેના પર વધારાની પાબંદી ન મુકાઇ હોય.",
 'revdelete-confirm' => 'કૃપયા પુષ્ટિ કરો કે તમે શું કરી રહ્યા છો તેની અને તેના પરિણામોની તમને જાણ છે અને તમે આ બધું  [[{{MediaWiki:Policy-url}}|the policy]] અ6તર્ગત કરી રહ્યાં છો.',
 'revdelete-suppress-text' => "બળ પૂર્વક છુપાવવું \"માત્ર\" આજ સંજોગોમાં કરી શકાશે:
 * સંભવતઃ ભયાજનક માહિતી 
@@ -1227,7 +1225,7 @@ $1",
 'search-section' => '(વિભાગ $1)',
 'search-suggest' => 'શું તમે $1 કહેવા માંગો છો?',
 'search-interwiki-caption' => 'બંધુ પ્રકલ્પ',
-'search-interwiki-default' => '$1 પરીણામો:',
+'search-interwiki-default' => '$1 àª®àª¾àª\82થà«\80 àªªàª°à«\80ણામà«\8b:',
 'search-interwiki-more' => '(વધુ)',
 'search-relatedarticle' => 'શોધ સંબંધિત',
 'searcheverything-enable' => 'નામસ્થળોમાં શોધો:',
index 4ddfee1..c5f6d8d 100644 (file)
@@ -800,7 +800,6 @@ Liá-chhṳ chhà-fûng he yù $1 só fûng ke. Tông-chûng ke ngièn-yîn he '
 'revdelete-show-file-submit' => '係',
 'revdelete-selected' => "'''選取[[:$1]]嘅$2次修訂:'''",
 'logdelete-selected' => "'''Chhí-chhṳ '''$1''' ke $2-ke ngit-ki hong-muk:'''",
-'revdelete-text' => "'''Chhù-thet ke siû-thin yìn-yèn chiông-voi hién-sṳ chhai vùn-chông li̍t-sṳ́ chûng, than vùn-sṳ nui-yùng yí-kîn put-nèn pûn chung-ngìn fóng-mun.''' Chhai chhṳ́ miong-chham ke khì-thâ kón-lî-yèn chiông chhòi-nèn fóng-mun yún-chhòng ke nui-yùng pin theu-ko siông-thùng ke kie-mien fî-fu̍k chhù-hi, chhù-fî miong-chham kûng-chok-chá chin-hàng han-chṳ.",
 'revdelete-legend' => 'Sat-thin siû-thin han-chṳ:',
 'revdelete-hide-text' => '隱藏修訂版本文字',
 'revdelete-hide-image' => '隱藏文件內容',
index ae8c6bf..07fea44 100644 (file)
@@ -917,6 +917,7 @@ $2',
 'createacct-another-realname-tip' => 'השם האמיתי הוא אופציונאלי.
 אם תבחרו לספקו, הוא ישמש לייחוס עבודת המשתמש אליו.',
 'pt-login' => 'כניסה לחשבון',
+'pt-login-button' => 'כניסה לחשבון',
 'pt-createaccount' => 'יצירת חשבון',
 'pt-userlogout' => 'יציאה מהחשבון',
 
@@ -1341,8 +1342,10 @@ $2
 'revdelete-show-file-submit' => 'כן',
 'revdelete-selected' => "'''ה{{PLURAL:$2|גרסה שנבחרה|גרסאות שנבחרו}} מתוך הדף [[:$1]]:'''",
 'logdelete-selected' => "'''{{PLURAL:$1|פעולת היומנים שנבחרה|פעולות היומנים שנבחרו}}:'''",
-'revdelete-text' => "'''גרסאות ופעולות יומנים שנמחקו עדיין תופענה בהיסטוריית הדף ובדפי היומנים, אך חלקים מהתוכן שלהן לא יהיה זמין לציבור.'''
-מפעילי מערכת אחרים באתר עדיין יוכלו לגשת לתוכן הנסתר ויוכלו לשחזר אותו שוב דרך הממשק הזה, אלא אם כן תוגדרנה הגבלות נוספות.",
+'revdelete-text-text' => 'גרסאות שנמחקו עדיין תופענה בהיסטוריית הדף, אך חלקים מהתוכן שלהן לא יהיו זמינים לציבור.',
+'revdelete-text-file' => 'גרסאות קבצים שנמחקו עדיין תופענה בהיסטוריית הקובץ, אך חלקים מהתוכן שלהן לא יהיו זמינים לציבור.',
+'logdelete-text' => 'פעולות יומנים שנמחקו עדיין תופענה בדפי היומנים, אך חלקים מהתוכן שלהן לא יהיו זמינים לציבור.',
+'revdelete-text-others' => 'מפעילי מערכת אחרים באתר עדיין יוכלו לגשת לתוכן הנסתר ויוכלו לשחזר אותו שוב דרך הממשק הזה, אלא אם כן תוגדרנה הגבלות נוספות.',
 'revdelete-confirm' => 'אנא אשרו שזה אכן מה שאתם מתכוונים לעשות, שאתם מבינים את התוצאות של מעשה כזה, ושהמעשה מבוצע בהתאם ל[[{{MediaWiki:Policy-url}}|נוהלי האתר]].',
 'revdelete-suppress-text' => "יש להשתמש בהסתרה מלאה '''אך ורק''' במקרים הבאים:
 * מידע שעלול להיות לשון הרע
@@ -1480,7 +1483,7 @@ $1",
 'search-file-match' => '(התאמה בתוכן הקובץ)',
 'search-suggest' => 'האם התכוונת ל: $1',
 'search-interwiki-caption' => 'מיזמי אחות',
-'search-interwiki-default' => 'ת×\95צ×\90×\95ת ×\91{{GRAMMAR:תחילית|$1}}:',
+'search-interwiki-default' => 'ת×\95צ×\90×\95ת ×\9e{{GRAMMAR:תחילית|$1}}:',
 'search-interwiki-more' => '(עוד)',
 'search-relatedarticle' => 'קשור',
 'searcheverything-enable' => 'חיפוש בכל מרחבי השם',
index 258b6aa..e01c6c0 100644 (file)
@@ -1168,8 +1168,6 @@ $2
 'revdelete-show-file-submit' => 'हाँ',
 'revdelete-selected' => "'''[[:$1]] {{PLURAL:$2|का चुना हुआ|के चुने हुए}} अवतरण:'''",
 'logdelete-selected' => "'''{{PLURAL:$1|चुना हुआ|चुने हुए}} लॉग इवेंट:'''",
-'revdelete-text' => "'''हटाए गए अवतरण और इवेंट पृष्ठ इतिहास और लॉग में दिखेंगे, लेकिन उनकी कुछ सामग्री सार्वजनिक नहीं होगी।'''
-{{SITENAME}} के अन्य प्रबंधक छिपी हुई सामग्री को देख पाएँगे, और इसी अंतरापृष्ठ के जरिए वे इसकी पुनर्स्थापना भी कर सकते हैं, बशर्ते कि अतिरिक्त प्रतिबंध न लगाए गए हों।",
 'revdelete-confirm' => 'पुष्टि करें कि आप यह कार्य करना चाहते हैं, आप इसका परिणाम समझते हैं, और आप ये [[{{MediaWiki:Policy-url}}|नीति]] के अनुसार कर रहे हैं।',
 'revdelete-suppress-text' => 'छिपाने का प्रयोग <strong>केवल</strong> इन परिस्थितियों में होना चाहिए:
 * संभावित अपमानजनक जानकारी
@@ -1305,7 +1303,7 @@ $1",
 'search-file-match' => '(फ़ाइल सामग्री से मेल खाता है)',
 'search-suggest' => 'कहीं आपका मतलब $1 तो नहीं था?',
 'search-interwiki-caption' => 'अन्य प्रकल्प',
-'search-interwiki-default' => '$1 à¤\95े परिणाम:',
+'search-interwiki-default' => '$1 à¤¸े परिणाम:',
 'search-interwiki-more' => '(और)',
 'search-relatedarticle' => 'सम्बंधित',
 'searcheverything-enable' => 'सभी नामस्थानों में खोजें',
index 3205753..15ad909 100644 (file)
@@ -982,8 +982,6 @@ Aap ii diff ke dekhe saktaa hae: iske baare me aur jaan kaari [{{fullurl:{{#Spec
 'revdelete-show-file-submit' => 'Haan',
 'revdelete-selected' => "'''{{PLURAL:$2|Selected badlao|Selected badlao}} of [[:$1]]:'''",
 'logdelete-selected' => "'''{{PLURAL:$1|Chuna gais log event|Chuna gais log events}}:'''",
-'revdelete-text' => "'''Mitawa gae badlao aur ghatna panna ke itihaas me dekhai, lekin content ke kuch part janta nai access kare saki.'''
-Duusra admins {{SITENAME}} me, lukawa gais content ke khole sake aur iske mitae bhi sake hai interface use kar ke, jab tak ki aur rukawat nai lagawa jaae.",
 'revdelete-confirm' => 'Meharbani kar ke aap ii confirm karo ki aap ii kare mangta hae, aap iske asar ke samajhta hae, aur iske aap [[{{MediaWiki:Policy-url}}|the policy]] ke anusar karta hae.',
 'revdelete-suppress-text' => "Suppression ke '''khaali''' ii chij ke khatir kaam me lawa jaae sake hai:
 * Aapan baare me jaankari thik nai hai
index 52b9dd9..05318ec 100644 (file)
@@ -907,8 +907,6 @@ ang ini nga buluhaton wala, ukon gahimakas ka nga taguon ang karon nga pagbag-o.
 'revdelete-show-file-submit' => 'Huo',
 'revdelete-selected' => "'''{{PLURAL:$2|Ginpili nga pagbag-o|Ginpili nga mga pagbag-o}} ni [[:$1]]:'''",
 'logdelete-selected' => "'''{{PLURAL:$1|Ginpili nga hinatabo sa log|Ginpili nga mga hinatabo sa log}}:'''",
-'revdelete-text' => "'''Ang mga ginpanas nga pagbag-o kag hinatabo magapakita sa gihapon sa kasaysayan sang panid kag mga log, apang ang mga parte sang ila kaundan indi na mahimo nga masudlan sang publiko.'''
-Ang iban nga administrador sa {{SITENAME}} mahimo sa gihapon nga makasulod sa nakatago nga kaundan kag mapaiway nga mapanas ini liwat sa amo sa gihapon nga interface, luwas na lang kon may dugang pa nga pagpangbawal ang ibutang.",
 'revdelete-confirm' => 'Palihog konpermar nga luyag mo ini himuon, nga imo naintiendihan ang mga konsekwensya, kag ginahimo mo ini suno sa [[{{MediaWiki:Policy-url}}|polisiya]].',
 'revdelete-suppress-text' => "Ang pagpahugot nagakadapat '''lamang''' nga pagagamiton sa masunod nga kaso:
 * Nagapang-guba sang dignindad nga impormasyon
index 2b50fc5..64c90dc 100644 (file)
@@ -1232,8 +1232,6 @@ Možete ju pregledati; više podataka možete vidjeti u [{{fullurl:{{#Special:Lo
 'revdelete-show-file-submit' => 'Da',
 'revdelete-selected' => "'''{{PLURAL:$2|Odabrana izmjena|Odabrane izmjene|Odabrane izmjene}} stranice [[$1]]:'''",
 'logdelete-selected' => "'''{{PLURAL:$1|Odabrani zapis u evidenciji|Odabrani zapisi u evidenciji}}:'''",
-'revdelete-text' => "'''Obrisane će se izmjene i dalje nalaziti u javnom popisu izmjena, ali njihov sadržaj neće biti dostupan javnosti.'''
-Drugi administratori ovoga projekta ({{SITENAME}}) moći će i dalje pristupiti skrivenom sadržaju i vratiti ga u javni pristup putem ovog sučelja, osim ako operateri na projektu nisu postavili dodatna ograničenja.",
 'revdelete-confirm' => 'Molimo potvrdite da namjeravate ovo učiniti, da razumijete posljedice i da to činite u skladu s [[{{MediaWiki:Policy-url}}|pravilima]].',
 'revdelete-suppress-text' => "Sklanjanje uređivanja treba raditi '''iznimno''' u slijedećih par slučajeva:
 * Privatne informacije neprilične javnom mediju tipa
index 5c103e7..03931e2 100644 (file)
@@ -683,6 +683,7 @@ Móžeš tutu zdźělenku ignorować, jeli so wužiwarske konto zmylnje wutwori
 'createacct-another-realname-tip' => '* Woprawdźite mjeno je opcionalne.
 Jeli jo podaš, budźe so to wužiwać, zo by přinoški přirjadowało.',
 'pt-login' => 'Přizjewić',
+'pt-login-button' => 'Přizjewić',
 'pt-createaccount' => 'Konto załožić',
 'pt-userlogout' => 'Wotzjewić',
 
@@ -1083,8 +1084,10 @@ Móžeš sej tutón rozdźěl wobhladać; podrobnosće namakaš w [{{fullurl:{{#
 'revdelete-show-file-submit' => 'Haj',
 'revdelete-selected' => "'''{{PLURAL:$2|Wubrana wersija|Wubranej wersiji|Wubrane wersije|Wubranych wersijow}} wot [[:$1]]:'''",
 'logdelete-selected' => "'''{{PLURAL:$1|Wubrany zapisk z protokola|Wubranej zapiskaj z protokola|Wubrane zapiski z protokola|Wubrane zapiski z protokola}} za '''$1:''''''",
-'revdelete-text' => "'''Wušmórnjene wersije a podawki so w stawiznach a protokolach dale jewja, ale dźěle jich wobsaha budu njepřistupne za zjawnosć.'''
-Druzy administratorojo na {{GRAMMAR:lokatiw|{{SITENAME}}}} móža hišće na schowany tekst přistup měć a jón z pomocu samsneho interfejsa wobnowić, chibazo tež přidatne prawa su wobmjezowane.",
+'revdelete-text-text' => 'Zhašane wersije wostanu hišće we wersijowej historiji, ale dźěle jeje wobsaha njebudu přistupne zjawnosći.',
+'revdelete-text-file' => 'Zhašane datajowe wersije wostanu w datajowej historiji, ale dźěle jeje wobsaha njebudu přistupne zjawnosći.',
+'logdelete-text' => 'Zhašane protokolowe zapiski wostanu hišće w protokolach, ale dźěle jich wobsaha njebudu přistupne zjawnosći.',
+'revdelete-text-others' => 'Druzy administratorojo na {{GRAMMAR:lokatiw|{{SITENAME}}}} móža hišće na schowany wobsah přistup měć a móža jón zaso přez samsny wužiwarski powjerch wobnowić, chibazo su přidatne wobmjezowanja.',
 'revdelete-confirm' => 'Prošu potwjerdź, zo chceš to činić, zo rozumiš konsekwency a zo činiš to po [[{{MediaWiki:Policy-url}}|prawidłach]].',
 'revdelete-suppress-text' => "Potłóčenje dyrbjało so '''jenož''' za slědowace pady wužiwać:
 * Potencielnje křiwdźace informacije
@@ -1219,7 +1222,7 @@ Podrobnosće móžeš w [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}
 'search-file-match' => '(wotpowěduje datajowemu wobsahej)',
 'search-suggest' => 'Měnješe ty $1?',
 'search-interwiki-caption' => 'Sotrowske projekty',
-'search-interwiki-default' => '$1 wuslědki:',
+'search-interwiki-default' => 'Wuslědki z $1:',
 'search-interwiki-more' => '(dalše)',
 'search-relatedarticle' => 'Přiwuzne',
 'searcheverything-enable' => 'We wšěch mjenowych rumach pytać',
index 92c9040..7d681d3 100644 (file)
@@ -1252,9 +1252,6 @@ vagy a legutolsó változatot próbáltad meg elrejteni.',
 'revdelete-show-file-submit' => 'Igen',
 'revdelete-selected' => "'''A(z) [[:$1]] lap {{PLURAL:$2|kiválasztott változata|kiválasztott változatai}}:'''",
 'logdelete-selected' => "'''{{PLURAL:$1|Kiválasztott naplóesemény|Kiválasztott naplóesemények}}:'''",
-'revdelete-text' => "'''A törölt változatok és események továbbra is megjelennek a laptörténetben és a naplókban,
-azonban a tartalmuk nem lesz mindenki számára hozzáférhető.'''
-A(z) {{SITENAME}} adminisztrátorai továbbra is meg tudják tekinteni az elrejtett tartalmat, és helyre tudják állítani ugyanezen a felületen keresztül, amennyiben nincs további korlátozás beállítva.",
 'revdelete-confirm' => 'Kérlek erősítsd meg, hogy valóban ezt szeretnéd tenni; megértetted a következményeket, és amit teszel, az összhangban van [[{{MediaWiki:Policy-url}}|az irányelvekkel]].',
 'revdelete-suppress-text' => "Az elrejtés '''csak''' a következő esetekben használható:
 * Illetlen személyes információk
index de8beed..79e2567 100644 (file)
@@ -1115,9 +1115,6 @@ $3 մասնակիցը տվել է հետևյալ պատճառը. ''$2''",
 'revdelete-show-file-submit' => 'Այո',
 'revdelete-selected' => "'''[[:$1]] էջի ընտրված {{PLURAL:$2|տարբերակը|տարբերակները}}.'''",
 'logdelete-selected' => "'''Տեղեկամատյանի ընտրված {{PLURAL:$1|գրառումը|գրառումները}}.'''",
-'revdelete-text' => "'''Ջնջված տարբերակները երևալու են էջերի պատմության մեջ և տեղեկամատյաններում, բայց դրանց պարունակության մի մասը հասարակ այցելուներին չի ցուցադրվելու։'''
-
-Ադմինիստրատորները հնարավորություն կունենան դիտել թաքցված պարունակությունը, ինչպես նաև վերականգնել այն այս նույն ինտերֆեյսի միջոցով, բացառությամբ ավելորդ սահմանափակումների դեպքում։",
 'revdelete-legend' => 'Սահմանել տեսանելիության սահմանափակումներ',
 'revdelete-hide-text' => 'Թաքցնել տարբերակի տեքստը',
 'revdelete-hide-image' => 'Թաքցնել նիշքի պարունակությունը',
index 451b541..5a1d0d3 100644 (file)
@@ -1136,8 +1136,6 @@ function, o le version specificate non existe, o tu essaya celar le version actu
 'revdelete-show-file-submit' => 'Si',
 'revdelete-selected' => "'''{{PLURAL:$2|Version seligite|Versiones seligite}} de [[:$1]]:'''",
 'logdelete-selected' => "'''{{PLURAL:$1|Evento|Eventos}} de registro seligite:'''",
-'revdelete-text' => "'''Le versiones e eventos delite continuara a apparer in le historia e registro del pagina, sed partes de lor contento essera inaccessibile al publico.'''
-Altere administratores in {{SITENAME}} continuara a poter acceder al contento celate e pote restaurar lo per medio de iste mesme interfacie, si non se ha definite restrictiones additional.",
 'revdelete-confirm' => 'Per favor confirma que tu ha le intention de facer isto, que tu comprende le consequentias, e que tu face isto in accordo con [[{{MediaWiki:Policy-url}}|le politica]].',
 'revdelete-suppress-text' => "Le suppression debe '''solmente''' esser usate pro le sequente casos:
 * Information potentialmente diffamatori
index afe8e0f..81214fb 100644 (file)
@@ -1292,8 +1292,6 @@ Sebagai seorang pengurus, Anda dapat melihat perbedaan ini; detail mungkin terse
 'revdelete-show-file-submit' => 'Ya',
 'revdelete-selected' => "'''{{PLURAL:$2|Revisi|Revisi-revisi}} pilihan dari '''$1''''''",
 'logdelete-selected' => "'''{{PLURAL:$1|Log|Log-log}} pilihan untuk:'''",
-'revdelete-text' => "'''Revisi dan tindakan yang telah dihapus akan tetap muncul di versi terdahulu dan log halaman, tapi bagian dari isinya tidak bisa diakses publik.'''
-Pengurus {{SITENAME}} lain akan tetap dapat mengakses isi yang tersembunyi ini dan dapat membatalkan penghapusannya menggunakan antarmuka yang sama, kecuali ada pembatasan lain yang dibuat oleh operator situs.",
 'revdelete-confirm' => 'Tolong konfirmasi bahwa Anda memang bermaksud melakukan ini, memahami konsekuensinya, dan bahwa Anda melakukannya sesuai dengan [[{{MediaWiki:Policy-url}}|kebijakan]].',
 'revdelete-suppress-text' => "Penyembunyian revisi '''hanya''' boleh digunakan untuk kasus-kasus berikut:
 * Informasi yang berpotensi memfitnah
index eb283d0..d120a65 100644 (file)
@@ -590,6 +590,7 @@ Pangngaasi nga agurayka ti $1 sakbay a padasem manen.',
 'createacct-another-realname-tip' => 'Saan a nasken ti pudno a nagan.
 No kayatmo nga ited, mausarto daytoy para iti panangited ti pammadayaw para kadagiti obrada.',
 'pt-login' => 'Sumrek',
+'pt-login-button' => 'Sumrek',
 'pt-createaccount' => 'Agaramid ti pakabilangan',
 'pt-userlogout' => 'Rummuar',
 
@@ -1025,8 +1026,10 @@ awan ti naibaga a panagbaliw, wenno padpadasem nga ilemlemmeng ti agdama a panag
 'revdelete-show-file-submit' => 'Wen',
 'revdelete-selected' => "'''{{PLURAL:$2|Napili a nabaliwan|Dagiti napili a nabaliwan}} iti [[:$1]]:'''",
 'logdelete-selected' => "'''{{PLURAL:$1|Ti napili a listaan ti napasamak|Dagiti napili a listaan ti napasamak}}:'''",
-'revdelete-text' => "'''Dagiti naikkat a binaliwan ken dagiti napasamak ket agparang idiay panid ti pakasaritaan ken dagiti listaan, ngem addaan dagiti paset ti nagyanda a saan a maserrekan ti publiko.'''
-Dagiti sabsabali nga administrador idiay {{SITENAME}} ket mabalinda a serrekan ti nailemmeng a nagyan ken isubli ti panakaikkatda manen idiay dati nga interface, ngem saan no adda dagiti nainayon a naikabil a panagparit.",
+'revdelete-text-text' => 'Dagiti naikkat a rebision ket agparangto pay laeng iti panid ti pakasaritaan, ngem dagiti paset ti linaonda ket saanton a publiko a maserrekan.',
+'revdelete-text-file' => 'Dagiti naikkat a bersion ti papeles ket agparangto pay laeng iti pakasaritaan ti papeles, ngem dagiti paset ti linaonda ket saanton a publiko a maserrekan.',
+'logdelete-text' => 'Dagiti naikkat a listaan ti pasamak ket agparangto pay laeng kadagiti listaan, ngem dagiti paset ti linaonda ket saanton a publiko a maserrekan.',
+'revdelete-text-others' => 'Dagiti sabali nga administrador iti {{SITENAME}} ket mabalindanto pay laeng a maserrekan ti nailemmeng a linaon ken mabalindanto manen ti mangisubli ti pannakaikkat babaen iti daytoy nga isu met laeng nga interface, malaksid no adda dagiti maipatinayon a maisaad a panangigawid.',
 'revdelete-confirm' => 'Pangngaasi a pasingkedam a kayatmo nga aramiden daytoy, a maawatam dagiti pagbanagan, ket araramidem daytoy a segun iti [[{{MediaWiki:Policy-url}}|ti annuroten]].',
 'revdelete-suppress-text' => "Ti panagdepdep ket usaren '''laeng''' kadagiti sumaganad a kaso;
 * Makapataud ti libelo a pakaammo
@@ -1162,7 +1165,7 @@ Dagiti salaysay ket mabalin a mabirukan idiay [{{fullurl:{{#Special:Log}}/delete
 'search-file-match' => '(maipada ti linaon a papeles)',
 'search-suggest' => 'Daytoy kadi: $1',
 'search-interwiki-caption' => 'Dagiti kakabsat a gandat',
-'search-interwiki-default' => '$1 dagiti nagbanagan:',
+'search-interwiki-default' => 'Dagiti resulta manipud ti $1:',
 'search-interwiki-more' => '(adu pay)',
 'search-relatedarticle' => 'Mainaig',
 'searcheverything-enable' => 'Agbirukka kadagiti amin a nagan ti espasio',
index d74ed9d..30894f5 100644 (file)
@@ -1165,8 +1165,6 @@ Frekari upplýsingar eru í [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGE
 'revdelete-show-file-submit' => 'Já',
 'revdelete-selected' => "'''{{PLURAL:$2|Valin breyting|Valdar breytingar}} fyrir [[:$1]]:'''",
 'logdelete-selected' => "'''{{PLURAL:$1|Valin aðgerð|Valdar aðgerðir}}:'''",
-'revdelete-text' => "'''Eyddar útgáfur og breytingar munu birtast áfram í breytingarskrá síðunnar og í aðgerðarskrám, en hluti upplýsingana verða falin almenningi.'''
-Önnur möppudýr á {{SITENAME}} hafa aðgang að földu upplýsingunum og geta endurvakið upplýsingarnar í gegnum sama viðmót, nema sérstakar takmarkanir séu virkar.",
 'revdelete-confirm' => 'Vinsamlegast staðfestu að þú viljir gera þetta, að þú skiljir afleiðingarnar og að þú sért að gera þetta í samræmi við  [[{{MediaWiki:Policy-url}}]].',
 'revdelete-suppress-text' => "Bælingu á '''eingöngu''' að nota í eftirfarandi tilfellum:
 * Mögulegar ærumleiðandi upplýsingar
index f15b90f..ee5f8fc 100644 (file)
@@ -830,6 +830,7 @@ Attendi $1 e riprova in seguito.',
 'suspicious-userlogout' => 'La tua richiesta di disconnessione è stata negata perché sembra inviata da un browser non funzionante o un proxy di caching.',
 'createacct-another-realname-tip' => "L'indicazione del proprio nome vero è opzionale; se si sceglie di inserirlo, verrà utilizzato per attribuire la paternità dei contenuti inviati.",
 'pt-login' => 'Entra',
+'pt-login-button' => 'Entra',
 'pt-createaccount' => 'Registrati',
 'pt-userlogout' => 'Esci',
 
@@ -1238,8 +1239,10 @@ In quanto amministratore puoi visualizzare questo confronto di versioni; potrebb
 'revdelete-show-file-submit' => 'Sì',
 'revdelete-selected' => "'''{{PLURAL:$2|Versione selezionata|Versioni selezionate}} di [[:$1]]:'''",
 'logdelete-selected' => "'''{{PLURAL:$1|Evento del registro selezionato|Eventi del registro selezionati}}:'''",
-'revdelete-text' => "'''Le versioni cancellate restano visibili nella cronologia della pagina, mentre il testo contenuto non è accessibile al pubblico.'''
-Gli altri amministratori di {{SITENAME}} potranno accedere comunque ai contenuti nascosti e ripristinarli attraverso questa stessa interfaccia, se non sono state impostate altre limitazioni in fase di installazione del sito.",
+'revdelete-text-text' => 'Le versioni cancellate appariranno ancora nella cronologia della pagina, ma parti del loro contenuto sarà inaccessibile al pubblico.',
+'revdelete-text-file' => 'Le versioni di file cancellati appariranno ancora nella cronologia del file, ma parti del loro contenuto sarà inaccessibile al pubblico.',
+'logdelete-text' => 'Gli eventi cancellati appariranno ancora nei registri, ma parti del loro contenuto sarà inaccessibile al pubblico.',
+'revdelete-text-others' => 'Altri amministratori di {{SITENAME}} saranno ancora in grado di accedere ai contenuti nascosti e potranno ripristinarli nuovamente attraverso questa stessa interfaccia, se non sono state impostate restrizioni aggiuntive.',
 'revdelete-confirm' => 'Per favore conferma che questo è quanto intendi fare, che sei consapevole delle conseguenze, e che stai facendo questo nel rispetto delle [[{{MediaWiki:Policy-url}}|linee guida]].',
 'revdelete-suppress-text' => "La rimozione dovrebbe essere utilizzata '''unicamente''' nei seguenti casi:
 * informazioni potenzialmente diffamatorie
index e4d0064..d974db2 100644 (file)
@@ -14,6 +14,7 @@
  * @author Aotake
  * @author Aphaia
  * @author Broad-Sky
+ * @author Burthsceh
  * @author Chatama
  * @author Chinneeb
  * @author Emk
@@ -926,6 +927,7 @@ $1待ってから再度試してください。',
 'createacct-another-realname-tip' => '本名は省略できます。
 入力すると、その利用者の著作物の帰属表示に使われます。',
 'pt-login' => 'ログイン',
+'pt-login-button' => 'ログイン',
 'pt-createaccount' => 'アカウント作成',
 'pt-userlogout' => 'ログアウト',
 
@@ -1364,8 +1366,6 @@ $3 が示した理由: ''$2''",
 'revdelete-show-file-submit' => 'はい',
 'revdelete-selected' => '<strong>[[:$1]] の{{PLURAL:$2|選択された版}}:</strong>',
 'logdelete-selected' => '<strong>{{PLURAL:$1|選択された記録項目}}:</strong>',
-'revdelete-text' => '<strong>削除された版や記録項目は引き続きページの履歴や記録に表示されますが、一般利用者はその内容の一部を取得できなくなります。</strong>
-追加の制限がかけられない限り、{{SITENAME}}の他の管理者は同じインターフェイスを使って非表示の内容の取得や復元ができます。',
 'revdelete-confirm' => 'この操作を行おうとしていること、その結果を理解していること、[[{{MediaWiki:Policy-url}}|方針]]に従っていること、を確認してください。',
 'revdelete-suppress-text' => '秘匿は、<strong>以下の場合に限って</strong>使用すべきです:
 * 名誉毀損のおそれがある記述
@@ -1502,7 +1502,7 @@ $1',
 'search-file-match' => '(ファイルの内容との一致)',
 'search-suggest' => 'もしかして: $1',
 'search-interwiki-caption' => '姉妹プロジェクト',
-'search-interwiki-default' => '$1の結果:',
+'search-interwiki-default' => '$1ã\81\8bã\82\89ã\81®çµ\90æ\9e\9c:',
 'search-interwiki-more' => '(続き)',
 'search-relatedarticle' => '関連',
 'searcheverything-enable' => 'すべての名前空間を検索',
@@ -1837,7 +1837,7 @@ $1 {{PLURAL:$1|文字}}以下である必要があります。',
 'recentchanges-legend-newpage' => '([[Special:NewPages|新しいページ一覧]]も参照)',
 'recentchanges-legend-plusminus' => '(<em>±123</em>)',
 'rcnotefrom' => '以下は<strong>$2</strong>以降の更新です (最大 <strong>$1</strong> 件)。',
-'rclistfrom' => '$2 $3以降の更新を表示する',
+'rclistfrom' => '$1以降の更新を表示する',
 'rcshowhideminor' => '細部の編集を$1',
 'rcshowhideminor-show' => '表示',
 'rcshowhideminor-hide' => '非表示',
index 41b75c8..2a97f04 100644 (file)
@@ -967,8 +967,6 @@ Sampéyan isih bisa ndelok prabédan iki; rincian bisa ditemokaké nèng [{{full
 'revdelete-show-file-submit' => 'Ya',
 'revdelete-selected' => "'''{{PLURAL:$2|Revisi kapilih|Revisi kapilih}} dari '''$1''''''",
 'logdelete-selected' => "'''{{PLURAL:$1|Log kapilih|Log kapilih}} kanggo:'''",
-'revdelete-text' => "'''Revisi lan tindhakan sing wis kabusak bakal tetep muncul ing kaca versi sadurungé lan log, nanging bagéyan isiné ora bisa diaksès déning publik.'''
-Pangurus {{SITENAME}} liyané bakal tetep bisa ngaksès isi sing kadhelikaké iku lan bisa mbatalaké pambusakan ngliwati antarmuka sing padha, kajaba ana pawatesan liya saka operator situs.",
 'revdelete-confirm' => 'Mangga pesthèkaké yèn Sampéyan pancèn kudu nglakoni iki, yèn Sampéyan ngerti akibaté, lan yèn Sampéyan ngakoni iki cocok karo [[{{MediaWiki:Policy-url}}|kawicakan]].',
 'revdelete-suppress-text' => "Pandhelikan révisi '''mung''' bisa dipigunakaké kanggo kasus ing ngisor:
 * Informasi sing kagolong pitnah
index f0a7f2e..c39d3be 100644 (file)
@@ -1114,8 +1114,6 @@ $3 -ემ ამგვარი ახსნა : ''$2''",
 'revdelete-show-file-submit' => 'ჰო',
 'revdelete-selected' => "'''[[:$1]]-ის {{PLURAL:$2|მონიშნული ცვლილება|მონიშნული ცვლილებები}}:'''",
 'logdelete-selected' => "'''ჟურნალის {{PLURAL:$1|არჩეული ჩანაწერი|არჩეული ჩანაწერები}}:'''",
-'revdelete-text' => "'''გვერდებისა და მოქმედებების წაშლილი ნაწილები დარჩება ისტორიაში და ჟურნალებში, მაგრამ მათ ნაწილს ვერ ნახავენ ჩვეულებრივი მომხმარებლები.'''
-პროექტის ადმინისტრატორებს ექნებათ შესაძლებლობა {{SITENAME}}ში დაინახონ ღია და არწაშლილი ნაწილი, და შეძლებენ აღადგინონ იგივე ინტერფეისის მეშვეობით, გარდა იმ შემთხვევებისა, როდესაც დამატებითი შეზღუდვა მოქმედებს.",
 'revdelete-confirm' => 'გთხოვთ დაადასტუროთ, რომ გსურთ ქმედების განხორციელება. ასევე ვიმედოვნებთ, რომ ყველაფერს აკეთებთ  [[{{MediaWiki:Policy-url}}|წესებთან შესაბამისობაში]].',
 'revdelete-suppress-text' => "დამალვა შეიძლება განხორციელდეს '''მხოლოდ''' შემდეგ შემთხვევებში:
 * პოტენციურად ცილისმწამებლური ინფორმაცია
index 52a07eb..9814afb 100644 (file)
@@ -961,8 +961,6 @@ Tzemreḍ att ẓṛeḍ ; tilɣa llant deg [{{fullurl:{{#Special:Log}}/delete|p
 'revdelete-show-file-submit' => 'Ih',
 'revdelete-selected' => "'''{{PLURAL:$2|Tasiwelt tettwafren|Tisiwal ttwafernen}} n [[:$1]]'''",
 'logdelete-selected' => "'''{{PLURAL:$1|Tamirt n uɣmis tettwafren|Isallen n uɣmis ttwafernen}}:'''",
-'revdelete-text' => 'Ileqman d tidyanin yettumḥan ad qqimen deg umezruy n usebter dɣa deg iɣmisen, maca agbur nsen ur i sɛu ara tuffart i uzayez."
-Inedbalen wiyaḍ deg {{SITENAME}} zemren ad ẓṛen imuren i yettwafren u zemren a ten-mḥan, ḥaca ma llan icekkilen.',
 'revdelete-confirm' => 'Sergeg ma tebɣiḍ ad xedmeḍ tigawt agi, fehmeḍ inalkamen, dɣa temtawiḍ s [[{{MediaWiki:Policy-url}}|ilugan]].',
 'revdelete-suppress-text' => "Ilaq tukksa att illi \"kan\" deg tijṛa agi :
 * Tilɣa ahat tinergamin
index f308bb9..0ed5351 100644 (file)
@@ -823,8 +823,6 @@ $3 ар зтеухуауэ къитхыр: ''$2''",
 'revdelete-show-file-submit' => 'НытӀэ',
 'revdelete-selected' => "'''{{PLURAL:$2|Версиэ хэхар|Версиэ хэхахэр}} напэкӀуэцӀ [[:$1]]:'''",
 'logdelete-selected' => "'''{{PLURAL:$1|Тхылъ хэхар|Тхылъ хэхахэр}} тхыгъэм:'''",
-'revdelete-text' => 'НапэкӀуэцӀхэм я версиэ ихахэмрэ хъыбар щекӀуэкӀахэмрэ напэкӀуэцӀым и тхыдэмрэ тхыгъэмрэ гъэлъэгъуауэ щытынущ, абыхэм я лъэныкъуэгъу гуэрэхэр цӀыхухэтхэм щхьэкӀэ теубыдауэ щытынущ.
-Тхьэмадэ {{SITENAME}} проэктым щыщхэм пӀалъэ яӀэнущ теубыда тхыгъэхэм екӀуэлъэн, а интерфейсымкӀи зэфӀагъувэжын, теубыдыгъэ нэхъ ину ятемылъу щымыт къуэдеймэ.',
 'revdelete-confirm' => 'Арэзыгъуэ ет, быщӀэр зэр уи гугъэр, къыхэкӀынур къызэрыбгурыӀуэр, быщӀу хъуамкӀэ [[{{MediaWiki:Policy-url}}|хабзэм]] узэремыбакъуэр.',
 'revdelete-suppress-text' => "ГъэпшкӀугъэр щекӀуэкӀыфыну '''къуэдер''' мыбым хуэдэм:
 
index 4908dca..2729453 100644 (file)
@@ -651,8 +651,6 @@ Sıma be idarekerênia ho ra şikinê hona [$1 nê ferqi bıvênê], eke wazenê
 'revdelete-show-file-confirm' => 'Sıma eminê ke wazenê çımraviarnaena esterıtiya na dosya "<nowiki>$1</nowiki>" $2 ra $3 de bıvênê?',
 'revdelete-show-file-submit' => 'Heya',
 'revdelete-selected' => "'''[[:$1]]: ra {{PLURAL:$2|Çımraviarnaiso weçinıte|Çımraviarnaisê weçinıtey}}'''",
-'revdelete-text' => "Çımraviarnaişê esterıtey u kerdişi hewna tarixê pele u qeydan de asenê, hama parçê zerrekê dine areze nêbenê.'''
-Eke şertê ilawekerdey ke niyê ro, idarekerê bini {{SITENAME}} de nêşikinê hona bıresê zerrekê nımıtey u şikinê ey oncia na eyni mianpele ra peyser biarê.",
 'revdelete-suppress-text' => "Wedardene gunê '''teyna''' nê halunê cêrênu de bıguriyo:
 * Melumatê kıfırio mıhtemel
 * Melumatê şexsio bêmınasıb
index 6bfe265..be4303c 100644 (file)
@@ -1011,9 +1011,6 @@ $3 كەلتىرىلگەن سەبەبى: ''$2''",
 كەلتىرىلگەن تۇزەتۋ جوق, نە اعىمدىق تۇزەتۋدى جاسىرۋ ٴۇشىن ارەكەتتەنىپ كوردىڭىز.',
 'revdelete-selected' => "'''[[:$1]] دەگەننىڭ بولەكتەنگەن {{PLURAL:$2|تۇزەتۋى|تۇزەتۋلەرى}}:'''",
 'logdelete-selected' => "'''بولەكتەنگەن {{PLURAL:$1|جۋرنال وقىيعاسى|جۋرنال وقىيعالارى}}:'''",
-'revdelete-text' => "'''جويىلعان تۇزەتۋلەر مەن وقىيعالاردى ٴالى دە بەت تارىيحىندا جانە جۋرنالداردا تابۋعا بولادى, بىراق ولاردىڭ ماعلۇمات بولشەكتەرى بارشاعا قاتىنالمايدى.'''
-
-{{SITENAME}} جوباسىنىڭ باسقا اكىمشىلەرى جاسىرىن ماعلۇماتقا قاتىناي الادى, جانە قوسىمشا تىيىمدار قويىلعانشا دەيىن, وسى تىلدەسۋ ارقىلى جويۋدى بولدىرماۋى مۇمكىن.",
 'revdelete-legend' => 'كورىنىس تىيىمدارىن قويۋ:',
 'revdelete-hide-text' => 'تۇزەتۋ ٴماتىنىن جاسىر',
 'revdelete-hide-image' => 'فايل ماعلۇماتىن جاسىر',
index 119719e..a6d123e 100644 (file)
@@ -399,7 +399,7 @@ $messages = array(
 'tog-showhiddencats' => 'Жасырын санаттарды көрсету',
 'tog-norollbackdiff' => 'Шегіндіруден кейін нұсқалардың айырмашылығын көрсетпеу',
 'tog-useeditwarning' => 'Өңдемесі сақталмаған парақшадан шығар кезде ескерту',
-'tog-prefershttps' => 'Кірген кезде қауіпсіз байлануды әрқашан қолдану',
+'tog-prefershttps' => 'Ð\9aÑ\96Ñ\80ген ÐºÐµÐ·Ð´Ðµ Ò\9bаÑ\83Ñ\96пÑ\81Ñ\96з Ð±Ð°Ð¹Ð»Ð°Ð½Ñ\8bÑ\81Ñ\83дÑ\8b Ó\99Ñ\80Ò\9bаÑ\88ан Ò\9bолданÑ\83',
 
 'underline-always' => 'Әрқашан',
 'underline-never' => 'Ешқашан',
@@ -525,7 +525,7 @@ $messages = array(
 'vector-action-unprotect' => 'Қорғанысты өзгерту',
 'vector-view-create' => 'Бастау',
 'vector-view-edit' => 'Өңдеу',
-'vector-view-history' => 'Тарихын қарау',
+'vector-view-history' => 'Өңделу тарихы',
 'vector-view-view' => 'Оқу',
 'vector-view-viewsource' => 'Қайнарын қарау',
 'actions' => 'Әрекеттер',
@@ -734,8 +734,8 @@ $1',
 'protectedpagetext' => 'Бұл бет өңдеу немесе басқа өзгерістер енгізілмес үшін қорғалған.',
 'viewsourcetext' => 'Бұл беттің қайнарын қарауыңызға және көшіріп алуыңызға болады:',
 'viewyourtext' => 'Осы бет арқылы "өзіңіз жасаған өңдеулердің" бастапқы мәтінін көруге және көшіруге мүмкіндігіңіз болады.',
-'protectedinterface' => 'Бұл MediaWiki-дің [[Уикипедия:Интерфейсті аудару|жүйе хабарламасы]], оны тек жоба [[Уикипедия:Әкімшілер|әкімшілер]] ғана өзгерте алады. 
-Кейбір хабарламалар [[translatewiki:{{FULLPAGENAME}}/qqq|құжаттамада]] [[mw:Manual:Interface/{{PAGENAME}}|бар]].',
+'protectedinterface' => 'This page provides interface text for the software on this wiki, and is protected to prevent abuse.
+To add or change translations for all wikis, please use [//translatewiki.net/ translatewiki.net], the MediaWiki localisation project.',
 'editinginterface' => "'''Ескерту:''' Бағдарламалық жасақтаманың тілдесу мәтінін жетістіретін бетін өңдеп жатырсыз.
 Бұл беттің өзгертуі басқа қатысушыларға пайдаланушылық тілдесуі қалай көрінетіне әсер етеді.
 Барлық уикилер үшін аудармаларды өзгерту немесе қосу үшін [//translatewiki.net/ translatewiki.net] МедиаУики жерлестіру жобасын пайдаланыңыз.",
@@ -822,7 +822,7 @@ $2',
 'createacct-reason' => 'Себебі:',
 'createacct-reason-ph' => 'Неге басқа тіркегі жасамақшысыз',
 'createacct-captcha' => 'Құпиялық тексеруі',
-'createacct-imgcaptcha-ph' => 'Жоғарғыдағы көріп тұрған мәтінді енгізіңіз',
+'createacct-imgcaptcha-ph' => 'Жоғарыдағы мәтінді енгізіңіз',
 'createacct-submit' => 'Тіркелгіңізді жасаңыз',
 'createacct-another-submit' => 'Басқа тіркелгі жасау',
 'createacct-benefit-heading' => '{{SITENAME}} сіз сияқты қызығатын адамдар арқылы жасалады.',
@@ -898,6 +898,10 @@ $2',
 'login-abort-generic' => 'Жүйеге кіру үшін сәтсіз талпыныс жасадыңыз.',
 'loginlanguagelabel' => 'Тіл: $1',
 'suspicious-userlogout' => 'Сіздің жүйеден шығу сұранымыңыз қабылданбады, өйткені, бұл жарамсыз браузер немесе кэштеуші проксидің сұранымына ұқсайды.',
+'pt-login' => 'Кіру',
+'pt-login-button' => 'Кіру',
+'pt-createaccount' => 'Тіркелгі жасау',
+'pt-userlogout' => 'Шығу',
 
 # Email sending
 'php-mail-error-unknown' => 'Mail() PHP-функциясындағы белгісіз қате.',
@@ -1227,9 +1231,6 @@ $3 келтірілген себебі: ''$2''",
 'revdelete-show-file-submit' => 'Иә',
 'revdelete-selected' => "'''[[:$1]] дегеннің бөлектенген {{PLURAL:$2|түзетуі|түзетулері}}:'''",
 'logdelete-selected' => "'''Бөлектенген {{PLURAL:$1|журнал оқиғасы|журнал оқиғалары}}:'''",
-'revdelete-text' => "'''Жойылған түзетулер мен оқиғаларды әлі де бет тарихында және журналдарда табуға болады, бірақ олардың мағлұмат бөлшектері баршаға қатыналмайды.'''
-
-{{SITENAME}} жобасының басқа әкімшілері жасырын мағлұматқа қатынай алады, және қосымша тиымдар қойылғанша дейін, осы тілдесу арқылы жоюды болдырмауы мүмкін.",
 'revdelete-legend' => 'Көрініс тиымдарын қою:',
 'revdelete-hide-text' => 'Түзету мәтінін жасыр',
 'revdelete-hide-image' => 'Файл мағлұматын жасыр',
@@ -1302,6 +1303,9 @@ $1",
 'showhideselectedversions' => 'Бөлектенген нұсқаларды көрсет/жасыр',
 'editundo' => 'жоққа шығару',
 'diff-empty' => '(айырмашылығы жоқ)',
+'diff-multi-sameuser' => '(Жоғарыда көрсетілген қатысушының (бір ғана қатысушының) арадағы {{PLURAL:$1|бір түзетуі|$1 түзетуі}} көрсетілмеген)',
+'diff-multi-otherusers' => '({{PLURAL:$2|басқа бір қатысуышының|$2 қатысушының}} арадағы {{PLURAL:$1|бір түзетуі|$1 түзетуі}} көрсетілмеген)',
+'diff-multi-manyusers' => '($2-(ден<sup>4</sup>) көп {{PLURAL:$2|қатысуышының|қатысушының}} арадағы {{PLURAL:$1|бір түзетуі|$1 түзетуі}} көрсетілмеген)',
 'difference-missing-revision' => 'Бұл ($1) {{PLURAL:$2|нұсқа|$2 нұсқалар}} айырмашылығы табылмады.
 
 
@@ -1881,14 +1885,14 @@ URL дұрыс екендігін және торап істеп тұрғаны
 'linkstoimage-redirect' => '$1 (файл айдатылуы) $2',
 'duplicatesoffile' => 'Келесі {{PLURAL:$1|файл бұл файлдың телнұсқасы|$1 файл бұл файлдың телнұсқалары}} ([[Special:FileDuplicateSearch/$2|толығырақ көру]]):',
 'sharedupload' => 'Бұл файл $1 жобасынан сондықтан басқа жобаларда қолдануы мүмкін.',
-'sharedupload-desc-there' => 'Бұл файл $1 жобасынан және сондықтан басқа жобаларда қолдануы мүмкін.
+'sharedupload-desc-there' => 'Бұл файл $1 жобасынан, сондықтан басқа жобаларда lf қолдануы мүмкін.
 Қосымша мәліметтер үшін [$2 файл сипаттама бетін] қараңыз.',
-'sharedupload-desc-here' => 'Бұл файл $1 жобасынан және сондықтан басқа жобаларда қолдануы мүмкін.
+'sharedupload-desc-here' => 'Бұл файл $1 жобасынан сондықтан басқа жобаларда қолдануы мүмкін.
 Бұның сипатамасы [$2 файл сипаттама беті] төменде көрсетілген.',
-'sharedupload-desc-edit' => 'Бұл файл $1 жобасынан және сондықтан басқа жобаларда қолдануы мүмкін.
-СипаÑ\82Ñ\82амаÑ\81Ñ\8bн Ó©Ò£Ð´ÐµÐ³Ñ\96Ò£Ñ\96з ÐºÐµÐ»Ñ\81е Ð¼Ò±Ð½Ð´Ð° [$2 Ñ\84айл Ñ\81ипаÑ\82Ñ\82ама Ð±ÐµÑ\82Ñ\96].',
-'sharedupload-desc-create' => 'Бұл файл $1 жобасынан және сондықтан басқа жобаларда қолдануы мүмкін.
-Сипаттамасын өңдегіңіз келсе мұнда [$2 файл сипаттама беті].',
+'sharedupload-desc-edit' => 'Бұл файл $1 жобасынан, сондықтан басқа жобаларда да қолдануы мүмкін.
+СипаÑ\82Ñ\82амаÑ\81Ñ\8bн Ó©Ò£Ð´ÐµÐ³Ñ\96Ò£Ñ\96з ÐºÐµÐ»Ñ\81е Ð¾Ð» [$2 Ñ\84айл Ñ\81ипаÑ\82Ñ\82ама Ð±ÐµÑ\82Ñ\96нде].',
+'sharedupload-desc-create' => 'Бұл файл $1 жобасынан, сондықтан басқа жобаларда да қолдануы мүмкін.
+Сипаттамасын өңдегіңіз келсе [$2 файл сипаттама бетіне] өтіңіз.',
 'filepage-nofile' => 'Бұл атаумен файл жоқ.',
 'filepage-nofile-link' => 'Бұл атаумен файл жоқ, бірақ сіз оны [$1 жүктей аласыз].',
 'uploadnewversion-linktext' => 'Бұл файлдың жаңа нұсқасын жүктеу',
@@ -2005,7 +2009,7 @@ URL дұрыс екендігін және торап істеп тұрғаны
 'nbytes' => '$1 {{PLURAL:$1|байт|байт}}',
 'ncategories' => '$1 {{PLURAL:$1|Санат|Санаттар}}',
 'ninterwikis' => '$1 {{PLURAL:$1|интеруики|интеруикилер}}',
-'nlinks' => '$1 {{PLURAL:$1|сілтеме|сілтемелер}}',
+'nlinks' => '$1 сілтеме',
 'nmembers' => '$1 {{PLURAL:$1|мүше|мүше}}',
 'nmemberschanged' => '$1 → $2 {{PLURAL:$2|мүше|мүше}}',
 'nrevisions' => '$1 {{PLURAL:$1|түзету|түзету}}',
@@ -2217,6 +2221,7 @@ URL дұрыс екендігін және торап істеп тұрғаны
 'watchmethod-list' => 'жуықтағы өзгерістер үшін бақылаулы беттерді тексеру',
 'watchlistcontains' => 'Бақылау тізіміңізде $1 бет бар.',
 'iteminvalidname' => "'$1' данада ақау бар — жарамсыз атау…",
+'wlnote2' => 'Төменде $2, $3 кезіне дейінгі соңғы {{PLURAL:$1|сағаттағы|<strong>$1</strong> сағаттағы}} өзгерістер көрсетілген.',
 'wlshowlast' => 'Соңғы $1 сағаттағы, $2 күндегі, $3 болған өзгерісті көрсету',
 'watchlist-options' => 'Бақылау тізімінің баптаулары',
 
@@ -2482,6 +2487,7 @@ $1',
 'sp-contributions-search' => 'Үлес үшін іздеу',
 'sp-contributions-username' => 'IP-мекенжайы немесе қатысушы аты:',
 'sp-contributions-toponly' => 'Өңдемелердің тек соңғы нұсқаларын көрсету',
+'sp-contributions-newonly' => 'Бет бастау өңдемелерін ғана көрсету',
 'sp-contributions-submit' => 'Ізде',
 
 # What links here
index 0df6226..6593320 100644 (file)
@@ -974,9 +974,6 @@ Mında [{{fullurl:{{#special:Log}}/delete|page={{FULLPAGENAMEE}}}} joyw jwrnalı
 keltirilgen tüzetw joq, ne ağımdıq tüzetwdi jasırw üşin ärekettenip kördiñiz.',
 'revdelete-selected' => "'''[[:$1]] degenniñ bölektengen {{PLURAL:$2|tüzetwi|tüzetwleri}}:'''",
 'logdelete-selected' => "'''Bölektengen {{PLURAL:$1|jwrnal oqïğası|jwrnal oqïğaları}}:'''",
-'revdelete-text' => "'''Joýılğan tüzetwler men oqïğalardı äli de bet tarïxında jäne jwrnaldarda tabwğa boladı, biraq olardıñ mağlumat bölşekteri barşağa qatınalmaýdı.'''
-
-{{SITENAME}} jobasınıñ basqa äkimşileri jasırın mağlumatqa qatınaý aladı, jäne qosımşa tïımdar qoýılğanşa deýin, osı tildesw arqılı joywdı boldırmawı mümkin.",
 'revdelete-legend' => 'Körinis tïımdarın qoyw:',
 'revdelete-hide-text' => 'Tüzetw mätinin jasır',
 'revdelete-hide-image' => 'Faýl mağlumatın jasır',
index c322182..8488642 100644 (file)
@@ -812,9 +812,6 @@ $2',
 'rev-showdeleted' => 'ತೋರಿಸು',
 'revdelete-show-file-submit' => 'ಹೌದು',
 'revdelete-selected' => "'''[[:$1]]ರ ಆಯ್ಕೆಯಾಗಿರುವ {{PLURAL:$2|ಆವೃತ್ತಿ|ಆವೃತ್ತಿಗಳು}}:'''",
-'revdelete-text' => "'''ಅಳಿಸಲ್ಪಟ್ಟಿರುವ ಬದಲಾವಣೆಗಳು ಮತ್ತು ಘಟನೆಗಳು ಪುಟದ ಇತಿಹಾಸದಲ್ಲಿ ತೋರುತ್ತದೆ, ಆದರೆ ಅದರಲ್ಲಿನ ಮಾಹಿತಿಯು ಸಾರ್ವಜನಿಕರಿಗೆ ದೊರೆಯುವುದಿಲ್ಲ.'''
-
-{{SITENAME}} ಅಲ್ಲಿನ ಇತರ ನಿರ್ವಾಹಕರು ಹೀಗೆ ಅಡಗಿಸಲ್ಪಟ್ಟ ಮಾಹಿತಿಯನ್ನು ಪಡೆಯಬಹುದು ಮತ್ತು ಅದರ ಅಳಿಸುವಿಕೆಯನ್ನು ಇದೇ ವ್ಯವಸ್ಥೆಯ ಪ್ರಕಾರ ರದ್ದುಮಾಡಬಹುದು. ಹೆಚ್ಚುವರಿ ನಿಬಂಧನಗಳಿದ್ದರೆ ಹಾಗೆ ಮಾಡಲಾಗುವುದಿಲ್ಲ.",
 'revdelete-legend' => 'ಕಾಣಿಸುವಿಕೆಯ ನಿಬಂಧನೆಗಳನ್ನು ನಿಶ್ಚಯಿಸು',
 'revdelete-hide-text' => 'ಬದಲಾವಣೆಯ ಪಠ್ಯವನ್ನು ಅಡಗಿಸು',
 'revdelete-hide-image' => 'ಫೈಲಿನಲ್ಲಿರುವ ಮಾಹಿತಿಯನ್ನು ಅಡಗಿಸು',
index 9eb76f8..a56aab0 100644 (file)
@@ -913,6 +913,7 @@ $1 기다렸다가 다시 시도하세요.',
 'createacct-another-realname-tip' => '실명은 선택 사항입니다.
 실명을 입력하면 문서 기여에 사용자의 이름이 들어가게 됩니다.',
 'pt-login' => '로그인',
+'pt-login-button' => '로그인',
 'pt-createaccount' => '계정 만들기',
 'pt-userlogout' => '로그아웃',
 
@@ -1345,8 +1346,6 @@ $2개 보다 적게 {{PLURAL:$2|써야}} 하지만 {{PLURAL:$1|지금은 $1개
 'revdelete-show-file-submit' => '예',
 'revdelete-selected' => "'''[[:$1]]의 {{PLURAL:$2|선택한 판}}:'''",
 'logdelete-selected' => "'''{{PLURAL:$1|선택한 기록}}:'''",
-'revdelete-text' => "'''삭제된 판과 기록은 문서 역사와 기록에 계속 나타나지만, 내용은 공개되지 않을 것입니다.'''
-{{SITENAME}}의 다른 관리자는 다른 제한이 설정되어 있지 않는 한, 숨겨진 내용을 볼 수 있고, 같은 도구를 이용해 되살릴 수 있습니다.",
 'revdelete-confirm' => '이 작업을 수행하는 것의 결과를 알고 있으며, [[{{MediaWiki:Policy-url}}|정책]]에 맞는 행동인지 확인해주세요.',
 'revdelete-suppress-text' => "숨기기는 '''다음 경우에만''' 사용되어야 합니다:
 * 잠재적인 비방 정보
@@ -1484,7 +1483,7 @@ $1",
 'search-file-match' => '(내용이 일치하는 파일 있음)',
 'search-suggest' => '$1 문서를 찾고 있으신가요?',
 'search-interwiki-caption' => '자매 프로젝트',
-'search-interwiki-default' => '$1 결과:',
+'search-interwiki-default' => '$1 로부터의 결과:',
 'search-interwiki-more' => '(더 보기)',
 'search-relatedarticle' => '관련',
 'searcheverything-enable' => '모든 이름공간에서 검색',
@@ -2635,7 +2634,7 @@ $UNWATCHURL
 'delete-warning-toobig' => '이 문서에는 {{PLURAL:$1|편집 역사}}가 $1개 있습니다.
 편집 역사가 긴 문서를 삭제하면 {{SITENAME}} 데이터베이스 동작에 큰 영향을 줄 수 있습니다.
 주의해 주세요.',
-'deleting-backlinks-warning' => "'''경고:''' 삭제하려는 문서가 다른 문서에 연결되거나 삽입되어 있습니다.",
+'deleting-backlinks-warning' => "'''경고:''' 삭제하려는 문서가 [[Special:WhatLinksHere/{{FULLPAGENAME}}다른 문서에 연결]]되거나 삽입되어 있습니다.",
 
 # Rollback
 'rollback' => '편집 되돌리기',
index 9875b6b..ff547a0 100644 (file)
@@ -986,8 +986,6 @@ $3 джанындан берилген сылтау: ''$2''",
 'revdelete-show-file-submit' => 'Хоу',
 'revdelete-selected' => "'''[[:$1]] бетни {{PLURAL:$2|1=Сайланнган версия|сайланнган версиялары}}:'''",
 'logdelete-selected' => "'''Журналны {{PLURAL:$1|1=Сайланнган джазыу|сайланнган джазыулары}}:'''",
-'revdelete-text' => "'''Кетерилге версияла бла болуула алкъын бетни тарихи бла журналлада кёрюннюкдю, алай а бир кесеги тюз кириучюледен джашырыллыкъды.'''
-{{SITENAME}} сайтдагъы башха администраторла джашырылгъан ичге кирирге эмда аны ызына салыргъа боллукъдула.",
 'revdelete-confirm' => 'Тилейбиз, буну этерге излегенигизни, эсеблерин ангылагъаныгъызны, эм буну [[{{MediaWiki:Policy-url}}|джорукълагъа]] кёре этгенигизни билдиригиз.',
 'revdelete-suppress-text' => "Джашырыу '''джангыз''' бу турумлада этиледи:
 * Келишмеген энчи информация
index 00895b4..c0a3e28 100644 (file)
@@ -1280,9 +1280,6 @@ Als ene Wiki_Köbes kanns De de Ungerscheide ävver aankike wann De wells.",
 'revdelete-show-file-submit' => 'Lohß Jonn!',
 'revdelete-selected' => "'''{{PLURAL:$2|Ein usjewählte Version|$2 usjewählte Versione|Kein Version usjewählt}} vun [[:$1]]:'''",
 'logdelete-selected' => "'''{{PLURAL:$1|Dä ußjewählte Logboch-Endrach|De Ußjewählte Logboch-Endrähsch}}:'''",
-'revdelete-text' => "'''Dä fottjeschmesse Sigge ehre Enhald kanns De nit mieh aanluure. Se blieve ävver en de Liss met de Versione un en de Logböcher dren.'''
-Ene Wiki Köbes kann de fottjeschmessene Krom immer noch aanluere un kann en och widder herholle, usser wann bei
-dem Wiki singe Installation dat anders fassjelaht woode es.",
 'revdelete-confirm' => 'Bes esu joot un doon dat beschtääteje, un donn domet ongerschriive, dat De dat donn wells, dat De weiß, wat dobei eruß kütt, un dat De dat och noh de [[{{MediaWiki:Policy-url}}|Rääjelle]] deihß.',
 'revdelete-suppress-text' => "Dat sullt '''blooß''' jedonn wäde för:
 * onjesäzlesche Aanjaabe
index 22e0fa8..f59ba71 100644 (file)
@@ -730,6 +730,7 @@ Waart w.e.g. $1 ier Dir et nach eng Kéier probéiert.',
 
 Wann Dir en ugitt, gëtt e benotzt fir d'Benotzerattributiounen fir Är Aarbecht zouzeuerdnen.",
 'pt-login' => 'Aloggen',
+'pt-login-button' => 'Aloggen',
 'pt-createaccount' => 'Benotzerkont opmaachen',
 'pt-userlogout' => 'Ausloggen',
 
@@ -1141,8 +1142,7 @@ Dir kënnt dësen Ënnerscheed gesinn; Detailer fannt Dir am [{{fullurl:{{#Speci
 'revdelete-show-file-submit' => 'Jo',
 'revdelete-selected' => "'''{{PLURAL:$2|Gewielt Versioun|Gewielt Versioune}} vu(n) [[:$1]] :'''",
 'logdelete-selected' => "'''Ausgewielten {{PLURAL:$1|Evenement|Evenementer}} aus dem Logbuch:'''",
-'revdelete-text' => "'''Geläscht Versiounen oder aner geläscht Bestanddeeler sinn net méi ëffentlech zougänglech, si stinn awer weiderhin an der Versiounsgeschicht vun der Säit.'''
-Aner {{SITENAME}}-Administrateure kënnen de geläschten Inhalt oder aner geläscht Bestanddeeler weiderhi gesinn a restauréieren, et sief, et gouf festgeluecht, datt déi Limitatioune vum Accès och fir Administrateure gëllen.",
+'revdelete-text-others' => 'Aner Administrateuren op {{SITENAME}} kënnen nach ëmmer de verstoppten Inhalt gesinn an en iwwer deeselwechten Interface nees restauréieren, ausser wann zousätzlech Limitatiounen agestallt sinn.',
 'revdelete-confirm' => "Confirméiert w.e.g. datt Dir dat maache wëllt, datt Dir d'Konsequenze verstitt an datt Dir dëst an Aklang mat de [[{{MediaWiki:Policy-url}}|Richtlinne]] maacht.",
 'revdelete-suppress-text' => "Ënnerdréckung sollt '''nëmmen''' an dëse Fäll benotzt ginn:
 * Informatiounen déi beleidege kéinten
@@ -1236,7 +1236,7 @@ Denkt w.e.g drunn datt d'Navigatiounslinken d'Wiel vun de Versiounen nees zréck
 'difference-title-multipage' => '$1 a(n) $2: Ënnerscheed tëscht de Säiten',
 'difference-multipage' => '(Ënnerscheed tëscht Säiten)',
 'lineno' => 'Linn $1:',
-'compareselectedversions' => 'Ausgewielte Versioune vergläichen',
+'compareselectedversions' => 'Ausgewielt Versioune vergläichen',
 'showhideselectedversions' => 'Erausgesicht Versioune weisen/verstoppen',
 'editundo' => 'zréck',
 'diff-empty' => '(Keen Ënnerscheed)',
@@ -1281,7 +1281,7 @@ Detailer fannt Dir am [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}
 'search-file-match' => '(Inhalt vum Fichier passt)',
 'search-suggest' => 'Mengt Dir: $1',
 'search-interwiki-caption' => 'Schwësterprojeten',
-'search-interwiki-default' => '$1 Resultater:',
+'search-interwiki-default' => 'Resultater vu(n) $1:',
 'search-interwiki-more' => '(méi)',
 'search-relatedarticle' => 'A Verbindung',
 'searcheverything-enable' => 'An allen Nummraim sichen',
@@ -1604,7 +1604,7 @@ Dës Informatioun ass ëffentlech.",
 'recentchanges-legend-heading' => "'''Legend:'''",
 'recentchanges-legend-newpage' => '(kuckt och [[Special:NewPages|Lëscht vun den neie Säiten]])',
 'recentchanges-legend-plusminus' => "''(±123)''",
-'rcnotefrom' => "Ugewise ginn d'Ännerunge vum '''$2''' un (maximal '''$1''' Ännerunge gi gewisen).",
+'rcnotefrom' => "Ugewise ginn d'Ännerunge vum <strong>$2</strong> un (maximal <strong>$1</strong> Ännerunge gi gewisen).",
 'rclistfrom' => 'Nei Ännerunge vu(n) $1 u weisen',
 'rcshowhideminor' => 'Kleng Ännerunge $1',
 'rcshowhideminor-show' => 'Weisen',
@@ -2336,7 +2336,7 @@ E-Mail: $PAGEEDITOR_EMAIL
 Wiki: $PAGEEDITOR_WIKI
 
 Et gi soulaang keng weider Maile geschéckt, bis Dir d\'Säit nees emol besicht hutt wärend deem Dir ageloggt sidd.
-Op Ärer Iwwerwaachungslëscht kënnt Dir all Benoorichtigungsmarkeren zesummen zErécksetzen.
+Op Ärer Iwwerwaachungslëscht kënnt Dir all Benoorichtigungsmarkeren zesummen zrécksetzen.
 
 
 Äre frëndleche {{SITENAME}} Benoriichtigungssystem
@@ -2394,14 +2394,14 @@ D'Läsche vu sou Säite gouf limitéiert fir ongewollte Stéierungen op {{SITENA
 'delete-warning-toobig' => "Dës Säit huet eng laang Versiounsgeschicht, méi wéi $1 {{PLURAL:$1|Versioun|Versiounen}}.
 D'Läschen dovu kann zu Stéierungen am Fonctionnement vun {{SITENAME}} féieren;
 dës Aktioun soll mat Virsiicht gemaach ginn.",
-'deleting-backlinks-warning' => "'''Opgepasst:''' Aner Säite linken op déi Säit déi Dir am Gaang sidd ze läschen oder déi säit Déi Dir am Gaang sidd ze läschen ass an aner Säiten agebonn.",
+'deleting-backlinks-warning' => "'''Opgepasst:''' [[Special:WhatLinksHere/{{FULLPAGENAME}}|Aner Säite]] linken op déi Säit déi Dir am Gaang sidd ze läschen oder déi Säit Déi Dir am Gaang sidd ze läschen ass an aner Säiten agebonn.",
 
 # Rollback
 'rollback' => 'Ännerungen zrécksetzen',
 'rollback_short' => 'Zrécksetzen',
 'rollbacklink' => 'Zrécksetzen',
-'rollbacklinkcount' => '{{PLURAL:$1|Eng Ännerung|$1 Ännerungen}} zerécksetzen',
-'rollbacklinkcount-morethan' => 'méi wéi {{PLURAL:$1|Eng Ännerung|$1 Ännerungen}} zerécksetzen',
+'rollbacklinkcount' => '{{PLURAL:$1|Eng Ännerung|$1 Ännerungen}} zrécksetzen',
+'rollbacklinkcount-morethan' => 'méi wéi {{PLURAL:$1|Eng Ännerung|$1 Ännerungen}} zrécksetzen',
 'rollbackfailed' => 'Zrécksetzen huet net geklappt',
 'cantrollback' => 'Lescht Ännerung kann net zréckgesat ginn. De leschten Auteur ass deen eenzegen Auteur vun dëser Säit.',
 'alreadyrolled' => 'Déi lescht Ännerung vun der Säit [[:$1]] vum [[User:$2|$2]] ([[User talk:$2|talk]]{{int:pipe-separator}}[[Special:Contributions/$2|{{int:contribslink}}]]);; kann net zeréckgesat ginn;
index e978c4f..891b0cf 100644 (file)
@@ -971,8 +971,6 @@ achtergrönj zeen meugelik te vinjen in 't [{{fullurl:{{#Special:Log}}/suppress|
 'revdelete-show-file-submit' => 'Jao',
 'revdelete-selected' => "'''Geselecteerde {{PLURAL:$2|bewerking|bewerkinge}} van '''[[:$1]]''':'''",
 'logdelete-selected' => "'''{{PLURAL:$1|Geselecteerde log gebeurtenis|Geselecteerde log gebeurtenisse}}:'''",
-'revdelete-text' => "'''Gewisjde bewerkinge zeen zichbaar in de gesjiedenis, maar de inhoud is neet langer publiek toegankelik.'''
-Anger beheerders van {{SITENAME}} kinne de verborge inhoud benäöjere en de verwiedering ongedaon make mit behölp van dit sjerm, tenzij d'r additionele restricties gelje die zeen ingesteld door de systeembeheerder.",
 'revdelete-confirm' => "Bevestig des se dit wils doon, des se de consequenties begrieps en des se dit deis in euvereinstömming mit 't geljendj [[{{MediaWiki:Policy-url}}|beleid]].",
 'revdelete-suppress-text' => "Versies verbèrge deentj '''allein''' gebroek te waere in de volgende gevalle:
 * Ongepaste perseunlike informatie
index 549b006..7d041bf 100644 (file)
@@ -718,6 +718,7 @@ Palaukite prieš bandant vėl.',
 'loginlanguagelabel' => 'Kalba: $1',
 'suspicious-userlogout' => 'Jūsų prašymas atsijungti buvo atmestas, nes, atrodo, jį klaidingai išsiuntė naršyklė arba spartinantysis tarpinis serveris.',
 'pt-login' => 'Prisijungti',
+'pt-login-button' => 'Prisijungti',
 'pt-createaccount' => 'Sukurti paskyrą',
 'pt-userlogout' => 'Atsijungti',
 
@@ -1089,22 +1090,20 @@ Kaip administratorius, jūs galite ją pamatyti; daugiau detalių gali būti [{{
 'revdelete-show-file-submit' => 'Taip',
 'revdelete-selected' => "'''{{PLURAL:$2|Pasirinkta [[:$1]] versija|Pasirinktos [[:$1]] versijos}}:'''",
 'logdelete-selected' => "'''{{PLURAL:$1|Pasirinktas istorijos įvykis|Pasirinkti istorijos įvykiai}}:'''",
-'revdelete-text' => "'''Ištrintos versijos bei įvykiai vis tiek dar bus rodomi puslapio istorijoje ir specialiųjų veiksmų sąraše, bet jų turinio dalys nebus viešai prieinamos.'''
-Kiti administratoriai iš {{SITENAME}} vis tiek galės pasiekti paslėptą turinį ir galės jį atkurti per tą pačią sąsają, nebent yra nustatyti papildomi apribojimai.",
 'revdelete-confirm' => 'Prašome patvirtinti, kad jūs tai ketinate padaryti, kad jūs suprantate padarinius, ir kad jūs tai darote pagal [[{{MediaWiki:Policy-url}}|politiką]].',
 'revdelete-suppress-text' => "Ištrynimas turėtų būti taikomas '''tik''' šiais atvejais:
 * Netinkama asmeninė informacija
 *: ''namų adresai, telefonų numeriai, asmens kodai ir t. t.''",
 'revdelete-legend' => 'Nustatyti matomumo apribojimus:',
-'revdelete-hide-text' => 'Slėpti versijos tekstą',
+'revdelete-hide-text' => 'Versijos tekstas',
 'revdelete-hide-image' => 'Slėpti failo turinį',
 'revdelete-hide-name' => 'Slėpti veiksmą ir paskirtį',
-'revdelete-hide-comment' => 'Slėpti redagavimo komentarą',
-'revdelete-hide-user' => 'Slėpti redagavusiojo naudotojo vardą ar IP adresą',
+'revdelete-hide-comment' => 'Keitimo komentaras',
+'revdelete-hide-user' => 'Redagavusiojo naudotojo vardas/IP adresas',
 'revdelete-hide-restricted' => 'Nuslėpti duomenis nuo adminstratorių kaip ir nuo kitų',
 'revdelete-radio-same' => '(nekeisti)',
-'revdelete-radio-set' => 'Taip',
-'revdelete-radio-unset' => 'Ne',
+'revdelete-radio-set' => 'Paslėpta',
+'revdelete-radio-unset' => 'Matoma',
 'revdelete-suppress' => 'Slėpti duomenis nuo administratorių kaip ir nuo kitų',
 'revdelete-unsuppress' => 'Šalinti apribojimus atkurtose versijose',
 'revdelete-log' => 'Priežastis:',
@@ -1183,6 +1182,7 @@ Prašome patikrinti sąrašus.',
 'compareselectedversions' => 'Palyginti pasirinktas versijas',
 'showhideselectedversions' => 'Rodyti/slėpti pasirinktas versijas',
 'editundo' => 'atšaukti',
+'diff-empty' => '(Jokio skirtumo)',
 'diff-multi-manyusers' => '(daugiau nei $2 {{PLURAL:$2|naudotojo|naudotojų|naudotojų}} $1 {{PLURAL:$1|tarpinis keitimas nėra rodomas|tarpiniai keitimai nėra rodomi|tarpinių keitimų nėra rodoma}})',
 
 # Search results
@@ -1199,7 +1199,7 @@ Prašome patikrinti sąrašus.',
 'shown-title' => 'Rodyti $1 {{PLURAL:$1|rezultatą|rezultatus|rezultatus}} puslapyje',
 'viewprevnext' => 'Žiūrėti ($1 {{int:pipe-separator}} $2) ($3)',
 'searchmenu-exists' => "'''Puslapis pavadinimu „[[$1]]“ šioje wiki'''",
-'searchmenu-new' => "'''Sukurti puslapį „[[:$1]]“ šioje wiki!'''",
+'searchmenu-new' => '<strong>Sukurti puslapį „[[:$1]]“ šioje wiki!</strong> {{PLURAL:$2|0=|Taip pat peržiūrėkite šį rastą puslapį.|Taip pat peržiūrėkite šiuos paieškos rezultatus.}}',
 'searchprofile-articles' => 'Turinio puslapiai',
 'searchprofile-project' => 'Pagalbos ir projekto puslapiai',
 'searchprofile-images' => 'Daugialypės terpės failai',
@@ -1217,7 +1217,7 @@ Prašome patikrinti sąrašus.',
 'search-section' => '(skyrius $1)',
 'search-suggest' => 'Galbūt norėjote $1',
 'search-interwiki-caption' => 'Dukteriniai projektai',
-'search-interwiki-default' => '$1 rezultatai:',
+'search-interwiki-default' => 'Rezultatai iš $1:',
 'search-interwiki-more' => '(daugiau)',
 'search-relatedarticle' => 'Susiję',
 'searcheverything-enable' => 'Ieškoti visose vardų srityse',
@@ -1524,7 +1524,7 @@ teisės",
 'recentchanges-label-unpatrolled' => 'Šis keitimas dar nebuvo patikrintas',
 'recentchanges-label-plusminus' => 'Šiuo baitų skaičiumi pakeista puslapio apimtis',
 'recentchanges-legend-newpage' => '$1 - naujas puslapis',
-'rcnotefrom' => "Žemiau yra pakeitimai pradedant '''$2''' (rodoma iki '''$1''' pakeitimų).",
+'rcnotefrom' => 'Žemiau yra pakeitimai pradedant <strong>$2</strong> (rodoma iki <strong>$1</strong> pakeitimų).',
 'rclistfrom' => 'Rodyti naujus pakeitimus pradedant $1',
 'rcshowhideminor' => '$1 smulkius keitimus',
 'rcshowhideminor-show' => 'Rodyti',
@@ -1532,7 +1532,7 @@ teisės",
 'rcshowhidebots' => '$1 robotus',
 'rcshowhidebots-show' => 'Rodyti',
 'rcshowhidebots-hide' => 'Slėpti',
-'rcshowhideliu' => '$1 prisijungusius naudotojus',
+'rcshowhideliu' => '$1 registruotus naudotojus',
 'rcshowhideliu-show' => 'Rodyti',
 'rcshowhideliu-hide' => 'Slėpti',
 'rcshowhideanons' => '$1 anoniminius naudotojus',
index 4f78d3d..b73e4a7 100644 (file)
@@ -22,6 +22,7 @@
  * @author Marozols
  * @author Papuass
  * @author Reedy
+ * @author Srolanh
  * @author Xil
  * @author Yyy
  * @author לערי ריינהארט
@@ -428,6 +429,7 @@ Lai pievienotu izmaiņas tulkojumā visās ''wiki'', lūdzam izmantot ''MediaWik
 'ns-specialprotected' => 'Nevar izmainīt īpašās lapas.',
 'titleprotected' => "Šī lapa ir aizsargāta pret izveidošanu. To aizsargāja [[User:$1|$1]].
 Norādītais iemesls bija ''$2''.",
+'exception-nologin' => 'Neesat pieslēdzies',
 
 # Virus scanner
 'virus-badscanner' => "Nekorekta konfigurācija: nezināms vīrusu skeneris: ''$1''",
@@ -548,9 +550,15 @@ Tādēļ šobrīd no šīs IP adreses vairs nevar izveidot jaunus kontus.',
 Lūdzu, uzgaidiet $1 pirms mēģiniet vēlreiz.',
 'login-abort-generic' => 'Jūsu pieteikšanās bija neveiksmīga — Darbība pārtraukta',
 'loginlanguagelabel' => 'Valoda: $1',
+'pt-login' => 'Pieslēgties',
+'pt-login-button' => 'Pieslēgties',
+'pt-createaccount' => 'Reģistrēties',
+'pt-userlogout' => 'Iziet',
 
 # Email sending
 'php-mail-error-unknown' => 'Nezināma kļūda PHP mail() funkcijā',
+'user-mail-no-addy' => 'Mēģināja sūtīt e-pastu bez e-pasta adreses.',
+'user-mail-no-body' => 'Mēģināja sūtīt e-pastu ar tukšu vai nepamatoti īsu pamata daļu.',
 
 # Change password dialog
 'changepassword' => 'Mainīt paroli',
@@ -596,6 +604,7 @@ Pagaidu parole: $2',
 'changeemail-cancel' => 'Atcelt',
 
 # Special:ResetTokens
+'resettokens-tokens' => 'Žetoni:',
 'resettokens-token-label' => '$1 (šībrīža vērtība: $2)',
 
 # Edit page toolbar
@@ -883,7 +892,6 @@ Sīkāku informāciju var atrast [{{fullurl:{{#Special:Log}}/delete|page={{FULLP
 'revdelete-show-file-submit' => 'Jā',
 'revdelete-selected' => "'''[[:$1]] {{PLURAL:$2|izvēlētā versija|izvēlētās versijas}}:'''",
 'logdelete-selected' => "'''{{PLURAL:$1|Izvēlētais reģistra ieraksts|Izvēlētie reģistra ieraksti}}:'''",
-'revdelete-text' => "'''Lapu hronoloģijā un reģistros izdzēstās versijas vēl joprojām būs redzamas, tomēr daļa informācijas nebūs pieejama publiski.''' Citi {{SITENAME}} administratori varēs apskatīt spēlto saturu un varēs to atslēpt, ja vien nav papildu ierobežojumi.",
 'revdelete-confirm' => 'Lūdzu apstiprini, ka Tu zini, ko dari, Tu apzinies sekas, tāpat Tu to dari saskaņā ar vadlīnijām.',
 'revdelete-suppress-text' => "Paslēpšanu izmantot vienīgi šādos gadījumos:
 * potenciāli apmelojoša informācija
index b1c0ca7..fb2d27d 100644 (file)
@@ -919,7 +919,6 @@ $2',
 'revdelete-show-file-submit' => '善',
 'revdelete-selected' => "'''審[[:$1]]已擇$2:'''",
 'logdelete-selected' => "'''已擇誌$1:'''",
-'revdelete-text' => "'''刪審雖見誌,其文摒公眾,惟有秩可得之。'''無規則有秩可復還焉。",
 'revdelete-confirm' => '爾確作之,解之果焉,合之[[{{MediaWiki:Policy-url}}|策]]矣。',
 'revdelete-suppress-text' => "'''限'''於此壓:
 * 無適之個訊
index ec60a5b..dc2fc1f 100644 (file)
@@ -842,8 +842,6 @@ $3 द्वारा देल कारण अछि ''$2''",
 'revdelete-show-file-submit' => 'हँ',
 'revdelete-selected' => "'''{{PLURAL:$2|चुनल संशोधन|चुनल संशोधन सभ}} एकर [[:$1]]:'''",
 'logdelete-selected' => "'''{{PLURAL:$1|चुनल वृत्तलेख घटना|चुनल वृत्तलेख घटना सभ}}:'''",
-'revdelete-text' => "'''मेटाएल संशोधन सभ आ घटना सभ पन्नाक इतिहास आ वृत्तलेखमे आएत, मुदा ओकर सूचीक किछु भाग सामान्य लोक लेल उपलब्ध नै रहत।'''
-{{अन्तर्जाल}} पर दोसर संचालक लग अखनो नुकाएल सूची उपलब्ध छन्हि आ ओ ओकरा फेरसँ आनि सकै छथि अही मध्यस्थक द्वारा, आ से हएत जँ अतिरिक्त प्रतिबन्ध लागू रहत।",
 'revdelete-confirm' => 'कृपा कऽ आश्वस्त भऽ जाउ जे अहाँ ई करऽ चाहै छी, अहाँकेँ एकर परिणामक जनतब अछि, आ अहाँ एकरा [[{{MediaWiki:Policy-url}}|निअम]] क अनुसार कऽ रहल छी।',
 'revdelete-suppress-text' => "दबाबैबला काज '''मात्र''' ऐ सभ स्थितिमे प्रयोग करू:
 * मानहानिक सम्भावनाबला सूचना
index 1f4fb43..d217830 100644 (file)
@@ -881,8 +881,6 @@ $3 макссь туфталсь - ''$2''",
 'revdelete-show-file-submit' => 'Ина',
 'revdelete-selected' => "''''''$1:'''-нь {{PLURAL:$2|Кочкаф верзиец|Кочкаф верзиенза}}'''",
 'logdelete-selected' => "'''{{PLURAL:$1|Кочкаф сёрматфтомась|кочкаф сёрматфтоматне}}:'''",
-'revdelete-text' => "'''Нардаф верзиетне илядыхть няевикс лопать историясонза ди нардамань лувомава, интай сонь потмоснон пакшенза кармайхть аф сембонди сатовихть.'''
-Иля {{SITENAME}}нь оцюнятненди кяшф потмоснон ули кода ваномс эди мърдафтомс тяка програмонь ванфть вельде мъзярс иля кардафксне исть путов.",
 'revdelete-legend' => 'Арафтомс няемга оторхне',
 'revdelete-hide-text' => 'Кяшемс тя лопать верзиенц',
 'revdelete-hide-image' => 'Кяшемс файлхнень потмосна',
index 95d1c2a..3166000 100644 (file)
@@ -1175,8 +1175,6 @@ tsy misy ilay izy, na ny santiôna ankehitriny no andramana asitrika.',
 'revdelete-show-file-submit' => 'Eny',
 'revdelete-selected' => "'''{{PLURAL:$2|Votoatiny nosafidiana|Votoatiny nosafidiana}}n'i '''[[:$1]]''' :'''",
 'logdelete-selected' => "'''{{PLURAL:$1||}}Laogy voafidy :'''",
-'revdelete-text' => "'''Mbola ho ao amin'ny laogim-pejy ary ao amin'ny logy ny versiona ary zava-nitranga voaesotra, fa tsy ho hitan'ny mason'ny vahoaka ny votoatin'izy ireo.'''
-Mbola afaka jeren'ireo mpandrindran'i {{SITENAME}} foana ny votoatiny voafina  ary azony atao ho hitan'ny vahoaka indray ilay izy amin'ny alalan'ity pejy fanaovan-tsafidy ity, raha tsy misy fepetra apetraka.",
 'revdelete-confirm' => 'Amafiso eto ny hevitrao raha hanao io ianao, raha azonao sary an-tsaina ny mety ho vokany, ary raha araka ny [[{{MediaWiki:Policy-url}}|fepetra mihatra]] ny zavatra ataonao.',
 'revdelete-suppress-text' => "Ny famafàna pejy dia ampiasaina rehefa :
 * Fampahalalana mampiely lainga
index 7ab865d..138bb9f 100644 (file)
@@ -1064,8 +1064,6 @@ Sanak dapek malieknyo; rinciannyo mungkin ado di [{{fullurl:{{#Special:Log}}/del
 'revdelete-show-file-submit' => 'Yo',
 'revdelete-selected' => "'''{{PLURAL:$2|Revisi piliahan}} dari [[:$1]]:'''",
 'logdelete-selected' => "'''{{PLURAL:$1|Log piliahan}}:'''",
-'revdelete-text' => "'''Revisi jo tindakan nan alah dihapuih akan tetap muncua di versi tadaulu dan laman log, tapi bagian dari isinyo indak dapek diakses publik.'''
-Panguruih {{SITENAME}} lain tetap dapek mangakses isi nan tasuruak ko dan dapek mambatalan pangapuihannyo manggunoan antarmuko nan samo, kacuali ado pambatehan lain nan dibuek.",
 'revdelete-confirm' => 'Tolong konfirmasi baso Sanak samemang bamakasuik malakuan iko, mamahami konsekuensinyo, dan baso Sanak malakuannyo sasuai jo [[{{MediaWiki:Policy-url}}|kabijakan]].',
 'revdelete-suppress-text' => "Panyambunyian revisi '''hanyo''' buliah digunoan untuak kasus-kasus barikuik:
 * Informasi paribadi nan indak patuik
index 98895db..721f280 100644 (file)
@@ -905,6 +905,7 @@ $2',
 'createacct-another-realname-tip' => 'Вистинското име е незадолжително.
 Доколку изберете да го внесете, тоа може да се искористи за оддавање на заслуги за Вашата работа.',
 'pt-login' => 'Најава',
+'pt-login-button' => 'Најава',
 'pt-createaccount' => 'Направи сметка',
 'pt-userlogout' => 'Одјава',
 
@@ -1337,8 +1338,10 @@ $3 ја наведе следнава причина: ''$2''",
 'revdelete-show-file-submit' => 'Да',
 'revdelete-selected' => "'''{{PLURAL:$2|Избрана ревизија|Избрани ревизии}} од [[:$1]]:'''",
 'logdelete-selected' => "'''{{PLURAL:$1|Одбран настан од дневник|Одбрани настани од дневник}}:'''",
-'revdelete-text' => "'''Избришаните измени и настани сѐ уште ќе се појавуваат во историјата на страницата и дневниците, но делови од нивната содржина ќе бидат недостапни за јавноста.'''
-Други администратори на {{SITENAME}} сѐ уште ќе имаат пристап до скриената содржина и ќе можат да ја вратат преку истиот посредник, освен ако не се поставени дополнителни ограничувања.",
+'revdelete-text-text' => 'Избришаните ревизии сепак се појавуваат во историјата, но делови од нивната содржина ќе бидат недостапни за јавноста.',
+'revdelete-text-file' => 'Избришаните верзии на податотеките сепак се појавуваат во нејзината историја, но делови од нивната содржина ќе бидат недостапни за јавноста.',
+'logdelete-text' => 'Избришаните дневнички ставки сепак се појавуваат во дневниците, но делови од нивната содржина ќе бидат недостапни за јавноста.',
+'revdelete-text-others' => 'Другите администратори на {{SITENAME}} сепак ќе имаат пристап до скриените содржини и ќе можат да го повратат избришаното преку овој ист посредник, доколку не ставите дополнителни ограничувања.',
 'revdelete-confirm' => 'Потврдете дека сакате да го направите ова, дека ги сфаќате последиците, и дека тоа го правите во согласност со [[{{MediaWiki:Policy-url}}|правилата]].',
 'revdelete-suppress-text' => "Притајувањето се користи '''само''' во следниве случаи:
 * Потенцијално клеветнички информации
index 9fd819f..eeb1f18 100644 (file)
@@ -887,6 +887,7 @@ $2',
 
 എങ്കിലും അങ്ങനെ ചെയ്താൽ, ഉപയോക്താക്കൾക്ക് അവരരവരുടെ പേരിൽ തന്നെ തങ്ങളുടെ സൃഷ്ടിക്ക് കടപ്പാട് ലഭിക്കുന്നതാണ്.',
 'pt-login' => 'പ്രവേശിക്കുക',
+'pt-login-button' => 'പ്രവേശിക്കുക',
 'pt-createaccount' => 'അംഗത്വമെടുക്കുക',
 'pt-userlogout' => 'ലോഗൗട്ട്',
 
@@ -1293,9 +1294,10 @@ $3 നൽകിയിരിക്കുന്ന കാരണം ''$2'' എന
 'revdelete-show-file-submit' => 'അതെ',
 'revdelete-selected' => "'''[[:$1]] എന്ന താളിന്റെ {{PLURAL:$2|തിരഞ്ഞെടുത്ത പതിപ്പ്|തിരഞ്ഞെടുത്ത പതിപ്പുകൾ}}:'''",
 'logdelete-selected' => "'''{{PLURAL:$1|തിരഞ്ഞെടുത്ത രേഖയിലുള്ളത്|തിരഞ്ഞെടുത്ത രേഖയിലുള്ളവ}}:'''",
-'revdelete-text' => "'''മായ്ക്കപ്പെട്ട നാൾപ്പതിപ്പുകളും സംഭവങ്ങളും താളിന്റെ നാൾവഴിയിലും രേഖകളിലും ഉണ്ടായിരിക്കും, പക്ഷേ ആ ഉള്ളടക്കം പൊതുജനത്തിനു ലഭ്യമായിരിക്കില്ല.'''
-
-മറ്റു സം‌രക്ഷണ പരിമിതികൾ സജ്ജീകരിച്ചിട്ടില്ലെങ്കിൽ {{SITENAME}} സം‌രംഭത്തിലെ മറ്റു കാര്യനിർവാഹകർക്ക്, ഇതേ സമ്പർക്കമുഖം ഉപയോഗിച്ചു തന്നെ, ഈ മറഞ്ഞിരിക്കുന്ന ഉള്ളടക്കം പരിശോധിക്കുവാനും താങ്കൾ മായ്ച്ചതു തിരസ്കരിക്കുവാനും സാധിക്കും.",
+'revdelete-text-text' => 'മായ്ക്കപ്പെട്ട നാൾപ്പതിപ്പുകൾ താളിന്റെ നാൾവഴിയിൽ കാണാവുന്നതായിരിക്കുമെങ്കിലും, അവയുടെ ഉള്ളടക്കത്തിന്റെ ചില ഭാഗങ്ങൾ പൊതുജനങ്ങൾക്ക് ലഭ്യമായിരിക്കണമെന്നില്ല.',
+'revdelete-text-file' => 'പ്രമാണത്തിന്റെ മായ്ക്കപ്പെട്ട പതിപ്പുകൾ താളിന്റെ നാൾവഴിയിൽ കാണാവുന്നതായിരിക്കുമെങ്കിലും, അവയുടെ ഉള്ളടക്കത്തിന്റെ ചില ഭാഗങ്ങൾ പൊതുജനങ്ങൾക്ക് ലഭ്യമായിരിക്കണമെന്നില്ല.',
+'logdelete-text' => 'മായ്ക്കപ്പെട്ട പ്രവൃത്തികൾ പ്രവർത്തന രേഖകളിൽ കാണാവുന്നതായിരിക്കുമെങ്കിലും, അവയുടെ ഉള്ളടക്കത്തിന്റെ ചില ഭാഗങ്ങൾ പൊതുജനങ്ങൾക്ക് ലഭ്യമായിരിക്കണമെന്നില്ല.',
+'revdelete-text-others' => '{{SITENAME}} സംരംഭത്തിലെ മറ്റ് കാര്യനിർവ്വാഹകർക്ക് മറയ്ക്കപ്പെട്ട ഉള്ളടക്കം ഇപ്പോഴും എടുക്കാവുന്നതും ആവശ്യമെങ്കിൽ ഇതേ സമ്പർക്കമുഖം ഉപയോഗിച്ച് പുനഃസ്ഥാപിക്കാനോ അല്ലെങ്കിൽ കൂടുതൽ നിബന്ധനകൾ ചേർക്കാനോ കഴിയുന്നതുമാണ്.',
 'revdelete-confirm' => 'ഇതിന്റെ അനന്തരഫലങ്ങളെക്കുറിച്ചറിയാമെന്നും, [[{{MediaWiki:Policy-url}}|നയങ്ങൾ]] പാലിച്ചാണ് താങ്കളിത് ചെയ്യുന്നതെന്നും ഉറപ്പാക്കുക.',
 'revdelete-suppress-text' => "താഴെ പറയുന്ന സാഹചര്യങ്ങളിൽ '''മാത്രമേ''' ഒതുക്കൽ ഉപയോഗിക്കാവൂ:
 * അപകീർത്തികരമായ വിവരങ്ങൾ അടങ്ങിയവ
@@ -1430,7 +1432,7 @@ $1",
 'search-file-match' => '(പ്രമാണ ഉള്ളടക്കവുമായി ഒത്തുപോകുന്നുണ്ട്)',
 'search-suggest' => 'താങ്കൾ ഉദ്ദേശിച്ചത് $1 എന്നാണോ',
 'search-interwiki-caption' => 'സഹോദര സംരംഭങ്ങൾ',
-'search-interwiki-default' => '$1 ഫലങ്ങൾ:',
+'search-interwiki-default' => '$1 à´µà´¿à´\95àµ\8dà´\95ിയിൽ à´¨à´¿à´¨àµ\8dà´¨àµ\81à´³àµ\8dà´³ à´«à´²à´\99àµ\8dà´\99ൾ:',
 'search-interwiki-more' => '(കൂടുതൽ)',
 'search-relatedarticle' => 'ബന്ധപ്പെട്ടവ',
 'searcheverything-enable' => 'എല്ലാ നാമമേഖലകളും തിരയുക',
index de8c093..6cc5215 100644 (file)
@@ -213,7 +213,7 @@ $messages = array(
 'vector-action-unprotect' => 'Хамгаалалтаа солих',
 'vector-view-create' => 'Үүсгэх',
 'vector-view-edit' => 'Засварлах',
-'vector-view-history' => 'Ð\97аÑ\81ваÑ\80Ñ\8bн Ñ\82үүх',
+'vector-view-history' => 'Түүх',
 'vector-view-view' => 'Унших',
 'vector-view-viewsource' => 'Кодыг харах',
 'actions' => 'Үйлдлүүд',
@@ -327,7 +327,7 @@ $1',
 'editlink' => 'загварыг засах',
 'viewsourcelink' => 'кодыг харах',
 'editsectionhint' => 'Хэсгийг засварлах: $1',
-'toc' => 'Ð\90гÑ\83Ñ\83лга',
+'toc' => 'Ð\93аÑ\80Ñ\87иг',
 'showtoc' => 'дэлгэх',
 'hidetoc' => 'хумих',
 'collapsible-collapse' => 'хумих',
@@ -348,7 +348,7 @@ $1',
 'sort-ascending' => 'Өсөхөөр эрэмбэлэх',
 
 # Short words for each namespace, by default used in the namespace tab in monobook
-'nstab-main' => 'Хуудас',
+'nstab-main' => 'Өгүүлэл',
 'nstab-user' => 'Хэрэглэгчийн хуудас',
 'nstab-media' => 'Медиа хуудас',
 'nstab-special' => 'Тусгай хуудас',
@@ -357,7 +357,7 @@ $1',
 'nstab-mediawiki' => 'Мэдэгдэл',
 'nstab-template' => 'Загвар',
 'nstab-help' => 'Тусламж',
-'nstab-category' => 'Ангилал',
+'nstab-category' => 'Анги',
 
 # Main script and global functions
 'nosuchaction' => 'Тийм үйлдэл байхгүй байна',
@@ -918,7 +918,7 @@ $3-н тодорхойлсон шалтгаан нь ''$2''",
 'historyempty' => '(хоосон байна)',
 
 # Revision feed
-'history-feed-title' => 'Ð\97аÑ\81ваÑ\80Ñ\8bн Ñ\82үүх',
+'history-feed-title' => 'Түүх',
 'history-feed-description' => 'Вики дэх энэ хуудасны засварын түүх',
 'history-feed-item-nocomment' => '$2 дээрх $1',
 'history-feed-empty' => 'Таны үзэх гэсэн хуудас байхгүй байна.
@@ -965,8 +965,6 @@ $3-н тодорхойлсон шалтгаан нь ''$2''",
 'revdelete-show-file-submit' => 'Тийм',
 'revdelete-selected' => "'''[[:$1]]-н {{PLURAL:$2|сонгосон засвар|сонгосон засварууд}}:'''",
 'logdelete-selected' => "'''{{PLURAL:$1|Сонгосон логийн үйл явдал|Сонгосон логийн үйл явдлууд}}:'''",
-'revdelete-text' => "'''Устгагдсан засварууд ба үйл явдлууд нь хуудасны түүх болон логт харагдах хэвээр үлдэх ч эдгээрийн зарим агуулга нийтэд үл харагдана.'''
-Давхар хязгаарууд тавигдаагүй тохиолдолд {{SITENAME}}-н бусад администраторууд нуугдсан агуулгыг энэ талбараар харж үл арилгах боломжтой хэвээр үлдэнэ.",
 'revdelete-confirm' => 'Та энэхүү үйлдлийг хийх гэж байгаа, үр дагаварыг ойлгож байгаа, [[{{MediaWiki:Policy-url}}|дүрмийн дагуу]] хийж байгаа гэдгээ батална уу.',
 'revdelete-suppress-text' => "'''Зөвхөн'' дараах тохиолдлуудад л далдалгааг хэрэглэнэ:
 *Гүтгэсэн, матсан байж болох мэдээлэл
@@ -1348,7 +1346,7 @@ $1 тэмдэгтээс богино байх ёстой.',
 'action-createtalk' => 'ярианы хуудас үүсгэх',
 'action-createaccount' => 'энэ хэрэглэгчийн бүртгэлийг үүсгэх',
 'action-minoredit' => 'энэ засварыг бага зэргийн гэж тэмдэглэх',
-'action-move' => 'хуудсыг зөөх',
+'action-move' => 'нэр солих',
 'action-move-subpages' => 'энэ хуудас болон түүний дэд хуудсуудыг зөөх',
 'action-move-rootuserpages' => 'хэрэглэгчийн үндсэн хуудсуудыг зөөх',
 'action-movefile' => 'энэ файлыг зөөх',
@@ -1389,12 +1387,15 @@ $1 тэмдэгтээс богино байх ёстой.',
 'recentchanges-label-bot' => 'Робот гүйцэтгэсэн засвар',
 'recentchanges-label-unpatrolled' => 'Энэ засварыг одоогийн байдлаар манаагүй байна',
 'recentchanges-label-plusminus' => 'Өөрчлөгдсөн байт хэмжээ',
+'recentchanges-legend-heading' => "'''Таних үсэг:'''",
 'recentchanges-legend-newpage' => '([[Special:NewPages|жагсааж харах]])',
 'rcnotefrom' => "Доорх нь '''$2'''-с хойших өөрчлөлтүүд ('''$1''' хүртэлхийг харуулав) юм.",
 'rclistfrom' => '$1-с хойших шинэ засваруудыг үзүүлэх',
 'rcshowhideminor' => 'Бага зэргийн засваруудыг $1',
 'rcshowhidebots' => 'Роботуудыг $1',
 'rcshowhideliu' => 'Нийт $1 бүртгэгдсэн хэрэглэгчид',
+'rcshowhideliu-show' => 'үзүүлэх',
+'rcshowhideliu-hide' => 'нуух',
 'rcshowhideanons' => 'Бүртгэлгүй хэрэглэгчдийг $1',
 'rcshowhideanons-show' => 'үзүүлэх',
 'rcshowhideanons-hide' => 'нуух',
@@ -1872,7 +1873,7 @@ URL нь зөв болон сайт ажиллагаатай байгаа эсэ
 'newpages' => 'Шинэ хуудсууд',
 'newpages-username' => 'Хэрэглэгчийн нэр:',
 'ancientpages' => 'Хамгийн хуучин хуудсууд',
-'move' => 'Ð\97Ó©Ó©х',
+'move' => 'Ð\9eндоогооÑ\80 Ð½Ñ\8dÑ\80лÑ\8dх',
 'movethispage' => 'Энэ хуудсыг зөөх',
 'unusedimagestext' => 'Дараах файлууд нь байгаа ч гэсэн ямар ч хуудсанд эмбэдлэгдээгүй байна.
 Бусад вэб хуудаснуудаас зураг руу шууд URL-р нь холбогдож болох учраас идэвхтэй хэрэглэгдэж буй эсэхээс үл хамааран энд жагсагдсан байж болно гэдгийг анхаарна уу.</p>',
@@ -2233,7 +2234,7 @@ $UNWATCHURL
 'undeletebtn' => 'Сэргээх',
 'undeletelink' => 'үзэх/сэргээх',
 'undeleteviewlink' => 'харах',
-'undeleteinvert' => 'ЭÑ\81Ñ\80Ñ\8dгÑ\8dÑ\8dÑ\80 Ð½Ñ\8c Ð±Ð¾Ð»Ð³Ð¾Ñ\85',
+'undeleteinvert' => 'Ð\97ааÑ\81нааÑ\81 Ð±Ñ\83Ñ\81ад',
 'undeletecomment' => 'Шалтгаан:',
 'undeletedrevisions' => '{{PLURAL:$1|1 хувилбар|$1 хувилбар}}  сэргээгдлээ',
 'undeletedrevisions-files' => '{{PLURAL:$1|1 засвар|$1 засвар}} ба {{PLURAL:$2|1 файл|$2 файл}} сэргээгдлээ',
@@ -2264,7 +2265,8 @@ $1',
 
 # Namespace form on various pages
 'namespace' => 'Нэрний зай:',
-'invert' => 'Эсрэгээр нь болгох',
+'invert' => 'Зааснаас бусад',
+'namespace_association' => 'Заасан төрлөөс',
 'blanknamespace' => '(Гол)',
 
 # Contributions
@@ -2457,7 +2459,7 @@ $1',
 
 # Move page
 'move-page' => '$1-г зөөх',
-'move-page-legend' => 'Ð¥Ñ\83Ñ\83дÑ\81Ñ\8bг Ð·Ó©Ó©х',
+'move-page-legend' => 'Ð¥Ñ\83Ñ\83дÑ\81Ñ\8bг Ð¾Ð½Ð´Ð¾Ð¾Ð³Ð¾Ð¾Ñ\80 Ð½Ñ\8dÑ\80лÑ\8dх',
 'movepagetext' => "Доорх маягтыг ашигласнаар хуудасны нэр солигдож, түүний бүх түүх шинэ нэр лүү зөөгдөх болно.
 Хуучин гарчиг нь шинэ гарчиг руух чиглүүлэгч болно.
 Та чиглүүлэгчийг эх бичвэр лүү автоматаар заахаар шинэчлэх боломжтой.
@@ -2472,7 +2474,7 @@ $1',
 *Доорх дөрвөлжинг хоосон болгосон
 
 Эдгээр тохиолдлуудад уг хуудсыг гар аргаар зөөх эсвэл нэгтгэх шаардлагатай болно.",
-'movearticle' => 'Ð¥Ñ\83Ñ\83дÑ\81Ñ\8bг Ð·Ó©Ó©х:',
+'movearticle' => 'Ð¥Ñ\83Ñ\83дÑ\81Ñ\8bн Ð½Ñ\8dÑ\80ийг Ñ\81олих:',
 'moveuserpage-warning' => "'''Анхаар:''' Та хэрэглэгчийн хуудсыг зөөх гэж байна. Зөвхөн хуудас нь л зөөгдөнө, харин хэрэглэгчийн нэр ''солигдохгүй'' гэдгийг анхаарана уу.",
 'movenologintext' => 'Та хуудсыг зөөхийн тулд бүртгэлтэй бөгөөд [[Special:UserLogin|холбогдсон]] байх ёстой.',
 'movenotallowed' => 'Таньд хуудас зөөх зөвшөөрөл байхгүй байна.',
@@ -2646,11 +2648,11 @@ $1',
 'tooltip-pt-mycontris' => 'Таны оруулсан хувь нэмрийн жагсаалт',
 'tooltip-pt-login' => 'Заавал хийх ёстой зүйл биш боловч таныг нэвтрэхийг зөвлөж байна.',
 'tooltip-pt-logout' => 'Гарах',
-'tooltip-ca-talk' => 'Хуудасны талаарх хэлэлцүүлэг',
-'tooltip-ca-edit' => 'Та энэ хуудсыг засварлах боломжтой. Хадгалахынхаа өмнө "Урьдчилан харах" товчлуурыг хэрэглэнэ үү.',
-'tooltip-ca-addsection' => 'ШинÑ\8d Ñ\85Ñ\8dÑ\81Ñ\8dг Ò¯Ò¯Ñ\81гэх',
+'tooltip-ca-talk' => 'Хуудсыг зөвшин хэлэлцэх',
+'tooltip-ca-edit' => 'Та энэ хуудсыг засч янзалж болно. Хадгалахаасаа өмнө урьдчилан харах товчийг дардаг юм шүү.',
+'tooltip-ca-addsection' => 'ШинÑ\8d Ñ\81Ñ\8dдвÑ\8dÑ\8dÑ\80 Ñ\8fÑ\80Ñ\8cж Ñ\8dÑ\85лэх',
 'tooltip-ca-viewsource' => 'Энэ хуудас хамгаалагдсан байна. Та зөвхөн кодыг нь харах боломжтой.',
-'tooltip-ca-history' => 'Энэ хуудасны өмнөх засварууд.',
+'tooltip-ca-history' => 'Энэ хуудсыг зассан түүхийг сөхөн нягтлах',
 'tooltip-ca-protect' => 'Энэ хуудсыг хамгаалах',
 'tooltip-ca-unprotect' => 'Энэ хуудасны хамгаалалтыг солих',
 'tooltip-ca-delete' => 'Энэ хуудсыг устгах',
@@ -2679,7 +2681,7 @@ $1',
 'tooltip-t-specialpages' => 'Тусгай хуудаснуудын жагсаалт',
 'tooltip-t-print' => 'Энэ хуудасны хувилж болох хувилбар',
 'tooltip-t-permalink' => 'Хуудасны одоогийн хувилбар луу очих тогтмол линк',
-'tooltip-ca-nstab-main' => 'Өгүүлж буй гол хуудсыг үзэх',
+'tooltip-ca-nstab-main' => 'Өгүүлсэн хуудас',
 'tooltip-ca-nstab-user' => 'Хэрэглэгчийн хуудсыг үзэх',
 'tooltip-ca-nstab-media' => 'Медиа хуудсыг үзэх.',
 'tooltip-ca-nstab-special' => 'Энэ бол тусгай хуудас, та үүнийг шууд засварлах боломжгүй.',
@@ -2688,7 +2690,7 @@ $1',
 'tooltip-ca-nstab-mediawiki' => 'Системийн мэдэгдлийг үзэх.',
 'tooltip-ca-nstab-template' => 'Загварыг үзэх',
 'tooltip-ca-nstab-help' => 'Тусламжийн хуудсыг үзэх',
-'tooltip-ca-nstab-category' => 'Ангиллын хуудсыг үзэх',
+'tooltip-ca-nstab-category' => 'Анги, бүлгийн хуудас',
 'tooltip-minoredit' => 'Бага зэргийн засвар гэж тэмдэглэх',
 'tooltip-save' => 'Засваруудаа хадгалах',
 'tooltip-preview' => 'Өөрийн оруулах гэж буй өөрчлөлтүүдийг урьдчилан харах. Үүнийг ашиглана уу!',
index 374a55e..23ce88d 100644 (file)
@@ -858,6 +858,8 @@ $2',
 'suspicious-userlogout' => 'तुमच्या सनोंद-निर्गमनास नकार दिल्या गेला कारण असे दिसते की ती विनंती अन-अनुबंधित(डिसकनेक्टेड) न्याहाळकाद्वारे पाठवल्या गेली.',
 'createacct-another-realname-tip' => 'आपले खरे नाव टाकणे वैकल्पिक आहे.
 जर आपण ते द्यायचे ठरविले तर,ते आपल्या कामाचा मूळ स्रोत म्णून देण्यास वापरले जाईल.',
+'pt-login' => 'सनोंद-प्रवेश करा',
+'pt-userlogout' => 'सनोंद-निर्गम',
 
 # Email sending
 'php-mail-error-unknown' => 'पीएचपीच्या विपत्र() पर्यायात अज्ञात चूक',
@@ -1240,9 +1242,6 @@ $3ने ''$2'' कारण दिले आहे.",
 'revdelete-show-file-submit' => 'होय',
 'revdelete-selected' => "'''[[:$1]] {{PLURAL:$2|ची निवडलेली आवृत्ती|च्या निवडलेल्या आवृत्त्या}}:'''",
 'logdelete-selected' => "'''{{PLURAL:$1|निवडलेली नोंदीकृत घटना|निवडलेल्या नोंदीकृत घटना}}:'''",
-'revdelete-text' => "'''वगळलेल्या नोंदी आणि घटना अजूनही पानाच्या इतिहासात आणि नोंदीत आढळेल,परंतु मजकुराचा भाग सार्वजनिक स्वरूपात उपलब्ध राहणार नाही.'''
-
-अजून इतर  प्रतिबंध घातल्याशिवाय {{SITENAME}}चे इतर प्रबंधक लपविलेला मजकूर याच दुव्याने परतवू शकतील.",
 'revdelete-confirm' => "कृपया '''याची खात्री करा''' की तुम्ही जे करीत आहात, त्याचे परिणाम आपण जाणत आहात आणि, ते काम [[{{MediaWiki:Policy-url}}|मीडियाविकीच्या नीती]]नुसार आहे.",
 'revdelete-suppress-text' => "लपवण्याचा वापर '''फक्त''' पुढील बाबतीत होतो:
 * उच्च दर्जाची बदनामीकारक माहिती
@@ -1693,16 +1692,28 @@ $1",
 'rcnotefrom' => "खाली <b>$2</b> पासूनचे ('''$1''' पर्यंत) बदल दाखविले आहेत.",
 'rclistfrom' => '$1 नंतर केले गेलेले बदल दाखवा.',
 'rcshowhideminor' => 'छोटे बदल $1',
+'rcshowhideminor-show' => 'दाखवा',
+'rcshowhideminor-hide' => 'लपवा',
 'rcshowhidebots' => 'सांगकामे(बॉट्स) $1',
+'rcshowhidebots-show' => 'दाखवा',
+'rcshowhidebots-hide' => 'लपवा',
 'rcshowhideliu' => '$1नोंदणीकृत सदस्य',
+'rcshowhideliu-show' => 'दाखवा',
+'rcshowhideliu-hide' => 'लपवा',
 'rcshowhideanons' => 'अनामिक सदस्य $1',
+'rcshowhideanons-show' => 'दाखवा',
+'rcshowhideanons-hide' => 'लपवा',
 'rcshowhidepatr' => '$1 पहारा असलेली संपादने',
+'rcshowhidepatr-show' => 'दाखवा',
+'rcshowhidepatr-hide' => 'लपवा',
 'rcshowhidemine' => 'माझे बदल $1',
+'rcshowhidemine-show' => 'दाखवा',
+'rcshowhidemine-hide' => 'लपवा',
 'rclinks' => 'मागील $2 दिवसांतील $1 बदल पहा.<br />$3',
 'diff' => 'फरक',
 'hist' => 'इति',
 'hide' => 'लपवा',
-'show' => 'पहा',
+'show' => 'दाà¤\96वा',
 'minoreditletter' => 'छो',
 'newpageletter' => 'न',
 'boteditletter' => 'सां',
index 653126f..d9bb355 100644 (file)
@@ -1133,8 +1133,6 @@ Anda boleh melihat perbezaan ini; butiran boleh didapati di [{{fullurl:{{#Specia
 'revdelete-show-file-submit' => 'Ya',
 'revdelete-selected' => "'''{{PLURAL:$2|Versi|Versi-versi}} '''$1''' yang dipilih:'''",
 'logdelete-selected' => "'''{{PLURAL:$1|Peristiwa|Peristiwa-peristiwa}} log yang dipilih:'''",
-'revdelete-text' => "'''Semakan dan peristiwa yang dihapuskan akan tetap muncul dalam sejarah laman dan log, tetapi kandungannya tidak boleh diakses awam.'''
-Pentadbir {{SITENAME}} boleh melihat kandungan tersebut dan menyahhapuskannya semula melalui laman ini melainkan mempunyai batasan.",
 'revdelete-confirm' => 'Sila sahkan bahawa anda bertujuan melakukan ini, bahawa anda faham akibatnya, dan anda melakukannya menurut [[{{MediaWiki:Policy-url}}| polisi]].',
 'revdelete-suppress-text' => "Sekatan seharusnya digunakan '''hanya''' untuk kes-kes berikut:
 * maklumat yang mungkin berunsur fitnah
index 615f174..db9e9a6 100644 (file)
@@ -1137,8 +1137,6 @@ Bħala amministratur inti xorta waħda tista' tarah dan il-konfront; ikkonsulta
 'revdelete-show-file-submit' => 'Iva',
 'revdelete-selected' => "'''{{PLURAL:$2|Reviżjoni magħżula|Reviżjonijiet magħżula}} ta' [[:$1]]:'''",
 'logdelete-selected' => "'''{{PLURAL:$1|Avveniment tar-reġistru magħżul|Avvenimenti tar-reġistri magħżula}}:'''",
-'revdelete-text' => "'''Reviżjonijiet u azzjonijiet imħassra xorta waħda jidhru fil-kronoloġija tal-paġna, filwaqt li partijiet tal-kontenut jiġu inaċċessibli għall-pubbliku.'''
-L-amminstraturi l-oħrajn fuq {{SITENAME}} xorta jkunu jistgħu jidħlu fuq il-kontenut moħbi u jistgħu jirkuprawh minn din l-istess interfaċċa, sakemm restrizzjonijiet ulterjuri jiġu definiti.",
 'revdelete-confirm' => 'Jekk jogħġbok ikkonferma li dan hu dak li tixtieq tagħmel, li tifhem il-konsegwenzi, u li qed tagħmel dan skont il-[[{{MediaWiki:Policy-url}}|politika]].',
 'revdelete-suppress-text' => "It-trażżin għandu jintuża '''biss''' għall-każijiet segwenti:
 * Potenzjal ta' kontenut libelluż
index 2d4662a..85e0ad2 100644 (file)
@@ -220,7 +220,7 @@ $messages = array(
 'articlepage' => 'Khoàⁿ loē-iông ia̍h',
 'talk' => 'thó-lūn',
 'views' => 'Khoàⁿ',
-'toolbox' => 'Ke-si kheh-á',
+'toolbox' => 'Ke-si',
 'userpage' => 'Khoàⁿ iōng-chiá ê Ia̍h',
 'projectpage' => 'Khoàⁿ sū-kang ia̍h',
 'imagepage' => 'Khoàⁿ tóng-àn ia̍h',
@@ -496,6 +496,9 @@ Lîm-sî ê bi̍t-bé: $2',
 'newarticle' => '(Sin)',
 'newarticletext' => "Lí tòe 1 ê liân-kiat lâi kàu 1 bīn iáu-bōe chûn-chāi ê ia̍h. Beh khai-sí pian-chi̍p chit ia̍h, chhiáⁿ tī ē-kha ê bûn-jī keh-á lāi-té phah-jī. ([[{{MediaWiki:Helppage}}|Bo̍k-lio̍k]] kà lí án-choáⁿ chìn-hêng.) Ká-sú lí bô-tiuⁿ-tî lâi kàu chia, ē-sai chhi̍h liû-lám-khì ê '''téng-1-ia̍h''' tńg--khì.",
 'anontalkpagetext' => "----''Pún thó-lūn-ia̍h bô kò·-tēng ê kháu-chō/hō·-thâu, kan-na ū 1 ê IP chū-chí (chhin-chhiūⁿ 123.456.789.123). In-ūi bô kāng lâng tī bô kāng sî-chūn ū khó-lêng tú-hó kong-ke kāng-ê IP, lâu tī chia ê oē ū khó-lêng hō· bô kāng lâng ê! Beh pī-bián chit khoán būn-tê, ē-sái khì [[Special:UserLogin|khui 1 ê hō·-thâu a̍h-sī teng-ji̍p]].''",
+'noarticletext' => '這頁這馬無內容,你會使佇別頁[[Special:Search/{{PAGENAME}}|揣這頁標題]],
+<span class="plainlinks">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} 揣相關日誌],
+抑[{{fullurl:{{FULLPAGENAME}}|action=edit}} 改這頁]</span>。',
 'clearyourcache' => "'''Chù-ì:''' Pó-chûn liáu-āu, tio̍h ē-kì leh kā liû-lám-khì ê cache piàⁿ tiāu chiah khoàⁿ-ē-tio̍h kái-piàn: *'''Firefox / Safari:''' chhi̍h tiâu \"Shift\" kâng-sî-chūn tiám-kik ''Reload/têng-sin chài-ji̍p'' a̍h-sī chhi̍h ''Ctrl-F5'' \"Ctrl-R\" kî-tiong chi̍t ê (''Command-R'' tī Mac) 
 * '''Google Chrome:''' chhi̍h ''Ctrl-Shift-R'' (''Command-Shift-R'' tī Mac)
 '''Internet Explorer :'''chhi̍h tiâu \"Ctrl\" kâng-sî-chūn tiám-kek ''Refresh/têng-sin chài-ji̍p'' a̍h-sī chhi̍h \"Ctrl-F5\" 
@@ -563,6 +566,12 @@ Lí ê kái-piàn tī ē-kha ê bûn-jī-keh. Lí su-iàu chiōng lí chò ê k
 # Revision feed
 'history-feed-item-nocomment' => '$1 tī $2',
 
+# Revision deletion
+'revdel-restore' => '改會當看無',
+
+# Merge log
+'revertmerge' => '取消合併',
+
 # Diffs
 'history-title' => '"$1"的歷史版本',
 'lineno' => 'Tē $1 chōa:',
@@ -580,16 +589,22 @@ Lí ê kái-piàn tī ē-kha ê bûn-jī-keh. Lí su-iàu chiōng lí chò ê k
 'shown-title' => 'Múi ia̍h hián-sī $1 {{PLURAL:$1|kiat-kó|kiat-kó}}',
 'viewprevnext' => 'Khoàⁿ ($1 {{int:pipe-separator}} $2) ($3)',
 'searchprofile-articles' => 'Loē-iông ia̍h',
+'searchprofile-project' => '幫助佮事工的頁',
 'searchprofile-images' => 'To-mûi-thé',
 'searchprofile-everything' => 'Só͘-ū ê',
 'searchprofile-advanced' => 'chìn-chi̍t-pō͘',
 'searchprofile-articles-tooltip' => 'Tī $1 chhoé',
+'searchprofile-project-tooltip' => 'Tī $1 chhoé',
 'searchprofile-images-tooltip' => 'Chhoé tóng-àn',
+'searchprofile-everything-tooltip' => '揣全部(包括討論頁)',
+'searchprofile-advanced-tooltip' => '佇你家己設的名空間內底揣',
 'search-result-size' => '$1 ({{PLURAL:$2|1 jī-goân|$2 jī-goân}})',
+'search-redirect' => '(轉去 $1)',
 'search-section' => '(toān-lo̍h $1)',
 'searchall' => 'choân-pō·',
 'showingresults' => 'Ē-kha tùi #<b>$2</b> khai-sí hián-sī <b>$1</b> hāng kiat-kó.',
 'showingresultsnum' => 'Ē-kha tùi #<b>$2</b> khai-sí hián-sī <b>$3</b> hāng kiat-kó.',
+'showingresultsheader' => "對'''$4'''的{{PLURAL:$5|第 '''$1''' 到第 '''$3''' 項結果|第 '''$1 - $2''' 項,總共 '''$3''' 項結果}}",
 'powersearch-legend' => 'Kiám-sek',
 
 # Preferences page
@@ -709,7 +724,7 @@ Tī pat-lâng liân-lo̍k lí ê sî-chūn bē kā e-mail tsū-tsí siá chhut--
 'filehist-datetime' => 'Ji̍t-kî/ Sî-kan',
 'filehist-thumb' => '細張圖',
 'filehist-user' => 'Iōng-chiá',
-'imagelinks' => 'Iáⁿ-siōng liân-kiat',
+'imagelinks' => 'tóng-àn sù-iōng ê chōng-hòng',
 'linkstoimage' => 'Í-hā ê ia̍h liân kàu chit ê iáⁿ-siōng:',
 'nolinkstoimage' => 'Bô poàⁿ ia̍h liân kàu chit tiuⁿ iáⁿ-siōng.',
 
@@ -888,6 +903,7 @@ Also see [[Special:WantedCategories|wanted categories]].',
 # Undelete
 'undelete' => 'Kiù thâi tiāu ê ia̍h',
 'undeletepage' => 'Khoàⁿ kap kiù thâi tiāu ê ia̍h',
+'undeletelink' => '看/復原',
 'undeleteviewlink' => 'Khoàⁿ',
 
 # Namespace form on various pages
@@ -932,6 +948,8 @@ Also see [[Special:WantedCategories|wanted categories]].',
 'ipusubmit' => 'Chhú-siau hong-só chit ê chū-chí',
 'ipblocklist' => 'Siū hong-só ê IP chū-chí kap iōng-chiá miâ-chheng',
 'blocklink' => 'hong-só',
+'unblocklink' => '廢除封鎖',
+'change-blocklink' => '改封鎖',
 'contribslink' => 'kòng-hiàn',
 'autoblocker' => 'Chū-tōng kìm-chí lí sú-iōng, in-ūi lí kap "$1" kong-ke kāng 1 ê IP chū-chí (kìm-chí lí-iû "$2").',
 'blocklogentry' => 'hong-só [[$1]], siat kî-hān chì $2 $3',
@@ -967,6 +985,7 @@ Liâu--lo̍h-khì chìn-chêng, chhiáⁿ seng khak-tēng lí ū liáu-kái chia
 'movepage-page-moved' => '$1 í-keng sóa khì tī $2.',
 'movelogpagetext' => 'Ē-kha lia̍t-chhut hông soá-ūi ê ia̍h.',
 'movereason' => 'Lí-iû:',
+'revertmove' => 'hôe-tńg',
 'selfmove' => 'Goân piau-tê kap sin piau-tê sio-siâng; bô hoat-tō· sóa.',
 'protectedpagemovewarning' => "'''KÉNG-KÒ: Pún ia̍h só tiâu leh. Kan-taⁿ ū hêng-chèng te̍k-koân ê iōng-chiá (sysop) ē-sái soá tín-tāng.'''
 Ē-kha ū choè-kīn ê kì-lio̍k thang chham-khó:",
@@ -993,6 +1012,7 @@ Liâu--lo̍h-khì chìn-chêng, chhiáⁿ seng khak-tēng lí ū liáu-kái chia
 'tooltip-pt-userpage' => 'Lí chit ê iōng-chiá ê ia̍h',
 'tooltip-pt-mytalk' => 'Lí ê thó-lūn ia̍h',
 'tooltip-pt-preferences' => 'Lí ê siat-tēng',
+'tooltip-pt-watchlist' => '你監視的頁有改過的清單',
 'tooltip-pt-mycontris' => 'Lí ê kòng-hiàn lia̍t-toaⁿ',
 'tooltip-pt-login' => 'Hi-bāng lí teng-ji̍p; m̄-ko bô kiông-chè',
 'tooltip-pt-logout' => 'Teng-chhut',
@@ -1003,6 +1023,7 @@ Lí ē-sái khoàⁿ i ê goân-sú-bé.',
 'tooltip-ca-history' => 'Chit ia̍h ê chá-chêng pán-pún',
 'tooltip-ca-delete' => 'Thâi chit ia̍h',
 'tooltip-ca-move' => '徙這頁',
+'tooltip-ca-watch' => '共這頁加入去你的監視單',
 'tooltip-ca-unwatch' => 'Lí ê kàm-sī-toaⁿ soá tiàu chit ia̍h.',
 'tooltip-search' => 'Chhoé {{SITENAME}}',
 'tooltip-search-fulltext' => 'Chhoé ū chia-ê jī ê ia̍h',
@@ -1016,6 +1037,7 @@ Lí ē-sái khoàⁿ i ê goân-sú-bé.',
 'tooltip-n-help' => 'Beh chhoé ê só͘-chāi',
 'tooltip-t-whatlinkshere' => 'Só͘-ū liân kàu chia ê liat-toaⁿ',
 'tooltip-t-recentchangeslinked' => 'Liân kàu chit ia̍h koh choè-kīn ū kái koè--ê',
+'tooltip-feed-atom' => '訂看這頁的修改',
 'tooltip-t-contributions' => 'Khoàⁿ chit ê iōng-chiá ê kòng-hiàn lia̍t-toaⁿ',
 'tooltip-t-upload' => 'Í-keng sàng chiūⁿ-bāng ê tóng-àn',
 'tooltip-t-specialpages' => 'Só͘-ū te̍k-sû-ia̍h ê lia̍t-toaⁿ',
index 5a45e9e..98498e2 100644 (file)
@@ -1277,8 +1277,6 @@ Du kan se denne diffen; det kan finnes detaljer i [{{fullurl:{{#Special:Log}}/su
 'revdelete-show-file-submit' => 'Ja',
 'revdelete-selected' => "'''{{PLURAL:$2|Valgt revisjon|Valgte revisjoner}} av [[:$1]]:'''",
 'logdelete-selected' => "'''{{PLURAL:$1|Valgt loggoppføring|Valgte loggoppføringer}}:'''",
-'revdelete-text' => "'''Slettede versjoner og oppføringer vil fortsatt vises i sidehistorikken og loggene, men deler av innholdet vil ikke lenger bli offentliggjort.'''
-Andre administratorer på {{SITENAME}} vil fortsatt kunne se det skjulte innholdet, og kan gjenopprette det, med mindre videre begrensninger blir gitt av sideoperatørene.",
 'revdelete-confirm' => 'Bekreft at du ønsker å gjøre dette, at du forstår konsekvensene, og at du gjør det i samsvar med [[{{MediaWiki:Policy-url}}|retningslinjene]].',
 'revdelete-suppress-text' => "Skjuling bør '''kun''' brukes i følgende tilfeller:
 * Mulig injurierende utsagn
index fb80ce9..1c3edd8 100644 (file)
@@ -961,8 +961,6 @@ As Administrater kannst du [$1 mit dissen Lenk] den Ünnerscheed ankieken.',
 'revdelete-show-file-submit' => 'Jo',
 'revdelete-selected' => "'''{{PLURAL:$2|Wählte Version|Wählte Versionen}} vun [[:$1]]:'''",
 'logdelete-selected' => "'''{{PLURAL:$1|Wählt Logbook-Indrag|Wählte Logbook-Indrääg}}:'''",
-'revdelete-text' => "'''Wegsmetene Versionen un Akschonen staht noch jümmer in de Versionsgeschicht un Logböker, sünd aver nich mehr apen intosehn.'''
-{{SITENAME}}-Administraters köönt de Sieden noch jümmer sehn un ok wedderhalen, solang dat nich extra fastleggt is, dat ok Administraters dat nich mehr mehr dröfft.",
 'revdelete-suppress-text' => "Ünnerdrücken schull '''blot''' bi disse Fäll bruukt warrn:
 * Nich passliche persönliche Information
 *: ''Adressen, Telefonnummern, Sozialversekerungsnummern etc.''",
index 60eab6c..23ff532 100644 (file)
@@ -1255,8 +1255,6 @@ Je kunnen disse verschillen bekieken. Misschien steet der over in t [{{fullurl:{
 'revdelete-show-file-submit' => 'Ja',
 'revdelete-selected' => "'''{{PLURAL:$2|Ekeuzen bewarking|Ekeuzen bewarkingen}} van '''[[:$1]]''':'''",
 'logdelete-selected' => "'''{{PLURAL:$1|Ekeuzen logboekboekaksie|Ekeuzen logboekaksies}}:'''",
-'revdelete-text' => "'''Vortedaone bewarkingen staon nog altied in de geschiedenisse en in logboeken, mer niet iederene kan de inhoud zo mer bekieken.'''
-Beheerders van {{SITENAME}} kunnen de verbörgen inhoud bekieken en t weerummeplaotsen deur dit scharm te gebruken, behalven as der aandere beparkingen in-esteld bin.",
 'revdelete-confirm' => "Bevestig da'j dit doon wollen, da'j de gevolgen dervan begriepen en da'j t doon in overeenstemming mit t geldende [[{{MediaWiki:Policy-url}}|beleid]].",
 'revdelete-suppress-text' => "Onderdrokken ma'j '''allinnig''' gebruken in de volgende gevallen:
 * Ongepassen persoonlike informasie
index 1aa1d63..8a26867 100644 (file)
@@ -938,6 +938,7 @@ Wacht alstublieft $1 voordat u het opnieuw probeert.',
 'createacct-another-realname-tip' => 'Echte naam is optioneel.
 Als u deze opgeeft, wordt deze naam gebruikt worden om u erkenning te geven voor uw werk.',
 'pt-login' => 'Aanmelden',
+'pt-login-button' => 'Aanmelden',
 'pt-createaccount' => 'Registreren',
 'pt-userlogout' => 'Afmelden',
 
@@ -1367,8 +1368,6 @@ U kunt deze verschillen bekijken. Er kunnen details te vinden zijn in het [{{ful
 'revdelete-show-file-submit' => 'Ja',
 'revdelete-selected' => "'''Geselecteerde {{PLURAL:$2|bewerking|bewerkingen}} van [[:$1]]:'''",
 'logdelete-selected' => "'''{{PLURAL:$1|Geselecteerde logboekhandeling|Geselecteerde logboekhandelingen}}:'''",
-'revdelete-text' => "'''Verwijderde bewerkingen zijn zichtbaar in de geschiedenis en logboeken, maar delen van de inhoud zijn niet langer publiek toegankelijk.'''
-Andere beheerders van {{SITENAME}} kunnen de verborgen inhoud benaderen en de verwijdering ongedaan maken met behulp van dit formulier, tenzij er aanvullende beperkingen gelden die zijn ingesteld door de systeembeheerder.",
 'revdelete-confirm' => 'Bevestig dat u dit wilde doen, dat u de consequenties begrijpt en dat u dit doet in overeenstemming met het geldende [[{{MediaWiki:Policy-url}}|beleid]].',
 'revdelete-suppress-text' => "Gebruik versies verbergen '''alleen''' in de volgende gevallen:
 * Mogelijk smadelijke informatie;
index 1b15a35..6fcdf81 100644 (file)
@@ -1208,8 +1208,6 @@ Du kan sjå skilnaden; detaljar finst i [{{fullurl:{{#Special:Log}}/suppcess|pag
 'revdelete-show-file-submit' => 'Ja',
 'revdelete-selected' => "'''{{PLURAL:$2|Vald versjon|Valde versjonar}} av [[:$1]]:'''",
 'logdelete-selected' => "'''{{PLURAL:$1|Vald loggoppføring|Valde loggoppføringar}}:'''",
-'revdelete-text' => "Sletta versjonar og oppføringar vert framleis synlege i sidehistorikken og loggane, men delar av innhaldet deira vert ikkje lenger offentleggjort.'''
-Andre administratorar på {{SITENAME}} kan framleis sjå det gøymde innhaldet og attopprette det, med mindre fleire avgrensingar vert lagde inn av sideoperatørane.",
 'revdelete-confirm' => 'Stadfest at du ynskjer å gjera dette, at du skjønar konsekvensane, og at du gjer det i samsvar med [[{{MediaWiki:Policy-url}}|retningslinene]].',
 'revdelete-suppress-text' => "Løyning av sideversjonar bør '''berre''' nyttast i desse tilfella:
 * Mogeleg ærekrenkjande informasjon
index 8cbbc3d..f7ed3bc 100644 (file)
@@ -292,8 +292,8 @@ $linkTrail = "/^([a-zàâçéèêîôû]+)(.*)$/sDu";
 $messages = array(
 # User preference toggles
 'tog-underline' => 'Soslinhar los ligams :',
-'tog-hideminor' => 'Amagar los darrièrs cambiaments menors',
-'tog-hidepatrolled' => 'Amagar las modificacions susvelhadas dels darrièrs cambiaments',
+'tog-hideminor' => 'Amagar los cambiaments menors dins los darrièrs cambiaments',
+'tog-hidepatrolled' => 'Amagar las modificacions susvelhadas dins los darrièrs cambiaments',
 'tog-newpageshidepatrolled' => 'Amagar las paginas susvelhadas de la lista de las paginas novèlas',
 'tog-extendwatchlist' => 'Espandir la lista de seguiment per afichar totas las modificacions e non pas solament las mai recentas',
 'tog-usenewrc' => 'Agropar los cambiaments per pagina dins los darrièrs cambiaments e la lista de seguiment',
@@ -617,9 +617,9 @@ Una lista de las paginas especialas pòt èsser trobada sus [[Special:SpecialPag
 'databaseerror-query' => 'Requèsta : $1',
 'databaseerror-function' => 'Foncion : $1',
 'databaseerror-error' => 'Error : $1',
-'laggedslavemode' => 'Atencion : Aquesta pagina pòt conténer pas totes los darrièrs cambiaments efectuats.',
+'laggedslavemode' => '<strong>Atencion :</strong> Aquesta pagina pòt conténer pas totes los darrièrs cambiaments efectuats.',
 'readonly' => 'Mesas a jorn blocadas sus la banca de donadas',
-'enterlockreason' => 'Indicatz la rason del blocatge, e mai una estimacion de sa durada',
+'enterlockreason' => 'Indicatz la rason del varrolhatge, e mai una estimacion de sa durada',
 'readonlytext' => "Los ajustons e mesas a jorn de la banca de donadas son actualament blocats, probablament per permetre la mantenença de la banca, aprèp aquò, tot dintrarà dins l'òrdre.
 
 L’administrator qu'a varrolhat la banca de donadas a balhat l’explicacion seguenta : $1",
@@ -695,7 +695,7 @@ L'administrator que l'a varrolhat a provesit aqueste motiu : « $3 ».",
 # Login and logout pages
 'logouttext' => "'''Ara, sètz desconnectat.'''
 
-Notatz que d'unas paginas pòdon èsser encara afichadas coma s'eratz encara connectat, fins al moment qu'escafaretz l'amagatal de vòstre navigador.",
+Notatz que d'unas paginas pòdon èsser encara afichadas coma s'eratz encara connectat, fins al moment qu'escafaretz l'escondedor de vòstre navigador.",
 'welcomeuser' => 'Benvenguda, $1&nbsp;!',
 'welcomecreation-msg' => "Vòstre compte d'utilizaire es estat creat.
 Doblidetz pas de modificar [[Special:Preferences|vòstras preferéncias per {{SITENAME}}]].",
@@ -826,6 +826,7 @@ Esperatz $1 abans d’ensajar tornarmai.',
 'createacct-another-realname-tip' => 'Lo nom vertadièr es opcional.
 Se decidissètz de lo provesir, serà utilizat per atribuir a l’utilizaire sos trabalhs.',
 'pt-login' => 'Se connectar',
+'pt-login-button' => 'Se connectar',
 'pt-createaccount' => 'Crear un compte',
 'pt-userlogout' => 'Se desconnectar',
 
@@ -938,7 +939,7 @@ Lo vos caldriá far se las avètz partejats accidentalament amb qualqu'un o se v
 'preview' => 'Previsualizar',
 'showpreview' => 'Previsualizacion',
 'showlivepreview' => 'Apercebut rapid',
-'showdiff' => 'Cambiaments en cors',
+'showdiff' => 'Veire los cambiaments',
 'anoneditwarning' => "'''Atencion :''' sètz pas identificat(ada).
 Vòstra adreça IP serà enregistrada dins l’istoric d'aquesta pagina.",
 'anonpreviewwarning' => "''Sètz pas identificat. Salvar enregistrarà vòstra adreça IP dins l’istoric de las modificacions de la pagina.''",
@@ -1221,8 +1222,6 @@ Podètz veire aquesta diff ; i pòt aver mai de detalhs dins lo [{{fullurl:{{#Sp
 'revdelete-show-file-submit' => 'Òc',
 'revdelete-selected' => "'''{{PLURAL:$2|Version seleccionada|Versions seleccionadas}} de [[:$1]] :'''",
 'logdelete-selected' => "'''{{PLURAL:$1|Eveniment d'istoric seleccionat|Eveniments d'istoric seleccionats}} :'''",
-'revdelete-text' => "'''Las revisions e eveniments suprimits apareisseràn encara dins l’istoric e los jornals de la pagina, mas lor contengut textual serà inaccessible al public.'''
-D’autres administrators sus {{SITENAME}} poiràn totjorn accedir al contengut amagat e lo restablir tornamai a travèrs d'aquesta meteissa interfàcia, a mens qu’una restriccion suplementària siá mesa en plaça pels operators del site.",
 'revdelete-confirm' => "Confirmatz que volètz efectuar aquesta accion, que ne comprenètz las consequéncias, e qu'o fasètz en acòrd amb [[{{MediaWiki:Policy-url}}|las règlas]].",
 'revdelete-suppress-text' => "La supression deu èsser utilizada '''sonque''' dins los cases seguents :
 * Informacions potencialament difamatòrias
@@ -1354,13 +1353,14 @@ Podètz trobar de detalhs dins lo [{{fullurl:{{#Special:Log}}/delete|page={{FULL
 'search-file-match' => '(correspond al contengut del fichièr)',
 'search-suggest' => 'Avètz volgut dire : $1',
 'search-interwiki-caption' => 'Projèctes fraires',
-'search-interwiki-default' => '$1 resultats :',
+'search-interwiki-default' => 'Resultats de $1 :',
 'search-interwiki-more' => '(mai)',
 'search-relatedarticle' => 'Relatat',
 'searcheverything-enable' => 'Recercar dins totes los espacis de noms',
 'searchrelated' => 'relatat',
 'searchall' => 'Totes',
-'showingresults' => "Afichatge {{PLURAL:$1|d''''1''' resultat|de '''$1''' resultats}} a partir del #'''$2'''.",
+'showingresults' => 'Afichatge de <b>$1</b> resultat{{PLURAL:$1||s}} a partir del n°<b>$2</b>.',
+'showingresultsinrange' => 'Afichar çaijós fins a {{PLURAL:$1|<strong>1</strong> resultat|<strong>$1</strong> resultats}} dins la seria #<strong>$2</strong> a #<strong>$3</strong>.',
 'showingresultsnum' => "Afichatge {{PLURAL:$3|d''''1''' resultat|de '''$3''' resultats}} a partir del #'''$2'''.",
 'showingresultsheader' => "{{PLURAL:$5|Resultat '''$1'''|Resultats '''$1 - $2'''}} de '''$3''' per '''$4'''",
 'search-nonefound' => 'I a pas cap de resultat correspondent a la requèsta.',
@@ -1383,7 +1383,7 @@ Atencion, lor indexacion de contengut {{SITENAME}} benlèu es pas a jorn.',
 'prefsnologintext2' => "$1 per definir las preferéncias d'utilizaire.",
 'prefs-skin' => 'Aparéncia',
 'skin-preview' => 'Previsualizar',
-'datedefault' => 'Cap de preferéncia',
+'datedefault' => 'Pas cap de preferéncia',
 'prefs-beta' => 'Foncionalitats bèta',
 'prefs-datetime' => 'Data e ora',
 'prefs-labs' => 'Foncionalitats « labs »',
@@ -1534,7 +1534,7 @@ Tanben podètz causir de permetre a d’autres de vos contactar per vòstra pagi
 'group-bot-member' => 'Robòt',
 'group-sysop-member' => 'Administrator',
 'group-bureaucrat-member' => 'Burocrata',
-'group-suppress-member' => 'Supervisor',
+'group-suppress-member' => '{{GENDER:$1|supervisor|supervisora}}',
 
 'grouppage-user' => '{{ns:project}}:Utilizaires',
 'grouppage-autoconfirmed' => '{{ns:project}}:Utilizaires enregistrats',
@@ -1560,7 +1560,7 @@ Tanben podètz causir de permetre a d’autres de vos contactar per vòstra pagi
 'right-reupload-own' => 'Espotir un fichièr telecargat pel meteis utilizaire',
 'right-reupload-shared' => 'Espotir localament un fichièr present sus un depaus partejat',
 'right-upload_by_url' => 'Importar un fichièr dempuèi una adreça URL',
-'right-purge' => "Purgar l'amagatal de las paginas sens l'aver de confirmar",
+'right-purge' => "Purgar l'escondedor de las paginas sens l'aver de confirmar",
 'right-autoconfirmed' => 'Èsser pas afectat per las limitacions de debit ligadas a las adreças IP',
 'right-bot' => 'Èsser tractat coma un procediment automatizat',
 'right-nominornewtalk' => 'Desenclavar pas lo bendèl "Avètz de messatges novèls" al moment d\'un cambiament menor sus una pagina de discussion d\'un utilizaire',
@@ -1603,7 +1603,7 @@ Tanben podètz causir de permetre a d’autres de vos contactar per vòstra pagi
 'right-importupload' => 'Importar de paginas dempuèi un fichièr',
 'right-patrol' => 'Marcar de cambiaments coma verificats',
 'right-autopatrol' => 'Aver sos cambiaments marcats automaticament coma verificats',
-'right-patrolmarks' => 'Utilizar las foncionalitats de la patrolha dels darrièrs cambiaments',
+'right-patrolmarks' => 'Veire los marcatges de susvelhança dins los darrièrs cambiaments',
 'right-unwatchedpages' => 'Veire la lista de las paginas pas seguidas',
 'right-mergehistory' => 'Fusionar los istorics de las paginas',
 'right-userrights' => "Modificar totes los dreches d'un utilizaire",
@@ -1675,7 +1675,7 @@ Tanben podètz causir de permetre a d’autres de vos contactar per vòstra pagi
 'recentchanges-label-minor' => 'Aqueste cambiament es menor',
 'recentchanges-label-bot' => 'Aqueste cambiament es estat efectuat per un bòt.',
 'recentchanges-label-unpatrolled' => 'Aqueste cambiament es pas estat verificat encara.',
-'recentchanges-label-plusminus' => "La talha de la pagna a cambiat d'aqueste nombre d’octets.",
+'recentchanges-label-plusminus' => "La talha de la pagina a cambiat d'aqueste nombre d’octets.",
 'recentchanges-legend-heading' => "'''Legenda :'''",
 'recentchanges-legend-newpage' => '(veire tanben la [[Special:NewPages|lista de las paginas novèlas]]).',
 'rcnotefrom' => 'Çaijós las modificacions efectuadas dempuèi lo <strong>$2</strong> (fins a <strong>$1</strong> afichats).',
@@ -1698,7 +1698,7 @@ Tanben podètz causir de permetre a d’autres de vos contactar per vòstra pagi
 'rcshowhidemine' => '$1 mas modificacions',
 'rcshowhidemine-show' => 'Afichar',
 'rcshowhidemine-hide' => 'Amagar',
-'rclinks' => 'Afichar los $1 darrièrs cambiaments efectuats al cors dels $2 darrièrs jorns; $3 cambiaments menors.',
+'rclinks' => 'Afichar los $1 darrièrs cambiaments efectuats al cors dels $2 darrièrs jorns<br />$3.',
 'diff' => 'dif',
 'hist' => 'ist',
 'hide' => 'amagar',
@@ -2157,6 +2157,8 @@ Las entradas <del>barradas</del> son estadas resolgudas.',
 'wantedpages' => 'Paginas mai demandadas',
 'wantedpages-badtitle' => 'Títol invalid dins los resultats : $1',
 'wantedfiles' => 'Fichièrs desirats',
+'wantedfiletext-cat' => "Los fichièrs seguents son utilizats, mas existisson pas localament. Se se tròban sus un depaus partejat, pòdon èsser listats aicí, mentre que sián, de fach, ja disponibles. Totes aqueles falses positius seràn <del>raiats</del>. Amai, las paginas qu'intègran de fichièrs qu'existisson pas son repertoriadas dins [[:$1]].",
+'wantedfiletext-nocat' => 'Los fichièrs seguents son utilizats, mas existisson pas localament. Se se tròban sus un depaus partejat, pòdon èsser listats aicí, mentre que sián, de fach, ja disponibles. Totes aqueles falses positius seràn <del>raiats</del>.',
 'wantedtemplates' => 'Modèls demandats',
 'mostlinked' => 'Paginas mai ligadas',
 'mostlinkedcategories' => 'Categorias mai utilizadas',
@@ -2368,7 +2370,7 @@ per modificar vòstra lista de seguiment.',
 'watchlist-details' => 'I a {{PLURAL:$1|pagina|paginas}} dins vòstra lista de seguiment, sens comptar las paginas de discussion.',
 'wlheader-enotif' => 'La notificacion per corrièr electronic es activada.',
 'wlheader-showupdated' => "Las paginas que son estadas modificadas dempuèi vòstra darrièra visita son afichadas en '''gras'''.",
-'watchmethod-recent' => 'verificacion dels darrièrs cambiaments de las paginas seguidas',
+'watchmethod-recent' => 'verificacion dels darrièrs cambiaments per i trobar de paginas seguidas',
 'watchmethod-list' => 'verificacion de las paginas seguidas per de modificacions recentas',
 'watchlistcontains' => 'Vòstra lista de seguiment conten $1 {{PLURAL:$1|pagina|paginas}}.',
 'iteminvalidname' => "Problèma amb l'article « $1 » : lo nom es invalid...",
@@ -3011,7 +3013,7 @@ Salvatz-lo sus vòstre disc dur puèi importatz-lo aicí.",
 'tooltip-n-mainpage-description' => 'Anar a l’acuèlh',
 'tooltip-n-portal' => 'A prepaus del projècte',
 'tooltip-n-currentevents' => "Trobar d'entresenhas suls eveniments actuals",
-'tooltip-n-recentchanges' => 'Lista dels darrièrs cambiaments sul wiki.',
+'tooltip-n-recentchanges' => 'Lista dels darrièrs cambiaments sul wiki',
 'tooltip-n-randompage' => "Afichar una pagina a l'azard",
 'tooltip-n-help' => "L'endrech per s'assabentar.",
 'tooltip-t-whatlinkshere' => 'Lista de las paginas ligadas a aquesta',
@@ -3037,7 +3039,7 @@ Salvatz-lo sus vòstre disc dur puèi importatz-lo aicí.",
 'tooltip-minoredit' => 'Marcar mas modificacions coma un cambiament menor',
 'tooltip-save' => 'Salvar vòstras modificacions',
 'tooltip-preview' => 'Mercé de previsualizar vòstras modificacions abans de salvar!',
-'tooltip-diff' => "Permet de visualizar los cambiaments qu'avètz efectuats",
+'tooltip-diff' => "Aficha los cambiaments qu'avètz aportats al tèxte",
 'tooltip-compareselectedversions' => "Afichar las diferéncias entre doas versions d'aquesta pagina",
 'tooltip-watch' => 'Apondre aquesta pagina a vòstra lista de seguiment',
 'tooltip-watchlistedit-normal-submit' => 'Levar los títols',
@@ -3147,8 +3149,8 @@ Inscriviscatz '''PAS RES''' dedins !",
 'markaspatrolledtext' => 'Marcar aqueste article coma pas vandalizat',
 'markedaspatrolled' => 'Marcat coma pas vandalizat',
 'markedaspatrolledtext' => 'La revision seleccionada de [[:$1]] es estada coma patrolhada.',
-'rcpatroldisabled' => 'La foncion de patrolha dels darrièrs cambiaments es pas activada.',
-'rcpatroldisabledtext' => 'La foncionalitat de susvelhança dels darrièrs cambiaments es pas activada.',
+'rcpatroldisabled' => 'La foncion de relectura dels darrièrs cambiaments es pas activada.',
+'rcpatroldisabledtext' => 'La foncionalitat de relectura dels darrièrs cambiaments es actualament desactivada.',
 'markedaspatrollederror' => 'Pòt pas èsser marcat coma pas vandalizat',
 'markedaspatrollederrortext' => 'Vos cal seleccionar una version per poder la marcar coma pas vandalizada.',
 'markedaspatrollederror-noautopatrol' => 'Avètz pas lo drech de marcar vòstras pròprias modificacions coma susvelhadas.',
@@ -3736,8 +3738,8 @@ Confirmatz que desiratz tornar crear aqueste article.",
 
 # action=purge
 'confirm_purge_button' => 'Confirmar',
-'confirm-purge-top' => "Volètz refrescar aquesta pagina (purgar l'amagatal) ?",
-'confirm-purge-bottom' => "Purgar una pagina vioda l'amagatal e fòrça la darrièra version a èsser afichada.",
+'confirm-purge-top' => "Volètz refrescar aquesta pagina (purgar l'escondedor) ?",
+'confirm-purge-bottom' => "Purgar una pagina vioda l'escondedor e fòrça la darrièra version a èsser afichada.",
 
 # action=watch/unwatch
 'confirm-watch-button' => 'Confirmar',
@@ -3991,9 +3993,9 @@ Ensajatz la previsualizacion normala.',
 'revdelete-uname-unhid' => 'nom d’utilizaire afichat',
 'revdelete-restricted' => 'aplicar las restriccions als administrators',
 'revdelete-unrestricted' => 'restriccions levadas pels administrators',
-'logentry-move-move' => '$1  {{GENDER:$2|a deplaçat}} la pagina $3 cap a $4',
-'logentry-move-move-noredirect' => '$1 {{GENDER:$2|a deplaçat}} la pagina $3 cap a $4 sens daissar cap de redireccion',
-'logentry-move-move_redir' => '$1 {{GENDER:$2|a deplaçat}} la pagina $3 cap a $4 per dessús una redireccion',
+'logentry-move-move' => '$1  {{GENDER:$2|a desplaçat}} la pagina $3 cap a $4',
+'logentry-move-move-noredirect' => '$1 {{GENDER:$2|a desplaçat}} la pagina $3 cap a $4 sens daissar cap de redireccion',
+'logentry-move-move_redir' => '$1 {{GENDER:$2|a desplaçat}} la pagina $3 cap a $4 per dessús una redireccion',
 'logentry-move-move_redir-noredirect' => '$1 {{GENDER:$2|a desplaçat}} la pagina $3 cap a $4 per dessús una redireccion sens daissar cap de redireccion',
 'logentry-patrol-patrol' => '$1 {{GENDER:$2|a marcat}} la revision $4 de la pagina $3 coma relegida',
 'logentry-patrol-patrol-auto' => '$1 {{GENDER:$2|a marcat automaticament}} la revision $4 de la pagina $3 coma relegida',
index 205fa22..8b1d184 100644 (file)
@@ -1191,8 +1191,6 @@ $3ଙ୍କ ଦେଇ ଦିଆଯାଇଥିବା କାରଣ ହେଲା '
 'revdelete-show-file-submit' => 'ହଁ',
 'revdelete-selected' => "'''[[:$1]]ର {{PLURAL:$2|ବଛା ସଙ୍କଳନ|ବଛା ସଙ୍କଳନ}}:'''",
 'logdelete-selected' => "'''{{PLURAL:$1|ବଛା ଲଗ ଘଟଣା|ବଛା ଲଗ ଘଟଣାବଳୀ}}:'''",
-'revdelete-text' => "'''ଲିଭାଯାଇଥିବା ସଂସ୍କରଣ ଓ ଘଟଣାସମୂହ ଏବେ ବି ପୃଷ୍ଠାର ଇତିହାସରେ ରହିବ, କିନ୍ତୁ ଜନସାଧାରଣଙ୍କୁ ସେସବୁର କିଛି ଭାଗ ଲୁଚାଇ ରଖାଯିବ ।'''
-ଏହି {{SITENAME}}ର ବାକି ପରିଚାଳକଗଣ ଲୁଚିରହିଥିବା ବିଷୟବସ୍ତୁ ଦେଖିପାରିବେ ଓ ଅଧିକ ବାରଣ ଥିଲେ ହେଁ ସେହି ଏକା ଇଣ୍ଟରଫେସ ବ୍ୟବହାର କରି ତାହାକୁ ଆଉଥରେ ଲିଭାଯିବାରୁ ଅଟକାଇପାରିବେ ।",
 'revdelete-confirm' => 'ଦୟାକରି ଥୟ କରନ୍ତୁ ଯେ ଆପଣ ଏହା କରିବାକୁ ଚାହୁଁଛନ୍ତି, ଆପଣ ଏହାର ପରିଣାମ ଜାଣନ୍ତି ଓ ଆପଣ [[{{MediaWiki:Policy-url}}|ନୀତି]] ଅନୁସାରେ ଏହା କରୁଛନ୍ତି ।',
 'revdelete-suppress-text' => "ଦବାଇ ରଖିବା '''କେବଳ''' ଏହି ତଳଲିଖିତ କ୍ଷେତ୍ରରେ ବ୍ୟବହାର କରାଯିବ:
 * ସମ୍ଭାବିତ ଅପମାନଜଣକ ତଥ୍ୟ
@@ -1302,7 +1300,7 @@ $1",
 'prevn' => '{{PLURAL:$1|$1}}ର ଆଗରୁ',
 'nextn' => '{{PLURAL:$1|$1}} ପର',
 'prevn-title' => 'ଆଗରୁ ମିଳିଥିବା $1ଟି  {{PLURAL:$1|result|ଫଳ}}',
-'nextn-title' => 'à¬\86à¬\97ର $1à¬\9fି  {{PLURAL:$1|result|ଫଳସବୁ}}',
+'nextn-title' => 'ପର $1 {{PLURAL:$1|ଫଳାଫଳ|ଫଳାଫଳସବୁ}}',
 'shown-title' => '$1 ପ୍ରତି ପୃଷ୍ଠାର {{PLURAL:$1|ଫଳାଫଳ|ଫଳାଫଳ}} ଦେଖାଇବେ ।',
 'viewprevnext' => '($1 {{int:pipe-separator}} $2) ($3) ଟି ଦେଖିବେ',
 'searchmenu-exists' => "'''ଏହି ଉଇକିରେ \"[[:\$1]]\" ନାଆଁରେ ପୃଷ୍ଠାଟିଏ ଅଛି ।'''",
@@ -1324,7 +1322,7 @@ $1",
 'search-section' => '(ଭାଗ $1)',
 'search-suggest' => 'ଆପଣ $1 ଭାବି ଖୋଜିଥିଲେ କି?',
 'search-interwiki-caption' => 'ସାଙ୍ଗରେ ଚାଲିଥିବା ବାକି ପ୍ରକଳ୍ପସବୁ',
-'search-interwiki-default' => '$1 ଫଳାଫଳ:',
+'search-interwiki-default' => '$1 à¬°à­\81 à¬«à¬³à¬¾à¬«à¬³:',
 'search-interwiki-more' => '(ଅଧିକ)',
 'search-relatedarticle' => 'ଯୋଡ଼ା',
 'searcheverything-enable' => 'ସବୁଗୁଡ଼ିକ ନେମସ୍ପେସରେ ଖୋଜିବେ',
@@ -2344,11 +2342,11 @@ wiki: $PAGEEDITOR_WIKI
 # Delete
 'deletepage' => 'ପୃଷ୍ଠାଟି ଲିଭାଇଦେବେ',
 'confirm' => 'ନିଶ୍ଚିତ କରନ୍ତୁ',
-'excontent' => 'ଭିତର à¬­à¬¾à¬\97 à¬¥à¬¿à¬²à¬¾: $1',
-'excontentauthor' => 'ଭିତର ଭାଗରେ ଥିଲା: "$1" (ଆଉ "[[Special:Contributions/$2|$2]]" କେବଳ ଜଣେ ମାତ୍ର ଦାତା ଥିଲେ)',
-'exbeforeblank' => 'ଖାଲି କରିବା ଆଗରୁ ଭିତରେ "$1" ଥିଲା',
+'excontent' => 'ଲà­\87à¬\96ା à¬¥à¬¿à¬²à¬¾: "$1"',
+'excontentauthor' => 'ଭିତରେ ଥିଲା: "$1" (ଆଉ "[[Special:Contributions/$2|$2]]" କେବଳ ଜଣେ ଦାତା ଥିଲେ)',
+'exbeforeblank' => 'ଖାଲିକରିବା ଆଗରୁ ଭିତରେ "$1" ଥିଲା',
 'exblank' => 'ପୃଷ୍ଠାଟି ଖାଲି ଅଛି',
-'delete-confirm' => 'ଲିଭେଇବେ $1',
+'delete-confirm' => 'ଲିଭେଇବେ "$1"',
 'delete-legend' => 'ଲିଭାଇବେ',
 'historywarning' => "'''ଚେତାବନୀ:''' ଆପଣ ଲିଭାଇବାକୁ ଯାଉଥିବା ଏହି ପୃଷ୍ଠାଟିର ପାଖାପାଖି $1 {{PLURAL:$1|ଟି ସଙ୍କଳନ|ଗୋଟି ସଙ୍କଳନ}} ରହିଅଛି:",
 'confirmdeletetext' => 'ଆପଣ ଗୋଟିଏ ପୃଷ୍ଠାର ଇତିହାସ ସହ ତାହାକୁ ଲିଭାଇବାକୁ ଯାଉଛନ୍ତି ।
@@ -2448,7 +2446,7 @@ $2ଙ୍କ ଦେଇ ଶେଷଥର ହୋଇଥିବା ସଂସ୍କର
 'protect-dropdown' => '*ସାଧାରଣ ପ୍ରତିରକ୍ଷା କାରଣ
 ** ଅତି ଅଧିକ ଅପବ୍ୟବହାର
 ** ଅତି ଅଧିକ ଅଦରକାରୀ ଚିଜ ପୁରାଇବା
-** ନକରାତ୍ମକ ସମ୍ପାଦନା ତାଗିଦା
+** à¬¨à¬\95ାରାତà­\8dମà¬\95 à¬¸à¬®à­\8dପାଦନା à¬¤à¬¾à¬\97ିଦା
 ** ଅଧିକ ଦେଖାଯାଉଥିବା ପୃଷ୍ଠା',
 'protect-edit-reasonlist' => 'କିଳିବା କାରଣମାନଙ୍କର ସମ୍ପାଦନା କରିବେ',
 'protect-expiry-options' => '୧ ଘଣ୍ଟା:1 hour,ଦିନେ:1 day,ସପ୍ତାହେ:1 week,୨ ସପ୍ତାହ:2 weeks,ମସେ:1 month,୩ ମାସ:3 months,୬ ମାସ:6 months,ବର୍ଷେ:1 year,ଅସିମୀତ କାଳ:infinite',
index c6686ef..4e96a64 100644 (file)
@@ -712,6 +712,7 @@ $2',
 'suspicious-userlogout' => 'ਤੁਹਾਡੀ ਵਿਦਾਇਗੀ ਦੀ ਬੇਨਤੀ ਨਕਾਰ ਦਿੱਤੀ ਗਈ ਕਿਉਂਕਿ ਲੱਗਦਾ ਹੈ ਕਿ ਇਹ ਕਿਸੇ ਟੁੱਟੇ ਹੋਏ ਬਰਾਊਜ਼ਰ ਜਾਂ ਕੈਸ਼ ਹੋਈ ਪ੍ਰਾਕਸੀ ਤੋਂ ਭੇਜੀ ਗਈ ਸੀ।',
 'createacct-another-realname-tip' => 'ਅਸਲੀ ਨਾਂ ਚੋਣਵਾਂ ਹੈ।
 ਜੇਕਰ ਤੁਸੀਂ ਇਹ ਦਿੱਤਾ ਹੈ ਤਾਂ ਤੁਹਾਡੇ ਕੰਮ ਵਾਸਤੇ ਗੁਣ ਦੇ ਤੌਰ ਉੱਤੇ ਵਰਤਿਆ ਜਾਵੇਗਾ।',
+'pt-login-button' => 'ਲਾਗ ਇਨ',
 
 # Email sending
 'php-mail-error-unknown' => 'PHP ਦੇ ਮੇਲ() ਕਰਜ ਵਿੱਚ ਅਣਜਾਣ ਦੋਸ਼',
index 5056109..ff5585d 100644 (file)
@@ -654,9 +654,6 @@ mapaliaring maki detalle king [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPA
 'revdelete-nooldid-text' => 'Mapaliaring ala kang binieng balak a pamanalili (target revision) ba meng daptan ing gamit (function) a iti, ala yu ing mebanggit a pamanaliling iti, o magtangka kang isalikut ya ing kasalungsungan a pamanalili.',
 'revdelete-selected' => "'''{{PLURAL:$2|Mepiling bersion|Mepiling bersion}} ning [[:$1]]:'''",
 'logdelete-selected' => "'''{{PLURAL:$1|Mepiling miliari king tala/listaan|Mepiling miliari king tala/listaan}}:'''",
-'revdelete-text' => "'''Lunto la pa murin king amlat ning bulung deng meburang pamanalili ampong kapaliarian (events), oneng e ra no abusni deng malda ding mapilang dake ning karelang laman.'''
-
-Abusni da pa murin deng aliwang talapanibala (admin) king {{SITENAME}} itang laman a makasalikut, at aurung da ing pangabura na niti kapamilatan na mismu niting interface, puera namu nung ating bayung pamag-limita o pamanyabat a miyutus.",
 'revdelete-legend' => 'Mitakdang angganan/limitasiun kareng maliaring akit',
 'revdelete-hide-text' => 'Isalikut ya ing meyaliling kulitan',
 'revdelete-hide-image' => 'Isalikut ya ing laman ning simpan',
index aa79503..f75e0f2 100644 (file)
@@ -61,7 +61,9 @@ $messages = array(
 # User preference toggles
 'tog-underline' => 'Gleecher unnerleine:',
 'tog-hideminor' => 'Gleene Enneringe verschwinne losse',
-'tog-watchdefault' => 'Vun mir gennerte Ardickele watsche',
+'tog-watchdefault' => 'Vun mir gennerte Ardickele un Feils watsche',
+'tog-watchmoves' => 'Vun mir gezogene Ardickele un Feils watsche',
+'tog-watchdeletion' => 'Vun mir verwischte Ardickele un Feils watsche',
 'tog-watchlisthideown' => 'Mei Ardickele vun mei Watsch-Lischt verschwinne losse',
 'tog-watchlisthidebots' => 'Enneringe vun Bots vun mei Watsch-Lischt verschwinne losse',
 'tog-watchlisthideminor' => 'Gleene Enneringe vun mei Watsch-Lischt verschwinne losse',
@@ -120,6 +122,16 @@ $messages = array(
 'oct' => 'Okt.',
 'nov' => 'Nov.',
 'dec' => 'Dis.',
+'january-date' => '$1. Yenner',
+'february-date' => '$1. Hanning',
+'march-date' => '$1. Matz',
+'april-date' => '$1. Abril',
+'may-date' => '$1. Moi',
+'june-date' => '$1. Tschuun',
+'july-date' => '$1. Tschulei',
+'august-date' => '$1. Aagscht',
+'october-date' => '$1. Oktower',
+'december-date' => '$1. Disember',
 
 # Categories related messages
 'pagecategories' => '{{PLURAL:$1|Abdeeling|Abdeelinge}}',
@@ -280,8 +292,11 @@ Wenns des net iss, hoscht verleicht en Fehler in de Daadebank gfunne. Bitte meld
 'virus-unknownscanner' => 'Unbekannter Virus-Uffgucker:',
 
 # Login and logout pages
+'welcomeuser' => 'Wilkum, $1!',
 'yourname' => 'Yuuser-Naame:',
+'userlogin-yourname' => 'Yuusernaame',
 'yourpassword' => 'Paesswatt:',
+'userlogin-yourpassword' => 'Paesswatt',
 'yourpasswordagain' => 'Paesswatt noch eemol:',
 'yourdomainname' => 'Dei Domain:',
 'login' => 'Kumm nei',
@@ -291,11 +306,15 @@ Wenns des net iss, hoscht verleicht en Fehler in de Daadebank gfunne. Bitte meld
 'logout' => 'Geh naus',
 'userlogout' => 'Geh naus',
 'gotaccountlink' => 'Kumm nei',
+'createacct-emailrequired' => 'E-Poschd',
 'createaccountmail' => 'iwwer E-Mail',
 'createaccountreason' => 'Grund:',
-'mailmypassword' => 'Neies Paesswadd eposchde',
+'mailmypassword' => 'Paesswatt zerricksetze',
 'noemail' => 'Yuuser „$1“ hot ken E-Mail aagewwe.',
 'loginlanguagelabel' => 'Schprooch: $1',
+'pt-login' => 'Nei kumme',
+'pt-login-button' => 'Nei kumme',
+'pt-userlogout' => 'Naus geh',
 
 # Change password dialog
 'changepassword' => 'Paesswatt ennere',
@@ -308,11 +327,13 @@ Wenns des net iss, hoscht verleicht en Fehler in de Daadebank gfunne. Bitte meld
 'passwordreset' => 'Paesswatt zerricksetze',
 'passwordreset-legend' => 'Paesswatt zerricksetze',
 'passwordreset-username' => 'Yuuser-Naame:',
+'passwordreset-email' => 'E-Poschd:',
 'passwordreset-emailelement' => 'Yuusernaame: $1
 Paesswatt fer nau: $2',
 
 # Special:ChangeEmail
 'changeemail-none' => '(ken)',
+'changeemail-submit' => 'E-Poschd ennere',
 
 # Edit page toolbar
 'bold_sample' => 'Wadde fett gmarrickt',
@@ -333,6 +354,7 @@ Paesswatt fer nau: $2',
 'savearticle' => 'Blatt beilege',
 'preview' => 'Aagucke',
 'showdiff' => 'Enneringe zeige',
+'blockedtitle' => 'Yuuser iss aabunne',
 'blockednoreason' => 'ken Grund gewwe',
 'loginreqlink' => 'kumm nei',
 'newarticle' => '(Nei)',
@@ -357,8 +379,8 @@ Paesswatt fer nau: $2',
 'last' => 'Letscht',
 'page_first' => 'Aafang',
 'page_last' => 'End',
-'histfirst' => 'Eldescht',
-'histlast' => 'Letscht',
+'histfirst' => 'eldescht',
+'histlast' => 'neieschd',
 'historysize' => '({{PLURAL:$1|1 Beit|$1 Beit}})',
 'historyempty' => '(leer)',
 
@@ -369,7 +391,7 @@ Paesswatt fer nau: $2',
 'rev-showdeleted' => 'zeig',
 'revdelete-no-file' => 'Sell Feil gebt es net.',
 'revdelete-show-file-submit' => 'Ya',
-'revdelete-hide-text' => 'Text vun de Version verschwinne losse',
+'revdelete-hide-text' => 'Text vun de Version',
 'revdelete-radio-same' => '(net ennere)',
 'revdelete-radio-set' => 'Ya',
 'revdelete-radio-unset' => 'Nee',
@@ -403,7 +425,7 @@ Paesswatt fer nau: $2',
 'search-section' => '(Abschnitt $1)',
 'search-suggest' => 'Iss „$1“ gemeent?',
 'search-interwiki-caption' => 'Schweschder Projects',
-'search-interwiki-default' => '$1 Results:',
+'search-interwiki-default' => 'Results vun $1:',
 'search-interwiki-more' => '(weidere)',
 'searchall' => 'all',
 'powersearch-ns' => 'Guck uff in Blatznaame:',
@@ -435,14 +457,16 @@ Paesswatt fer nau: $2',
 'prefs-custom-css' => 'CSS vum Yuuser',
 'prefs-custom-js' => 'JavaScript vum Yuuser',
 'youremail' => 'E-Poschde:',
-'username' => 'Yuuser-Naame:',
-'uid' => 'Yuuser-ID:',
-'prefs-memberingroups' => 'Mitglied vun de {{PLURAL:$1|Yuuser-Druppe|Yuuser-Druppe}}:',
+'username' => '{{GENDER:$1|Yuuser-Naame}}:',
+'uid' => '{{GENDER:$1|Yuuser-ID}}:',
+'prefs-memberingroups' => '{{GENDER:$2|Mitglied}} vun de {{PLURAL:$1|Yuuser-Druppe|Yuuser-Druppe}}:',
 'yourlanguage' => 'Schprooch:',
 'yourgender' => 'Geschlecht:',
-'gender-female' => 'Weiblich',
+'gender-female' => 'Ich bin weiblich',
 'email' => 'E-Poschde',
 'prefs-signature' => 'Unnerschrift',
+'prefs-editor' => 'Schreiwer',
+'prefs-preview' => 'Aasicht',
 'prefs-diffs' => 'Unnerschidd vun Versione',
 
 # User rights
@@ -672,7 +696,7 @@ Paesswatt fer nau: $2',
 'emailsent' => 'E-Poscht naus gschickt',
 
 # Watchlist
-'watchlist' => 'Mei Watsch-Lischt',
+'watchlist' => 'Watsch-Lischt',
 'mywatchlist' => 'Watsch-Lischt',
 'watchlistfor2' => 'Vun $1 $2',
 'watch' => 'watsche',
@@ -737,10 +761,10 @@ Guck $2 fer e Lischt vun de letscht Leschunge.',
 'blanknamespace' => '(Bledder)',
 
 # Contributions
-'contributions' => 'Ardickele vum Yuuser',
+'contributions' => 'Ardickele vum {{GENDER:$1|Yuuser}}',
 'contributions-title' => 'Ardickele vun „$1“',
 'mycontris' => 'Mei Ardickele',
-'contribsub2' => 'Fer $1 ($2)',
+'contribsub2' => 'Fer {{GENDER:$3|$1}} ($2)',
 'uctop' => '(ewwerscht)',
 'month' => 'unn Munet:',
 'year' => 'bis Yaahr:',
index 4388f73..4bef23f 100644 (file)
@@ -864,6 +864,7 @@ Odczekaj $1 zanim ponowisz próbę.',
 'createacct-another-realname-tip' => 'Wpisanie imienia i nazwiska nie jest obowiązkowe.
 Jeśli zdecydujesz się je podać, zostaną użyte, by udokumentować Twoje autorstwo.',
 'pt-login' => 'Zaloguj się',
+'pt-login-button' => 'Zaloguj się',
 'pt-createaccount' => 'Utwórz konto',
 'pt-userlogout' => 'Wyloguj',
 
@@ -1289,8 +1290,8 @@ wybrana wersja nie istnieje lub próbowano ukryć wersję bieżącą.',
 'revdelete-show-file-submit' => 'Tak',
 'revdelete-selected' => "'''{{PLURAL:$2|Zaznaczona wersja|Zaznaczone wersje}} strony [[:$1]]:'''",
 'logdelete-selected' => "'''Zaznaczone {{PLURAL:$1|zdarzenie|zdarzenia}} z rejestru:'''",
-'revdelete-text' => "'''Usunięte wersje i czynności będą nadal widoczne w historii strony i rejestrach, ale ich treść nie będzie publicznie dostępna.'''
-Inni administratorzy {{GRAMMAR:D.lp|{{SITENAME}}}} nadal będą mieć dostęp do ukrytych treści oraz będą mogli je odtworzyć używając standardowych mechanizmów, chyba że nałożono dodatkowe ograniczenia.",
+'revdelete-text-text' => 'Usunięte wersje będą nadal widoczne w historii strony, ale niektóre fragmenty ich treści nie będą dostępne dla wszystkich.',
+'revdelete-text-file' => 'Usunięte wersje pliku będą nadal widoczne w historii pliku, ale niektóre fragmenty ich treści nie będą dostępne dla wszystkich.',
 'revdelete-confirm' => 'Potwierdź, że chcesz to zrobić zgodnie z [[{{MediaWiki:Policy-url}}|zasadami]] i że rozumiesz konsekwencje.',
 'revdelete-suppress-text' => "Ukrywanie powinno być używane '''wyłącznie''' w sytuacji:
 * Informacji, która może być zniesławieniem
@@ -1423,7 +1424,7 @@ Zazwyczaj jest to spowodowane przestarzałym linkiem do usuniętej strony. Powó
 'search-file-match' => '(odpowiada zawartości pliku)',
 'search-suggest' => 'Czy chodziło Ci o: $1',
 'search-interwiki-caption' => 'Projekty siostrzane',
-'search-interwiki-default' => 'Wyniki dla $1:',
+'search-interwiki-default' => 'Wyniki od $1:',
 'search-interwiki-more' => '(więcej)',
 'search-relatedarticle' => 'Pokrewne',
 'searcheverything-enable' => 'Szukaj we wszystkich przestrzeniach nazw',
index ce2ccc2..9bb759b 100644 (file)
@@ -999,8 +999,6 @@ Chiel a peul ancora s-ciairé costa diferensa; a peulo essje pì 'd detaj ant ë
 'revdelete-show-file-submit' => 'Bò!',
 'revdelete-selected' => "'''{{PLURAL:$2|Revision|Revision}} selessionà për [[:$1]]:'''",
 'logdelete-selected' => "'''{{PLURAL:$1|Event|Event}} dël registr selessionà:'''",
-'revdelete-text' => "Le version scancelà e j'event a së s-ciaireran sempe ant la stòria dla pàgina e ant ij registr, ma sò test al pùblich a j'andrà pì nen.'''
-J'àutri aministrator dzora a {{SITENAME}} a saran ancó sempe bon a s-ciairé ël contnù stërmà e a podran disdëscancelelo andré con la midema antërfacia, sempe che a sia nen stàita butà na restrission adissional.",
 'revdelete-confirm' => "Për piasì, ch'a confema ch'a veul fé sòn, ch'as rend cont dle conseguense, e ch'a lo fa an acòrd con [[{{MediaWiki:Policy-url}}|le régole]].",
 'revdelete-suppress-text' => "La scancelassion a dovrìa '''mach''' esse dovrà an costi cas:
 * Anformassion ch'a podrìo esse difamatòrie
index 1b94c0d..6cd0239 100644 (file)
@@ -828,8 +828,6 @@ $3 نے ''$2'' وجہ دسی اے۔",
 'revdelete-show-file-submit' => 'ہاں',
 'revdelete-selected' => "'''{{PLURAL:$2|چنی ریوین|چنیاں ریویناں}} دی [[:$1]]:'''",
 'logdelete-selected' => "'''{{PLURAL:$1|چنیا لاگ واقعہ|چنے لاگ واقعے}}:'''",
-'revdelete-text' => "'''مٹائیاں ریویناں تے واقعے صفے دے رکارڈ تے لاگ چ دسن گے، پر اودا کج حصہ عام لوکاں ل‏ی لکیا ہووے گا'''
-دوجے مکھیا  {{سائیٹناں}} ہلے وی ایس قابل نیں جے لکی لکھت نوں ویکھ سکن تے اینوں واپس لے آن دوبارہ اودوں تک جے ایدے تے ہور روکاں ناں لا دتیا جان.",
 'revdelete-confirm' => 'اے پکا کرلو جے تسیں ایہ کرنا چاندے او، تے توانوں ایدے نتیجے دا پتہ اے، تے تسیں [[{{MediaWiki:Policy-url}}|پالیسی]] تے چل کے ک رۓ او۔',
 'revdelete-suppress-text' => "دبانا اودوں ای ٹھیک اے جدوں اے تھلے دتے کۓ مسلیاں لئی ہووے۔
 * غلط جانکاری
index 20fb6e8..bf98839 100644 (file)
@@ -666,6 +666,7 @@ $1',
 لطفاً د بيا هڅې نه مخکې $1 شېبې تم شۍ.',
 'login-abort-generic' => 'غونډال کې مو ننوتل نابريالی شو - ناڅاپي بند شو',
 'loginlanguagelabel' => 'ژبه: $1',
+'pt-login-button' => 'ننوتل',
 
 # Email sending
 'user-mail-no-addy' => 'د يوې برېښليک پتې پرته د برېښليک لېږلو هڅه شوې.',
@@ -1002,7 +1003,7 @@ $1',
 'search-section' => '(برخه $1)',
 'search-suggest' => 'آيا همدا مو موخه وه: $1',
 'search-interwiki-caption' => 'خورلڼې پروژې',
-'search-interwiki-default' => '$1 پايلې:',
+'search-interwiki-default' => 'پايلې له $1 څخه:',
 'search-interwiki-more' => '(نور)',
 'search-relatedarticle' => 'اړونده',
 'searcheverything-enable' => 'په ټولو نوم-تشيالونو کې پلټل',
index 6ad3666..bc8052f 100644 (file)
@@ -324,7 +324,7 @@ $magicWords = array(
 
 $messages = array(
 # User preference toggles
-'tog-underline' => 'Sublinhar links:',
+'tog-underline' => 'Sublinhar ligações:',
 'tog-hideminor' => 'Esconder edições menores nas mudanças recentes',
 'tog-hidepatrolled' => 'Esconder edições patrulhadas nas mudanças recentes',
 'tog-newpageshidepatrolled' => 'Esconder páginas patrulhadas na lista de páginas novas',
@@ -334,7 +334,7 @@ $messages = array(
 'tog-showtoolbar' => 'Mostrar barra de edição',
 'tog-editondblclick' => 'Editar páginas quando houver um clique duplo',
 'tog-editsectiononrightclick' => 'Possibilitar a edição de secções por clique com o botão direito no título da secção',
-'tog-rememberpassword' => 'Recordar os meus dados neste browser (no máximo, durante $1 {{PLURAL:$1|dia|dias}})',
+'tog-rememberpassword' => 'Recordar os meus dados neste navegador (no máximo, durante $1 {{PLURAL:$1|dia|dias}})',
 'tog-watchcreations' => 'Adicionar as páginas e ficheiros que eu criar às minhas páginas vigiadas',
 'tog-watchdefault' => 'Adicionar as páginas e ficheiros que eu editar às minhas páginas vigiadas',
 'tog-watchmoves' => 'Adicionar as páginas e ficheiros que eu mover às minhas páginas vigiadas',
@@ -342,10 +342,10 @@ $messages = array(
 'tog-minordefault' => 'Por omissão, marcar todas as edições como menores',
 'tog-previewontop' => 'Mostrar a antevisão antes da caixa de edição',
 'tog-previewonfirst' => 'Mostrar a antevisão na primeira edição',
-'tog-enotifwatchlistpages' => 'Notificar-me por correio eletrónico quando uma página ou ficheiro vigiado for alterado',
-'tog-enotifusertalkpages' => 'Notificar-me por correio eletrónico quando a minha página de discussão é editada',
-'tog-enotifminoredits' => 'Notificar-me por correio eletrónico também sobre edições menores de páginas ou ficheiros',
-'tog-enotifrevealaddr' => 'Revelar o meu endereço de correio eletrónico nas notificações',
+'tog-enotifwatchlistpages' => 'Notificar-me por correio electrónico quando uma página ou ficheiro vigiado for alterado',
+'tog-enotifusertalkpages' => 'Notificar-me por correio electrónico quando a minha página de discussão é editada',
+'tog-enotifminoredits' => 'Notificar-me por correio electrónico também sobre edições menores de páginas ou ficheiros',
+'tog-enotifrevealaddr' => 'Revelar o meu endereço de correio electrónico nas notificações',
 'tog-shownumberswatching' => 'Mostrar o número de utilizadores a vigiar',
 'tog-oldsig' => 'Assinatura existente:',
 'tog-fancysig' => 'Tratar assinatura como texto wiki (sem link automático)',
@@ -357,7 +357,7 @@ $messages = array(
 'tog-watchlisthideliu' => 'Esconder edições de utilizadores autenticados ao listar mudanças às páginas vigiadas',
 'tog-watchlisthideanons' => 'Esconder edições de utilizadores anónimos ao listar mudanças às páginas vigiadas',
 'tog-watchlisthidepatrolled' => 'Esconder edições patrulhadas ao listar mudanças às páginas vigiadas',
-'tog-ccmeonemails' => 'Enviar-me cópias das mensagens por correio eletrónico que eu enviar a outros utilizadores',
+'tog-ccmeonemails' => 'Enviar-me cópias das mensagens por correio electrónico que eu enviar a outros utilizadores',
 'tog-diffonly' => 'Não mostrar o conteúdo da página ao comparar duas edições',
 'tog-showhiddencats' => 'Mostrar categorias ocultas',
 'tog-norollbackdiff' => 'Omitir diferenças depois de reverter edições em bloco',
@@ -366,11 +366,11 @@ $messages = array(
 
 'underline-always' => 'Sempre',
 'underline-never' => 'Nunca',
-'underline-default' => 'Usar opção padrão do tema ou do browser',
+'underline-default' => 'Usar opção padrão do tema ou do navegador',
 
 # Font style option in Special:Preferences
 'editfont-style' => 'Fonte de edição:',
-'editfont-default' => 'Fonte por omissão, do browser',
+'editfont-default' => 'Fonte por omissão, do navegador',
 'editfont-monospace' => 'Fonte monoespaçada',
 'editfont-sansserif' => 'Fonte sem serifa',
 'editfont-serif' => 'Fonte serifada',
@@ -404,7 +404,7 @@ $messages = array(
 'december' => 'dezembro',
 'january-gen' => 'janeiro',
 'february-gen' => 'fevereiro',
-'march-gen' => 'Março',
+'march-gen' => 'março',
 'april-gen' => 'abril',
 'may-gen' => 'maio',
 'june-gen' => 'junho',
@@ -444,7 +444,7 @@ $messages = array(
 'category_header' => 'Páginas na categoria "$1"',
 'subcategories' => 'Subcategorias',
 'category-media-header' => 'Multimédia na categoria "$1"',
-'category-empty' => "''Esta categoria não contém atualmente nenhuma página ou ficheiro multimédia.''",
+'category-empty' => "''Esta categoria não contém actualmente nenhuma página ou ficheiro multimédia.''",
 'hidden-categories' => '{{PLURAL:$1|Categoria oculta|Categorias ocultas}}',
 'hidden-category-category' => 'Categorias ocultas',
 'category-subcat-count' => '{{PLURAL:$2|Esta categoria só contém a seguinte subcategoria.|Esta categoria contém {{PLURAL:$1|a seguinte subcategoria|as seguintes $1 subcategorias}} (de um total de $2).}}',
@@ -456,7 +456,7 @@ $messages = array(
 'listingcontinuesabbrev' => 'cont.',
 'index-category' => 'Páginas indexadas',
 'noindex-category' => 'Páginas não indexadas',
-'broken-file-category' => 'Páginas com links quebrados para ficheiros',
+'broken-file-category' => 'Páginas com ligações quebradas para ficheiros',
 
 'about' => 'Sobre',
 'article' => 'Página de conteúdo',
@@ -485,13 +485,13 @@ $messages = array(
 'vector-action-move' => 'Mover',
 'vector-action-protect' => 'Proteger',
 'vector-action-undelete' => 'Restaurar',
-'vector-action-unprotect' => 'Alterar proteção',
+'vector-action-unprotect' => 'Alterar protecção',
 'vector-view-create' => 'Criar',
 'vector-view-edit' => 'Editar',
 'vector-view-history' => 'Ver histórico',
 'vector-view-view' => 'Ler',
 'vector-view-viewsource' => 'Ver fonte',
-'actions' => 'Ações',
+'actions' => 'Acções',
 'namespaces' => 'Espaços nominais',
 'variants' => 'Variantes',
 
@@ -506,9 +506,9 @@ $messages = array(
 'searcharticle' => 'Ir',
 'history' => 'Histórico',
 'history_short' => 'Histórico',
-'updatedmarker' => 'atualizado desde a minha última visita',
+'updatedmarker' => 'actualizado desde a minha última visita',
 'printableversion' => 'Versão para impressão',
-'permalink' => 'Link permanente',
+'permalink' => 'Ligação permanente',
 'print' => 'Imprimir',
 'view' => 'Ver',
 'edit' => 'Editar',
@@ -867,6 +867,7 @@ Aguarde $1 antes de tentar novamente, por favor.',
 'createacct-another-realname-tip' => 'O fornecimento do nome verdadeiro é opcional.
 Se optar por revelá-lo, ele será utilizado para atribuir-lhe crédito pelo seu trabalho.',
 'pt-login' => 'Autenticação',
+'pt-login-button' => 'Iniciar sessão',
 'pt-createaccount' => 'Criar uma conta',
 'pt-userlogout' => 'Sair',
 
@@ -1298,8 +1299,9 @@ Pode ver a diferença entre revisões; encontrará detalhes no [{{fullurl:{{#Spe
 'revdelete-show-file-submit' => 'Sim',
 'revdelete-selected' => "'''{{PLURAL:$2|Edição selecionada|Edições selecionadas}} de [[:$1]]:'''",
 'logdelete-selected' => "'''{{PLURAL:$1|Evento do registo selecionado|Eventos do registo selecionados}}:'''",
-'revdelete-text' => '<strong>Edições e operações eliminadas continuarão a aparecer no histórico da página e nos registos, mas partes do seu conteúdo estarão inacessíveis ao público.</strong>
-Outros administradores da {{SITENAME}} continuarão a poder aceder ao conteúdo escondido e podem repô-lo através desta mesma interface, a menos que restrições adicionais sejam definidas.',
+'revdelete-text-text' => 'Revisões eliminadas ainda aparecerão no histórico da página, mas parte do seu conteúdo estará inacessível para o público.',
+'revdelete-text-file' => 'Versões eliminadas do ficheiro ainda aparecerão no histórico da página, mas parte do seu conteúdo estará inacessível para o público.',
+'revdelete-text-others' => 'Outros administradores em {{SITENAME}} podem aceder ao conteúdo oculto e torná-lo visível novamente através desta mesma interface, a menos que sejam definidas restrições adicionais.',
 'revdelete-confirm' => 'Por favor confirme que pretende executar esta operação, que compreende as suas consequências e que o faz em concordância com as [[{{MediaWiki:Policy-url}}|políticas e recomendações]].',
 'revdelete-suppress-text' => "A supressão '''só''' deverá ser usada nos seguintes casos:
 * Informação potencialmente caluniosa, difamatória ou injuriosa
@@ -2744,7 +2746,7 @@ $1',
 'sp-contributions-newbies-title' => 'Contribuições de contas novas',
 'sp-contributions-blocklog' => 'registo de bloqueios',
 'sp-contributions-deleted' => 'contribuições eliminadas',
-'sp-contributions-uploads' => 'uploads',
+'sp-contributions-uploads' => 'carregamentos',
 'sp-contributions-logs' => 'registos',
 'sp-contributions-talk' => 'discussão',
 'sp-contributions-userrights' => 'gestão de privilégios de utilizador',
@@ -4134,13 +4136,13 @@ Em conjunto com este programa deve ter recebido [{{SERVER}}{{SCRIPTPATH}}/COPYIN
 'dberr-cachederror' => 'A seguinte página é uma cópia em cache da página pedida e pode não estar atualizada.',
 
 # HTML forms
-'htmlform-invalid-input' => 'Existem problemas com alguns dos dados introduzidos',
+'htmlform-invalid-input' => 'Existem problemas com alguns dos dados introduzidos.',
 'htmlform-select-badoption' => 'O valor que especificou não é uma opção válida.',
 'htmlform-int-invalid' => 'O valor que especificou não é um inteiro.',
 'htmlform-float-invalid' => 'O valor que especificou não é um número.',
-'htmlform-int-toolow' => 'O valor que especificou é inferior ao mínimo de $1',
-'htmlform-int-toohigh' => 'O valor que especificou é superior ao máximo de $1',
-'htmlform-required' => 'Este valor é necessário',
+'htmlform-int-toolow' => 'O valor que especificou é inferior ao mínimo de $1.',
+'htmlform-int-toohigh' => 'O valor que especificou é superior ao máximo de $1.',
+'htmlform-required' => 'Este valor é necessário.',
 'htmlform-submit' => 'Enviar',
 'htmlform-reset' => 'Desfazer alterações',
 'htmlform-selectorother-other' => 'Outros',
index 49b4913..237cb0a 100644 (file)
@@ -875,6 +875,7 @@ Por favor aguarde $1 antes de tentar novamente.',
 'createacct-another-realname-tip' => 'O nome verdadeiro é opcional.
 Se você optar por fornecê-lo, este nome será utilizado para dar ao usuário a atribuição de seu trabalho.',
 'pt-login' => 'Entrar',
+'pt-login-button' => 'Entrar',
 'pt-createaccount' => 'Criar conta',
 
 # Email sending
@@ -1298,8 +1299,10 @@ Você pode ver esta comparação; detalhes podem ser encontrados no [{{fullurl:{
 'revdelete-show-file-submit' => 'Sim',
 'revdelete-selected' => "'''{{PLURAL:$2|Edição selecionada|Edições selecionadas}} de [[:$1]]:'''",
 'logdelete-selected' => "'''{{PLURAL:$1|Evento de registro selecionado|Eventos de registro selecionados}}:'''",
-'revdelete-text' => "'''Revisões eliminadas e eventos continuarão aparecendo no histórico da página e nos registros, apesar de o seu conteúdo textual estar inacessível ao público.'''
-Outros administradores no {{SITENAME}} continuarão podendo acessar ao conteúdo escondido e restaurá-lo através desta mesma ''interface'', a menos que uma restrição adicional seja definida.",
+'revdelete-text-text' => 'Revisões apagadas continuarão a aparecer na página de histórico, mas parte de seus conteúdos estarão inacessíveis ao público.',
+'revdelete-text-file' => 'Versões dos arquivos apagados continuarão a aparecer no arquivo de histórico, mas parte de seus conteúdos estarão inacessíveis ao publico.',
+'logdelete-text' => 'Eventos de log apagados continuarão a aparecer nos logs, mas parte de seus conteúdos estarão inacessíveis ao público.',
+'revdelete-text-others' => 'Outros administrador na {{SITENAME}} continuarão capazes de acessar o conteúdo oculto e desocultá-lo pela mesma interface, a menos que restrições adicionais tenha sido feitas.',
 'revdelete-confirm' => 'Por favor confirme que pretende executar esta ação, que compreende as suas consequências e que o faz em concordância com as [[{{MediaWiki:Policy-url}}|políticas e recomendações]].',
 'revdelete-suppress-text' => "A supressão deverá ser usada '''apenas''' para os seguintes casos:
 * Informação potencialmente difamatória
@@ -2286,12 +2289,15 @@ Entradas <del>riscadas</del> foram resolvidas.',
 'deadendpagestext' => 'As seguintes páginas não contêm links para outras páginas no wiki {{SITENAME}}.',
 'protectedpages' => 'Páginas protegidas',
 'protectedpages-indef' => 'Proteções infinitas apenas',
+'protectedpages-summary' => 'Esta página lista as páginas existentes que estão protegidas no momento. Para uma lista de títulos que estão protegidos desde a criação, veja [[{{#special:ProtectedTitles}}]].',
 'protectedpages-cascade' => 'Apenas proteções progressivas',
 'protectedpages-noredirect' => 'Ocultar redirecionamentos',
 'protectedpagesempty' => 'Neste momento, nenhuma das páginas está protegida com estes parâmetros.',
 'protectedpages-timestamp' => 'Data e hora',
 'protectedpages-page' => 'Página',
 'protectedpages-expiry' => 'Expira',
+'protectedpages-performer' => 'Protegendo usuário',
+'protectedpages-params' => 'Parâmetros de proteção.',
 'protectedpages-reason' => 'Motivo',
 'protectedpages-unknown-timestamp' => 'Desconhecido',
 'protectedpages-unknown-performer' => 'Usuário desconhecido',
@@ -2482,6 +2488,7 @@ Futuras modificações em tal página e páginas de discussão relacionadas ser
 'watchmethod-list' => 'verificando páginas vigiadas para edições recentes',
 'watchlistcontains' => 'Sua lista de páginas vigiadas contém $1 {{PLURAL:$1|página|páginas}}.',
 'iteminvalidname' => "Problema com item '$1', nome inválido...",
+'wlnote2' => 'A seguir estão as mudanças nas últimas {{PLURAL:$1|hora|<strong>$1</strong> houras}}, a partir de $2, $3.',
 'wlshowlast' => 'Ver últimas $1 horas $2 dias $3',
 'watchlist-options' => 'Opções da lista de páginas vigiadas',
 
@@ -2571,7 +2578,7 @@ A eliminação de tais páginas foi restrita, a fim de se evitarem problemas aci
 'delete-warning-toobig' => 'Esta página possui um longo histórico de edições, com mais de $1 {{PLURAL:$1|edição|edições}}.
 Eliminá-la poderá causar problemas na base de dados de {{SITENAME}};
 prossiga com cuidado.',
-'deleting-backlinks-warning' => "'''Cuidado:''' Outras páginas se ligam ou redirecionam para a página que você está prestes a deletar.",
+'deleting-backlinks-warning' => "'''Cuidado:'''[[Special:WhatLinksHere/{{FULLPAGENAME}}|Outras páginas]] se ligam ou redirecionam para a página que você está prestes a deletar.",
 
 # Rollback
 'rollback' => 'Reverter edições',
@@ -3053,6 +3060,7 @@ Acesse [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] e [/
 'thumbnail_image-type' => 'Tipo de imagem não suportado',
 'thumbnail_gd-library' => 'Configuração da biblioteca GD incompleta: função $1 não encontrada',
 'thumbnail_image-missing' => 'Arquivo aparentemente inexistente: $1',
+'thumbnail_image-failure-limit' => 'Houveram muitas tentativas falhas recentemente ($1 ou mais) de criação desta miniatura. Por favor, tente novamente mais tarde.',
 
 # Special:Import
 'import' => 'Importar páginas',
index 9b83b36..a5e12d0 100644 (file)
  * @author Umherirrender
  * @author Urhixidur
  * @author Usarker
+ * @author V.narsikar
  * @author Verdy p
  * @author Vinhtantran
  * @author Vivaelcelta
@@ -1579,8 +1580,10 @@ This message is used in html.
 'createacct-another-realname-tip' => "{{doc-singularthey}}
 Used on the account creation form when creating another user's account. Similar to {{msg-mw|prefs-help-realname}}.
 {{Identical|Real name attribution}}",
-'pt-login' => "Shown as the caption of the button at [[Special:UserLogin]], and also to anonymous users in the upper right corner of the page when they can't create an account (otherwise the message {{msg-mw|nav-login-createaccount}} is shown there)
+'pt-login' => "Shown to anonymous users in the upper right corner of the page when they can't create an account (otherwise the message {{msg-mw|nav-login-createaccount}} is shown there).
 {{Identical|Log in}}",
+'pt-login-button' => 'Shown as the caption of the button at [[Special:UserLogin]].
+{{Identical|Log in}}',
 'pt-createaccount' => 'Used on the top of the page for logged out users, where it appears next to {{msg-mw|login}}, so consider making them similar.
 {{Identical|Create account}}',
 'pt-userlogout' => '{{Doc-actionlink}}
@@ -2491,8 +2494,32 @@ Parameters:
 * $1 - number of log events
 See also:
 * {{msg-mw|Revdelete-selected}}',
-'revdelete-text' => '{{RevisionDelete}}
-This is the introduction explaining the feature.',
+'revdelete-text-text' => '{{RevisionDelete}}
+This is the introduction explaining the feature.
+
+See also:
+* {{msg-mw|Revdelete-text-file}}
+* {{msg-mw|Logdelete-text}}
+* {{msg-mw|Revdelete-text-others}}',
+'revdelete-text-file' => '{{RevisionDelete}}
+This is the introduction explaining the feature.
+
+See also:
+* {{msg-mw|Revdelete-text-text}}
+* {{msg-mw|Logdelete-text}}
+* {{msg-mw|Revdelete-text-others}}',
+'logdelete-text' => '{{RevisionDelete}}
+This is the introduction explaining the feature.
+
+See also:
+* {{msg-mw|Revdelete-text-text}}
+* {{msg-mw|Revdelete-text-file}}
+* {{msg-mw|Revdelete-text-others}}',
+'revdelete-text-others' => '{{RevisionDelete}}
+This message is shown after one of:
+* {{msg-mw|Revdelete-text-text}}
+* {{msg-mw|Revdelete-text-file}}
+* {{msg-mw|Logdelete-text}}',
 'revdelete-confirm' => 'This message is a part of the [[mw:RevisionDelete|RevisionDelete]] feature.
 
 Refers to {{msg-mw|Policy-url}}.
index 6844d02..834e10e 100644 (file)
@@ -1178,8 +1178,6 @@ Kay wakin kayta qhawayta atinkim; astawanchá rikunkiman [{{fullurl:{{#Special:L
 'revdelete-show-file-submit' => 'Arí',
 'revdelete-selected' => "'''{{PLURAL:$2|Akllasqa llamk'apusqa|Akllasqa llamk'apusqakuna}} [[:$1]]-manta:'''",
 'logdelete-selected' => "'''{{PLURAL:$1|Akllasqa tukusqa|Akllasqa tukusqakuna}} hallch'api:'''",
-'revdelete-text' => "'''Qullusqa llamk'apusqakunaqa p'anqap wiñay kawsayninpi hallch'ankunapipas paqarinqaraqmi, samiqninpa rakinkunataq manam uyanalla qhawanapaqchu.'''
-{{SITENAME}}pi huk kamachiqkunaqa p'anqap pakasqa samiqninta qhawaspa qullusqa kaymanta kutichiyta atinkuraqmi kay kaqlla uyapuratam llamk'achispa, kay wikip kamariqninkuna mana huk saywachanakunata tiyachiptinqa.",
 'revdelete-confirm' => 'Ama hina kaspa, takyachiy munayniykita, qatiqninkunata riqsiyniykita, [[{{MediaWiki:Policy-url}}|kawpaykama]] rurayniykitapas.',
 'revdelete-suppress-text' => "Pakay ruranata '''kaylla kaptin''' llamk'achiy:
 * K'amiqchá willakuna
index 6ddfd10..dc62a32 100644 (file)
@@ -432,32 +432,66 @@ Resguarda ch'entginas paginas pon tuttina anc vesair or sco sche ti eras annunzi
 'welcomecreation-msg' => "Tes conto è vegnì creà. 
 N'emblida betg da midar tias [[Special:Preferences|{{SITENAME}} preferenzas]].",
 'yourname' => "Num d'utilisader",
+'userlogin-yourname-ph' => "Endatescha tes num d'utilisader",
+'createacct-another-username-ph' => "Endatescha in num d'utilisader",
 'yourpassword' => 'pled-clav',
+'userlogin-yourpassword' => 'Pled-clav',
+'userlogin-yourpassword-ph' => 'Endatescha tes pled-clav',
+'createacct-yourpassword-ph' => 'Endatescha in pled-clav',
 'yourpasswordagain' => 'repeter pled-clav',
+'createacct-yourpasswordagain' => 'Confermar il pled-clav',
+'createacct-yourpasswordagain-ph' => 'Endatescha il pled-clav anc ina giada',
 'remembermypassword' => "S'annunziar permanantamain sin quest computer (per maximalmain $1 {{PLURAL:$1|di|dis}})",
+'userlogin-remembermypassword' => 'Restar annunzià',
+'userlogin-signwithsecure' => 'Duvrar ina connexiun segira',
 'yourdomainname' => 'Vossa domain',
 'password-change-forbidden' => 'Ti na pos betg midar pleds-clav sin quest vichi.',
 'externaldberror' => "U ch'i è capità ina errur cun l'autentificaziun externa u che ti na dastgas betg actualisar tes conto extern.",
 'login' => "T'annunziar",
-'nav-login-createaccount' => "T'annunziar / registrar",
+'nav-login-createaccount' => "T'annunziar / crear in conto",
 'loginprompt' => "Ti stos avair '''activà ils cookies''' per pudair t'annunziar tar {{SITENAME}}.",
-'userlogin' => "T'annunziar / registrar",
+'userlogin' => "T'annunziar / crear in conto",
 'userloginnocreate' => "T'annunziar",
 'logout' => 'Sortir',
 'userlogout' => 'sortir',
 'notloggedin' => "Betg s'annunzià",
+'userlogin-noaccount' => 'Anc nagin conto?',
+'userlogin-joinproject' => 'Far part da {{SITENAME}}',
 'nologin' => "Anc nagin conto? '''$1'''.",
 'nologinlink' => "Crear in conto d'utilisader",
 'createaccount' => "Crear in conto d'utilisader",
 'gotaccount' => "Gia in conto d'utilisader? '''$1'''.",
 'gotaccountlink' => "T'annunziar",
 'userlogin-resetlink' => "Emblidà tias datas per s'annunziar?",
+'userlogin-resetpassword-link' => 'Has emblidà tes pled-clav?',
+'userlogin-helplink' => "[[{{MediaWiki:helplogin-url}}|Agid tar l'annunzia]]",
+'userlogin-loggedin' => "Ti es gia t'annunzià sco {{GENDER:$1|$1}}.
+Dovra il suandant formular per t'annunziar cun in auter conto.",
+'userlogin-createanother' => 'Crear in auter conto',
+'createacct-join' => 'Endatescha tias infurmaziuns sutvart.',
+'createacct-another-join' => 'Endatescha sutvart las infurmaziuns dal nov conto.',
+'createacct-emailrequired' => 'Adressa dad e-mail',
+'createacct-emailoptional' => 'Adressa dad e-mail (opziunal)',
+'createacct-email-ph' => "Endatescha ti'adressa dad e-mail",
+'createacct-another-email-ph' => "Endatescha in'adressa dad e-mail",
 'createaccountmail' => "Dovrar per il mument in pled-clav casual ed inviar el a l'adressa d'e-mail inditgada.",
+'createacct-realname' => 'Num real (opziunal)',
 'createaccountreason' => 'Motiv:',
+'createacct-reason' => 'Motiv',
+'createacct-reason-ph' => 'Tes motiv per crear in auter conto',
+'createacct-captcha' => 'Controlla da segirezza',
+'createacct-imgcaptcha-ph' => 'Endatescha il text che vesas survart',
+'createacct-submit' => 'Crear tes conto',
+'createacct-another-submit' => 'Crear in auter conto',
+'createacct-benefit-heading' => '{{SITENAME}} exista grazia a persunas sco ti.',
+'createacct-benefit-body1' => '{{PLURAL:$1|modificaziun|modificaziuns}}',
+'createacct-benefit-body2' => '{{PLURAL:$1|pagina|paginas}}',
+'createacct-benefit-body3' => '{{PLURAL:$1|contribuent activ|contribuents activs}}',
 'badretype' => 'Ils dus pleds-clav na corrispundan betg.',
 'userexists' => "Quest num d'utilisader vegn gia duvrà. 
 Tscherna per plaschair in'auter.",
 'loginerror' => "Sbagl cun t'annunziar",
+'createacct-error' => 'Errur cun crear il conto',
 'createaccounterror' => 'Betg pussaivel da crear in conto: $1',
 'nocookiesnew' => "Il conto da l'utilisader è vegnì creà, ti es dentant betg t'annunzià. 
 {{SITENAME}} utilisescha cookies per che utilisaders pon s'annunziar. 
@@ -521,6 +555,8 @@ Spetga $1 avant ch'empruvar anc ina giada.",
 'login-abort-generic' => 'Annunzia senza success - Annullà',
 'loginlanguagelabel' => 'Lingua: $1',
 'suspicious-userlogout' => "Tia dumonda per partir è vegnida refusada perquai ch'i para ch'ella è vegnida tramessa d'in navigatur che funcziuna betg correctamain u d'in proxy da cache.",
+'createacct-another-realname-tip' => "Il num real è opziunal.
+Sche ti l'inditgeschas, vegn el duvrà per attribuir las contribuziuns.",
 
 # Email sending
 'php-mail-error-unknown' => 'Errur nunenconuschenta en la funcziun mail() da PHP',
@@ -907,8 +943,6 @@ Ti pos vesair quest diff; detagls pon vegnir chattads en il [{{fullurl:{{#Specia
 'revdelete-show-file-submit' => 'Gea',
 'revdelete-selected' => "'''{{PLURAL:$2|Versiun tschernida|Versiuns tschernidas}} da [[:$1]]:'''",
 'logdelete-selected' => "'''{{PLURAL:$1|Element dal protocol tschernì|Elements dal protocol tschernids}}:'''",
-'revdelete-text' => "'''Versiuns ed ocurrenzas stizzadas cumparan era vinavant en la cronologia ed en ils protocols, dentant èn parts dal cuntegn betg accessibels al public.'''
-Auters administraturs sin {{SITENAME}} vegnan tuttina ad avair access al cuntegn zuppentà e pon restaurar puspè la pagina, sch'i na vegnan betg definidas restricziuns supplementaras.",
 'revdelete-confirm' => 'Confermescha che ti vuls far quai, che ti chapeschas las consequenzas e che ti fas quai en accordanza cun [[{{MediaWiki:Policy-url}}|las directivas]].',
 'revdelete-suppress-text' => "Ti duessas '''be''' supprimer en quests cas: 
 * Infurmaziuns offendentas
@@ -1023,7 +1057,7 @@ Detagls pon vegnir chattads en il [{{fullurl:{{#Special:Log}}/delete|page={{FULL
 'shown-title' => 'Mussar $1 {{PLURAL:$1|resultat|resultats}} per pagina',
 'viewprevnext' => 'Mussar ($1 {{int:pipe-separator}} $2) ($3).',
 'searchmenu-exists' => "'''Igl exista ina pagina cun il num \"[[:\$1]] sin questa vichi\"'''",
-'searchmenu-new' => "'''Crear la pagina \"[[:\$1]]\" sin questa vichi!'''",
+'searchmenu-new' => '<strong>Crear la pagina «[[:$1]]» sin quest vichi!</strong> {{PLURAL:$2|0=|Vesair er la pagina chattada cun tia tschertga.|Vesair er las resultats da tia tschertga.}}',
 'searchprofile-articles' => 'Paginas da cuntegn',
 'searchprofile-project' => 'Agid e paginas dal project',
 'searchprofile-images' => 'Multimedia',
@@ -1337,15 +1371,28 @@ Tia adressa dad e-mail na vegn betg mussada sche auters utilisaders ta contactes
 'recentchanges-label-minor' => 'Quai è ina pitschna modificaziun',
 'recentchanges-label-bot' => 'Questa modificaziun è vegnida exequida dad in bot',
 'recentchanges-label-unpatrolled' => "Questa midada n'è anc betg vegnida controllada",
+'recentchanges-legend-heading' => "'''Legenda:'''",
 'recentchanges-legend-newpage' => '(vesair era la [[Special:NewPages|glista da novas paginas]])',
-'rcnotefrom' => "Midadas dapi '''$2''' (maximalmain '''$1''' vegnan mussads).",
-'rclistfrom' => 'Mussar las novas midadas entschavend cun $1',
+'rcnotefrom' => 'I vegnan mussadas las midadas a partir da las <strong>$4</strong> dals <strong>$3</strong> (maximalmain <strong>$1</strong>).',
+'rclistfrom' => 'Mussar las novas midadas a partir da las $2 dals $3',
 'rcshowhideminor' => '$1 midadas pitschnas',
+'rcshowhideminor-show' => 'Mussar',
+'rcshowhideminor-hide' => 'Zuppentar',
 'rcshowhidebots' => '$1 bots',
+'rcshowhidebots-show' => 'Mussar',
+'rcshowhidebots-hide' => 'Zuppentar',
 'rcshowhideliu' => '$1 utilisaders annunziads',
+'rcshowhideliu-show' => 'Mussar',
+'rcshowhideliu-hide' => 'Zuppentar',
 'rcshowhideanons' => '$1 utilisaders anonims',
+'rcshowhideanons-show' => 'Mussar',
+'rcshowhideanons-hide' => 'Zuppentar',
 'rcshowhidepatr' => '$1 midadas controlladas',
+'rcshowhidepatr-show' => 'Mussar',
+'rcshowhidepatr-hide' => 'Zuppentar',
 'rcshowhidemine' => '$1 mias midadas',
+'rcshowhidemine-show' => 'Mussar',
+'rcshowhidemine-hide' => 'Zuppentar',
 'rclinks' => 'Mussar las davosas $1 midadas dals ultims $2 dis<br />$3',
 'diff' => 'diff',
 'hist' => 'ist',
@@ -3501,6 +3548,7 @@ Ti duessas avair retschavì [{{SERVER}}{{SCRIPTPATH}}/COPYING ina copia da la GN
 
 # Special:SpecialPages
 'specialpages' => 'Paginas spezialas',
+'specialpages-note-top' => 'Legenda',
 'specialpages-note' => '* Paginas spezialas normalas.
 * <span class="mw-specialpagerestricted">Paginas spezialas restrenschidas.</span>',
 'specialpages-group-maintenance' => 'Rapports da mantegnamant',
@@ -3610,8 +3658,8 @@ Ti duessas avair retschavì [{{SERVER}}{{SCRIPTPATH}}/COPYING ina copia da la GN
 'logentry-newusers-create2' => 'Il conto $3 è vegnì creà da $1',
 'logentry-newusers-autocreate' => 'Il conto $1 è vegnì creà automaticamain',
 'logentry-rights-rights' => '$1 ha midà la commembranza da gruppas per $3 da $4 a $5',
-'logentry-rights-rights-legacy' => '$1 ha midà la commembranza da gruppas per $3',
-'logentry-rights-autopromote' => '$1 è vegnì promovì automaticamain da $4 a $5',
+'logentry-rights-rights-legacy' => '$1 ha {{GENDER:$2|midà}} la commembranza da gruppas per $3',
+'logentry-rights-autopromote' => '$1 è vegnì {{GENDER:$2|promovì|promovida}} automaticamain da $4 a $5',
 'rightsnone' => '(nagins)',
 
 # Feedback
index 98b45e3..3fec820 100644 (file)
@@ -837,6 +837,7 @@ Vă rugăm să așteptați $1 până să reîncercați.',
 'createacct-another-realname-tip' => 'Numele real este opțional.
 Dacă decideți furnizarea sa, acesta va fi folosit pentru a atribui utilizatorului munca sa.',
 'pt-login' => 'Autentificare',
+'pt-login-button' => 'Autentificare',
 'pt-createaccount' => 'Creare cont',
 'pt-userlogout' => 'Închide sesiunea',
 
@@ -1262,7 +1263,10 @@ funcție, fie versiunea specificată nu există, ori sunteți pe cale să ascund
 'revdelete-show-file-submit' => 'Da',
 'revdelete-selected' => "'''{{PLURAL:$2|Versiunea aleasă|Versiunile alese}} pentru [[:$1]]:'''",
 'logdelete-selected' => "'''{{PLURAL:$1|Revizia aleasă|Reviziile alese}}:'''",
-'revdelete-text' => "'''Versiunile șterse vor apărea în istoricul paginii, dar conținutul lor nu va fi accesibil publicului.''' Administratorii {{SITENAME}} pot accesa conținutul șters și îl pot recupera prin aceeași interfață, dacă nu este impusă altă restricție de către operatorii sitului.",
+'revdelete-text-text' => 'Versiunile șterse vor continua să fie vizibile în istoricul paginii, însă anumite părți ale conținutului acestora vor fi inaccesibile publicului.',
+'revdelete-text-file' => 'Versiunile șterse ale fișierului vor continua să fie vizibile în istoricul fișierului, însă anumite părți ale conținutului acestora vor fi inaccesibile publicului.',
+'logdelete-text' => 'Evenimentele șterse ale jurnalului vor continua să fie vizibile în jurnale, însă anumite părți ale conținutului acestora vor fi inaccesibile publicului.',
+'revdelete-text-others' => 'Alți administratori de la {{SITENAME}} vor avea acces în continuare la conținutul ascuns și îl vor putea restaura prin intermediul acestei interfețe, cu excepția cazurilor în care nu sunt activate și restricții suplimentare.',
 'revdelete-confirm' => 'Vă rugăm să confirmați că intenționați să faceți acest lucru, că înțelegeți consecințele și că faceți asta în conformitate cu [[{{MediaWiki:Policy-url}}|politica]].',
 'revdelete-suppress-text' => "Suprimarea trebuie folosită '''doar''' în următoarele cazuri:
 * Informații potențial calomnioase
@@ -1397,7 +1401,7 @@ Detalii se pot găsi în [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE
 'search-file-match' => '(se regăsește în conținutul fișierului)',
 'search-suggest' => 'V-ați referit la: $1',
 'search-interwiki-caption' => 'Proiecte înrudite',
-'search-interwiki-default' => '$1 rezultate:',
+'search-interwiki-default' => 'Rezultate de la $1:',
 'search-interwiki-more' => '(mai mult)',
 'search-relatedarticle' => 'Relaționat',
 'searcheverything-enable' => 'Caută în toate spațiile de nume',
@@ -2525,7 +2529,7 @@ Accesați $2 pentru o listă cu elementele recent șterse.',
 'delete-warning-toobig' => 'Această pagină are un istoric al modificărilor mult prea mare, cu mai mult de $1 {{PLURAL:$1|versiune|versiuni|de versiuni}}.
 Ștergerea sa poate afecta baza de date a sitului {{SITENAME}};
 acționați cu precauție.',
-'deleting-backlinks-warning' => "'''Atenție:''' Alte pagini se leagă sau sunt transcluse din pagina pe care doriți să o ștergeți.",
+'deleting-backlinks-warning' => "'''Atenție:''' [[Special:WhatLinksHere/{{FULLPAGENAME}}|Alte pagini]] se leagă sau transclud pagina pe care doriți să o ștergeți.",
 
 # Rollback
 'rollback' => 'Editări de revenire',
index 39e4423..f2a41f2 100644 (file)
@@ -998,8 +998,6 @@ Tu puè vedè ste differenze; pò essere ca stonne cchiù 'mbormaziune jndr'à l
 'revdelete-show-file-submit' => 'Sìne',
 'revdelete-selected' => "'''{{PLURAL:$2|Revisiona selezionete|Revisiune selezionete}} de [[:$1]]:'''",
 'logdelete-selected' => "'''{{PLURAL:$1|Fatte de l'archivije selezionete|Fatte de l'archivije selezionete}}:'''",
-'revdelete-text' => "'''Le revisiune scangellete e le evende iessene angore jndr'à storie d'a pàgene e jndr'à l'archivije, ma stuezze d'u condenute lore pò essere inaccessibbele a 'u pubbleche.'''
-Otre amministrature sus a {{SITENAME}}ponne angore trasè jndr'à 'u condenute scunnute e 'u ponne scangellà 'n'otra vote ausanne st'inderfacce, senze 'mbostà otre restriziune.",
 'revdelete-confirm' => 'Pe piacere conferme ca tu vuè ccu face sta cose, ce tu è capite le conseguenze e ce quidde ca ste face jè in accorde cu le [[{{MediaWiki:Policy-url}}|reghele]] de Uicchipèdie.',
 'revdelete-suppress-text' => "'A soppressione adda essere ausate '''sulamende''' jndr'à le case seguende:
 * 'Mbormaziune potenzialmende offenzive
index 6cb525d..9ed0b92 100644 (file)
@@ -987,6 +987,7 @@ $2',
 'createacct-another-realname-tip' => 'Настоящее имя (необязательное поле).
 Если вы укажете его, то оно будет использовано для того, чтобы показать, кем была внесена правка страницы.',
 'pt-login' => 'Войти',
+'pt-login-button' => 'Войти',
 'pt-createaccount' => 'Создать учётную запись',
 'pt-userlogout' => 'Выйти',
 
@@ -1415,8 +1416,10 @@ $3 {{GENDER:$3|указал|указала}} следующую причину:
 'revdelete-show-file-submit' => 'Да',
 'revdelete-selected' => "'''{{PLURAL:$2|1=Выбранная версия|Выбранные версии}} страницы [[:$1]]:'''",
 'logdelete-selected' => "'''{{PLURAL:$1|1=Выбранная запись|Выбранные записи}} журнала:'''",
-'revdelete-text' => "'''Удалённые версии страниц и события будут показываться в истории страницы и журналах, но часть их содержания будет недоступна обычным посетителям.'''
-Администраторы проекта {{SITENAME}} будут иметь доступ к скрытому содержанию и смогут восстановить его через этот же интерфейс, за исключением случаев, когда установлено дополнительное ограничение.",
+'revdelete-text-text' => 'Удалённые версии будут по-прежнему видны в истории страницы, но части их содержимого будут недоступны для участников.',
+'revdelete-text-file' => 'Удалённые версии файла будут по-прежнему видны в истории страницы, но части их содержимого будут недоступны для участников.',
+'logdelete-text' => 'Удалённые события в журнале будут по-прежнему видны в журналах, но части их содержимого будут недоступны для участников.',
+'revdelete-text-others' => 'Другие администраторы на {{grammar:genitive|{{SITENAME}}}} по-прежнему будет иметь возможность доступа к скрытому содержимому и смогут восстановить его снова через этот же интерфейс, если не установлены дополнительные ограничения.',
 'revdelete-confirm' => 'Пожалуйста, подтвердите, что вы действительно желаете совершить это действие, осознаёте последствия, делаете это в соответствии с [[{{MediaWiki:Policy-url}}|правилами]].',
 'revdelete-suppress-text' => "Сокрытие может производиться '''только''' в следующих случаях:
 * Потенциально клеветническая информация
@@ -1552,7 +1555,7 @@ $1",
 'search-file-match' => '(совпадает с содержимым файла)',
 'search-suggest' => 'Возможно, вы имели в виду «$1».',
 'search-interwiki-caption' => 'Родственные проекты',
-'search-interwiki-default' => '$1 результ.:',
+'search-interwiki-default' => 'Результаты из $1:',
 'search-interwiki-more' => '(ещё)',
 'search-relatedarticle' => 'Связанный',
 'searcheverything-enable' => 'Поиск по всем пространствам имён',
index e4bf359..0bdade2 100644 (file)
@@ -1054,9 +1054,6 @@ $3 зазначів тоту причіну: ''$2''",
 'revdelete-show-file-submit' => 'Гей',
 'revdelete-selected' => "'''{{PLURAL:$2|Выбрана ревізія|Выбраны ревізії}} з [[:$1]]:'''",
 'logdelete-selected' => "'''{{PLURAL:$1|Выбрана протоколована подїя|Выбраны протоколованы подїї}}:'''",
-'revdelete-text' => "'''Змазаны верзії і подїї будуть надале зображены в історії сторінкы і протоколовачіх записах, але дакотры їх части не будуть публікованы.'''
-Другы адміністраторы {{GRAMMAR:2sg|{{SITENAME}}}} собі будуть мочі схованый обсяг перезерати і помочов того самого інтерфейсу го будуть мочі обновити,
-кідь не были наставлены далшы обмеджіня.",
 'revdelete-confirm' => 'Просиме Вас, потвердьте, же то хочете справды зробити, же собі усвідомлюєте резултат і же є то в згодї з  [[{{MediaWiki:Policy-url}}|правилами]].',
 'revdelete-suppress-text' => "Затаёваня бы ся мало хосновати  ''лем''' в такых припадах:
 * Потенціално огваряючі інформації
index ef1ed10..c375c74 100644 (file)
@@ -357,18 +357,18 @@ $messages = array(
 'october' => 'अक्तूबर',
 'november' => 'नवम्बर',
 'december' => 'दिसम्बर',
-'january-gen' => 'à¤\9cनà¥\81वरि',
-'february-gen' => 'फà¥\87़बà¥\8dरà¥\81वरि',
-'march-gen' => 'मार्च',
-'april-gen' => 'à¤\8fपà¥\8dरिलà¥\8d',
-'may-gen' => 'मà¥\87यà¥\8d',
-'june-gen' => 'जून',
-'july-gen' => 'à¤\9cà¥\81लà¥\88',
-'august-gen' => 'à¤\93à¤\97सà¥\8dà¤\9fà¥\8d',
-'september-gen' => 'सपà¥\8dतमà¥\8dबरà¥\8d',
-'october-gen' => 'à¤\85षà¥\8dà¤\9fà¥\8bबरà¥\8d',
-'november-gen' => 'नवम्बर',
-'december-gen' => 'दशमà¥\8dबरà¥\8d',
+'january-gen' => 'à¤\9cनवरà¥\80',
+'february-gen' => 'फरवरà¥\80',
+'march-gen' => 'मार्च',
+'april-gen' => 'à¤\85पà¥\8dरà¥\88ल',
+'may-gen' => 'मà¤\88',
+'june-gen' => 'जून',
+'july-gen' => 'à¤\9cà¥\81लाà¤\88',
+'august-gen' => 'à¤\85à¤\97सà¥\8dत',
+'september-gen' => 'सितमà¥\8dबर',
+'october-gen' => 'à¤\85à¤\95à¥\8dतà¥\82बर',
+'november-gen' => 'नवम्बर',
+'december-gen' => 'दिसमà¥\8dबर',
 'jan' => 'जेन.',
 'feb' => 'फेब.',
 'mar' => 'मार्च.',
@@ -404,11 +404,11 @@ The following {{PLURAL:$1|file is|$1 files are}} in the current category.',
 
 'about' => 'इत्यस्मिन् विषये:',
 'article' => 'लेखः',
-'newwindow' => '(नवà¥\87 à¤\97वाà¤\95à¥\8dषà¥\87 à¤\87दमà¥\8d उद्घाट्यते)',
+'newwindow' => '(à¤\87दà¤\82 à¤¨à¤µà¥\80नà¥\87 à¤\97वाà¤\95à¥\8dषà¥\87 उद्घाट्यते)',
 'cancel' => 'निरस्यताम्',
 'moredotdotdot' => 'अपि च...',
 'mypage' => 'मम पृष्ठम्',
-'mytalk' => 'मम à¤¸à¤®à¥\8dभाषणमà¥\8d',
+'mytalk' => 'सम्भाषणम्',
 'anontalk' => 'अस्य आइ.पी. संकेतस्य कृते सम्भाषणम्',
 'navigation' => 'सञ्चरणम्',
 'and' => '&#32;तथा च',
@@ -419,7 +419,7 @@ The following {{PLURAL:$1|file is|$1 files are}} in the current category.',
 'qbedit' => 'सम्पाद्यताम्',
 'qbpageoptions' => 'इदं पृष्ठम्',
 'qbmyoptions' => 'मम पृष्ठानि',
-'faq' => 'बहà¥\81धा à¤ªà¥\83à¤\9aà¥\8dà¤\9bà¥\8dयमानाà¤\83 à¤ªà¥\8dरशà¥\8dनाà¤\83',
+'faq' => 'सामानà¥\8dयà¤\9cिà¤\9cà¥\8dà¤\9eासाà¤\83 (FAQ)',
 'faqpage' => 'Project:बहुधा पृछ्यमानाः प्रश्नाः',
 
 # Vector skin
@@ -506,12 +506,12 @@ $1',
 'aboutsite' => '{{SITENAME}} विषयकं',
 'aboutpage' => 'Project:विषयकम्',
 'copyright' => 'अस्य घटकानि $1 इत्यस्यान्तर्गतानि उपलब्धानि।',
-'copyrightpage' => '{{ns:project}}:पà¥\8dरतिलिपà¥\8dयधिà¤\95ाराः',
+'copyrightpage' => '{{ns:project}}:पà¥\8dरतिà¤\95à¥\83तà¥\8dयधिà¤\95ारः',
 'currentevents' => 'वर्तमानवार्ताः',
 'currentevents-url' => 'Project:वर्तमानवार्ताः',
 'disclaimers' => 'अस्वीकारः',
 'disclaimerpage' => 'Project:सामान्याऽस्वीकरणम्',
-'edithelp' => 'सम्पादनार्थं सहाय्यम्',
+'edithelp' => 'समà¥\8dपादनारà¥\8dथà¤\82 à¤¸à¤¾à¤¹à¤¾à¤¯à¥\8dयमà¥\8d',
 'helppage' => 'Help:अन्तर्वस्तु',
 'mainpage' => 'मुख्यपृष्ठम्',
 'mainpage-description' => 'मुख्यपृष्ठम्',
@@ -564,7 +564,7 @@ $1',
 
 # Short words for each namespace, by default used in the namespace tab in monobook
 'nstab-main' => 'पृष्ठम्',
-'nstab-user' => 'यà¥\8bà¤\9cà¤\95सà¥\8dय à¤ªà¥\83षà¥\8dठमà¥\8d',
+'nstab-user' => 'योजकपृष्ठम्',
 'nstab-media' => 'माध्यमपृष्ठम्',
 'nstab-special' => 'विशेषपृष्ठम्',
 'nstab-project' => 'प्रकल्पपृष्ठम्',
@@ -768,6 +768,7 @@ You may ignore this message, if this account was created in error.',
 'login-abort-generic' => 'भवतः प्रवेशप्रयासः विफलीभूतः - परित्यक्तः',
 'loginlanguagelabel' => 'भाषा : $1',
 'suspicious-userlogout' => 'भवतः सत्राद् बहिर्गमनस्य अनुरोधः अस्वीकृतोऽस्ति, यस्मादेतत् भग्नादेकस्मात् ब्राउज़र्तः अथवा स्वल्पसञ्चयि-प्रॉक्सितः प्रेषित आसीत्।',
+'pt-login-button' => 'प्रविश्यताम्',
 
 # Email sending
 'php-mail-error-unknown' => 'पीएच्पी इत्येतस्य mail() फलने अज्ञाता काऽपि त्रुटिर्जाता।',
@@ -831,37 +832,37 @@ $2
 'changeemail-cancel' => 'निवर्तयते',
 
 # Edit page toolbar
-'bold_sample' => 'सà¥\8dथà¥\82लाà¤\95à¥\8dषरà¥\88à¤\83 à¤¯à¥\81à¤\95à¥\8dतà¤\83 à¤­à¤¾à¤\97à¤\83',
-'bold_tip' => 'सà¥\8dथà¥\82लाà¤\95à¥\8dषरà¥\88à¤\83 à¤¯à¥\81à¤\95à¥\8dतà¤\83 à¤­à¤¾à¤\97à¤\83',
+'bold_sample' => 'सà¥\8dथà¥\82लाà¤\95à¥\8dषराणि',
+'bold_tip' => 'सà¥\8dथà¥\82लाà¤\95à¥\8dषराणि',
 'italic_sample' => 'तिर्यक् अक्षरम्',
 'italic_tip' => 'तिर्यक् अक्षरम्',
-'link_sample' => 'सà¤\82बà¤\82धनसà¥\8dय शीर्षकम्',
+'link_sample' => 'परिसनà¥\8dधà¥\87à¤\83 शीर्षकम्',
 'link_tip' => 'आन्तरिकसम्पर्कतन्तुः',
-'extlink_sample' => 'http://www.example.com à¤¸à¤\82बà¤\82धनसà¥\8dय शीर्षकम्',
-'extlink_tip' => 'बाह्य-संबंधनम् (अवश्यमेव  http:// इति पूर्वलग्नं योक्तव्यम्)',
+'extlink_sample' => 'http://www.example.com à¤ªà¤°à¤¿à¤¸à¤¨à¥\8dधà¥\87à¤\83 शीर्षकम्',
+'extlink_tip' => 'बाह्यानुबन्धः (http:// इति पूर्वन्यासम् अग्रे योजनीयम् इति स्मरतु)',
 'headline_sample' => 'शीर्षकम्',
 'headline_tip' => 'द्वितीयस्तरीयं शीर्षकम्',
-'nowiki_sample' => 'à¤\85पà¥\8dरारà¥\82पà¥\80à¤\95à¥\83तà¤\82 à¤ªà¤¾à¤ à¤\82 à¤\85तà¥\8dर à¤¨à¤¿à¤µà¥\87शयतà¥\81',
-'nowiki_tip' => 'विकिप्रारूपणं अवगणना कुरु',
+'nowiki_sample' => 'à¤\85पà¥\8dरारà¥\82पितà¤\82 à¤ªà¤¾à¤ à¤®à¥\8d à¤\85तà¥\8dर à¤¨à¤¿à¤µà¥\87शà¥\8dयतामà¥\8d',
+'nowiki_tip' => 'विकि-प्रारूपस्य अवगणनां करोतु',
 'image_sample' => 'उदाहरणम्.jpg',
-'image_tip' => 'à¤\85नà¥\8dतरà¥\8dà¤\97ता सञ्चिका',
+'image_tip' => 'à¤\85नà¥\8dतरà¥\8dनिहिता सञ्चिका',
 'media_sample' => 'उदाहरणम्.ogg',
-'media_tip' => 'सà¤\82à¤\9aिà¤\95ा-समà¥\8dपरà¥\8dà¤\95तनà¥\8dतà¥\81ः',
-'sig_tip' => 'भवतà¤\83 à¤¹à¤¸à¥\8dताà¤\99à¥\8dà¤\95नà¤\82 à¤¸à¤®à¤¯à¥\8bलà¥\8dलà¥\87à¤\96शà¥\8dà¤\9a',
+'media_tip' => 'सà¤\9eà¥\8dà¤\9aिà¤\95ासमà¥\8dबनà¥\8dधः',
+'sig_tip' => 'समयà¥\8bलà¥\8dलà¥\87न à¤¸à¤¹ à¤­à¤µà¤¤à¤\83/भवतà¥\8dयाà¤\83 à¤¹à¤¸à¥\8dताà¤\95à¥\8dषरà¤\83',
 'hr_tip' => 'क्षैतिज-रेखा (न्यूनतया प्रयोक्तव्या)',
 
 # Edit pages
-'summary' => 'सारांशः :',
+'summary' => 'सारांशः:',
 'subject' => 'विषयः/शीर्षकम् :',
 'minoredit' => 'इदं लघु परिवर्तनम्',
 'watchthis' => 'इदं पृष्ठं निरीक्षताम्',
 'savearticle' => 'पृष्ठं रक्ष्यताम्',
 'preview' => 'प्राग्दृश्यम्',
-'showpreview' => 'पà¥\8dराà¤\97à¥\8dदà¥\83शà¥\8dयà¤\82 à¤¦à¤°à¥\8dश्यताम्',
+'showpreview' => 'पà¥\8dराà¤\97à¥\8dदà¥\83शà¥\8dयà¤\82 à¤¦à¥\83श्यताम्',
 'showlivepreview' => 'प्रत्यक्षं प्राग्दृश्यम्',
-'showdiff' => 'परिवरà¥\8dतनानि à¤¦à¤°à¥\8dश्यन्ताम्',
-'anoneditwarning' => "'''पà¥\8dरबà¥\8bधà¤\83'''भवानà¥\8d à¤¨ à¤ªà¥\8dरविषà¥\8dà¤\9fà¥\8bऽसà¥\8dति !
-समà¥\8dपादनà¤\82 à¤\95रà¥\8dतà¥\81मà¥\8d à¤\85तà¥\8dर à¤ªà¥\8dरवà¥\87शà¤\83 à¤\86वशà¥\8dयà¤\95à¤\83 à¥¤ à¤\85नà¥\8dयथा à¤\85सà¥\8dय à¤ªà¥\83षà¥\8dठसà¥\8dय à¤\87तिहासà¥\87 à¤­à¤µà¤¦à¥\80या IPसà¤\82ख्या अङ्किता भवति ।",
+'showdiff' => 'परिवरà¥\8dतनानि à¤¦à¥\83श्यन्ताम्',
+'anoneditwarning' => "'''पà¥\82रà¥\8dवसà¥\82à¤\9aना''' à¤­à¤µà¤¤à¤¾/भवतà¥\8dया à¤ªà¥\8dरवà¥\87शà¤\83 à¤¨ à¤\95à¥\83तà¤\83 !
+à¤\85तà¥\8dर à¤¸à¤®à¥\8dपादनà¤\82 à¤\95रà¥\8dतà¥\81à¤\82 à¤ªà¥\8dरवà¥\87शà¤\83 à¤\85निवारà¥\8dयà¤\83 à¥¤ à¤\85नà¥\8dयथा à¤\85सà¥\8dय à¤ªà¥\83षà¥\8dठसà¥\8dय à¤\87तिहासà¥\87 à¤­à¤µà¤¤à¤\83/भवतà¥\8dयाà¤\83 à¤\85नà¥\8dतरà¥\8dà¤\9cालसà¤\82विदà¤\83 (IP) à¤¸à¤\99à¥\8dख्या अङ्किता भवति ।",
 'anonpreviewwarning' => "''भवान् प्रवेशितः न अस्ति। रक्षणेन पृष्ठस्य सम्पादनेतिहासे भवतः आइपीसंकेतः अंकितः भविष्यति।''",
 'missingsummary' => "'''अनुस्मारकम्:''' भवता सम्पादनस्य सारः न प्रदत्तः।
 चेद्भवान् \"{{int:savearticle}}\" इत्येतद् पुनः क्लिक्करोति, भवतः सम्पादनानि साराद् ऋते रक्षितीभविष्यन्ति।",
@@ -917,12 +918,12 @@ $2
 'anontalkpagetext' => 'तस्य अनामकयोजकस्य, अथवा अनुपयोजकस्य च परिचर्चापुटम् येन एतावति काले स्वस्थनं  न निर्मितम् । 
 अतः तस्य अभिज्ञानार्थं ऐ.पि.सङ्गेतसङ्ख्या प्रयोजनीया । 
 सा समाना सङ्ख्याः अन्ययोजकैः अपि विभक्ता । यदि भवान् अनामकयोजकः, भवता असम्बद्धटीकाः श्रुताः, कृपया स्वस्थनं निर्मीय नामाभिलेखं करोतु ।  [[Special:UserLogin/signup|create an account]], [[Special:UserLogin|log in]] अन्यानामकयोजकैः सह सम्भूयमनभ्रमैः विमुक्तः भवतु ।',
-'noarticletext' => 'अस्मिन् पृष्ठे अधुना किमपि न विद्यते। भवान् विकिपीडियावर्तिषु अन्येषु पृष्ठेषु इदं [[Special:Search/{{PAGENAME}}|शीर्षकम् अन्वेष्टुम्]]अर्हति अथवा इदं पृष्ठं 
-<span class="plainlinks">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}}  à¤¸à¤®à¥\8dबदà¥\8dधà¥\87षà¥\81 à¤ªà¥\83षà¥\8dठà¥\87षà¥\81 à¤\85नà¥\8dवà¥\87षà¥\8dà¤\9fà¥\81मà¥\8d à¤\85रà¥\8dहति],
-अथवा [{{fullurl:{{FULLPAGENAME}}|action=edit}} इदं पृष्ठं सम्पादयितुम् अर्हति]</span>.',
-'noarticletext-nopermission' => 'अस्मिन् पृष्ठे अधुना किमपि न विद्यते। भवान् विकिपीडियावर्तिषु अन्येषु पृष्ठेषु इदं [[Special:Search/{{PAGENAME}}|शीर्षकम् अन्वेष्टुम् अर्हति]] 
-<span class="plainlinks">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}}  related logs अन्वेष्टुम् अर्हति],
-अथवा [{{fullurl:{{FULLPAGENAME}}|action=edit}} इदं पृष्ठं स्रष्टुम् अर्हति]</span>.',
+'noarticletext' => 'अस्मिन् पृष्ठे अधुना किमपि न विद्यते । [[Special:Search/{{PAGENAME}}|एषः शब्दः]] येषु पृष्ठेषु अन्तर्भवति, तानि पृष्ठानि अन्वेष्टुं शक्यन्ते । 
+<span class="plainlinks">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}}  à¤¸à¤®à¥\8dबदà¥\8dधà¥\87षà¥\81 à¤ªà¥\83षà¥\8dठà¥\87षà¥\81 à¤\85नà¥\8dवà¥\87षणà¤\82]
+[{{fullurl:{{FULLPAGENAME}}|action=edit}} अस्य पृष्ठस्य सम्पादनं] वा  शक्यम्</span>.',
+'noarticletext-nopermission' => 'अस्मिन् पृष्ठे अधुना किमपि न विद्यते । [[Special:Search/{{PAGENAME}}|एषः शब्दः]] येषु पृष्ठेषु अन्तर्भवति, तानि पृष्ठानि अन्वेष्टुं शक्यन्ते । 
+<span class="plainlinks">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}}  सम्बद्धेषु पृष्ठेषु अन्वेषणं]
+[{{fullurl:{{FULLPAGENAME}}|action=edit}} अस्य पृष्ठस्य सम्पादनं] वा  शक्यम्</span>.',
 'missing-revision' => '{{PAGENAME}} इति नामाङ्कितपुटस्य #$1 इति पुनरावृत्तिः अत्र नाश्ति । 
 पुटेन सह कालातीतानुबन्धकारणेन एतत् अभवत् ।
 विवरणम् अत्र दृश्यते ।[{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} deletion log].',
@@ -1037,9 +1038,8 @@ $2
 'expensive-parserfunction-warning' => "'''प्रबोधः :''' अस्मिन् पृष्ठे प्रभूतानि जटिलानि पार्सर्-फ़ंक्शन्-आह्वानानि सन्ति।
 अत्र $2 संख्यातः  {{PLURAL:$2|न्यूनं आह्वानं|न्यूनानि आह्वानानि}} भवितव्यानि, सद्यः तत्र {{PLURAL:$1 $1 आह्वानं विद्यते|$1 आह्वानानि विद्यन्ते}}।",
 'expensive-parserfunction-category' => 'प्रभूतेभ्यः जटिलेभ्यः पार्सर्-फंक्शन्-आह्वानेभ्यः युक्तानि पृष्ठाणि।',
-'post-expand-template-inclusion-warning' => "'''प्रबोधः:''' फलकानां योजनस्य आकारः अतिविशालः वर्तते ।
-कानिचन फलकानि न योजयिष्यते ।",
-'post-expand-template-inclusion-category' => 'पृष्ठाणि यत्र अतोऽधिकाः बिम्बधराः समाहितीकर्तुं न शक्यन्ते।',
+'post-expand-template-inclusion-warning' => "'''पूर्वसूचना:''' फलकस्य आकारः बृहत् वर्तते । कानिचन फलकानि नान्तर्भविष्यन्ति ।",
+'post-expand-template-inclusion-category' => 'माहितीफलकस्य अपेक्षया पृष्ठं बृहत् वर्तते ।',
 'post-expand-template-argument-warning' => "'''जागरणम्''' अस्मिन् पृष्ठे कश्चन एतादृशं फलकं विद्यते यच्च संवर्धनेन बृहदाकारतां प्राप्नोति ।
 एतादृशानि फलकानि परित्यक्तानि सन्ति ।",
 'post-expand-template-argument-category' => 'परित्यक्तैः फलकैः युक्तानि पृष्ठानि एतानि',
@@ -1070,13 +1070,13 @@ $2
 'viewpagelogs' => 'अस्य पृष्ठस्य लॉंग् इत्येतद् दर्शयतु',
 'nohistory' => 'अस्य पृष्ठस्य कृते पृष्ठेतिहासः न वर्तते।',
 'currentrev' => 'सद्यःकालीना आवृत्तिः',
-'currentrev-asof' => 'वर्तमाना आवृत्तिः $1 इति समये',
+'currentrev-asof' => '$1 समयस्य संस्करणम्',
 'revisionasof' => '$1 इत्यस्य संस्करणं',
 'revision-info' => '$1इति समयस्य आवृत्तिः $2 इत्यनेन',
 'previousrevision' => '← पुरातनानि संस्करणानि',
 'nextrevision' => 'नूतनतरा आवृत्तिः →',
 'currentrevisionlink' => 'सद्यःकालीना आवृत्तिः',
-'cur' => 'सदà¥\8dयà¥\8bà¤\9cातमà¥\8d',
+'cur' => 'वरà¥\8dतमानà¤\83',
 'next' => 'आगामि',
 'last' => 'पूर्वतनम्',
 'page_first' => 'प्रथमम्',
@@ -1119,7 +1119,7 @@ You can still [$1 view this revision]',
 You can still [$1 view this revision]",
 'rev-deleted-diff-view' => 'एतस्मात् अन्तरतः किञ्चिदवतरणं परिमार्जितम् । एतदन्तरं दृष्टुं शक्नुवन्ति । विवरणम् [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} हटाने की लॉग]',
 'rev-suppressed-diff-view' => 'अस्मिन्नन्तरे किञ्चिदवतरणं सङ्गुपतम् । तदन्तरम् अत्र दृष्टुं शक्नुवन्ति । [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} suppression log].',
-'rev-delundel' => 'दरà¥\8dशà¥\8dयनà¥\8dतामà¥\8d/à¤\97à¥\8bपà¥\8dयनà¥\8dताम्',
+'rev-delundel' => 'दà¥\83शà¥\8dयतामà¥\8d/à¤\97à¥\8bपà¥\8dयताम्',
 'rev-showdeleted' => 'दर्श्यताम्',
 'revisiondelete' => 'अवतरणं परिमार्जयतु/पुनस्थापयतु',
 'revdelete-nooldid-title' => 'लक्ष्यरूपा आवृत्तिः अमान्याऽस्ति।',
@@ -1129,8 +1129,6 @@ You can still [$1 view this revision]",
 'revdelete-show-file-submit' => 'आम्',
 'revdelete-selected' => "'''{{PLURAL:$2|Selected revision|Selected revisions}} of [[:$1]]:'''",
 'logdelete-selected' => "'''{{PLURAL:$1|Selected log event|Selected log events}}:'''",
-'revdelete-text' => "'''परिमार्जितानि अवतरणानि पुटेतिहासे अद्यापि दृश्यन्ते । तस्य कश्चन भागः सार्वजनिकः न भवति । '''
-{{SITENAME}} इत्यस्य अन्यप्रशसासकः गुप्तसामग्रीः प्राप्नुवन्ति । अपि च अन्तरापुटेन अस्य अपरिमार्जनं कर्तुं शक्नुवन्ति । यावत् अतिरिक्तप्रतिबन्धकाः न स्थापिताः ।",
 'revdelete-confirm' => 'भवान् एतत् कार्यं करोति इति दढयतु । भवान् अस्य परिणामं जानाति । [[{{MediaWiki:Policy-url}}|the policy]] भवान् एतदनुसारं करोति ।',
 'revdelete-suppress-text' => 'अधोनिदेशितपरिस्थितिषु केवलं निग्रहः कार्यः । 
 * अवमाननीयाः विषयाः ।
@@ -1154,7 +1152,7 @@ You can still [$1 view this revision]",
 'revdelete-failure' => 'अवतरणदृश्यता उन्नतीकरणं न शक्यते ।$1',
 'logdelete-success' => 'नामाङ्कनदृश्यता साफल्येन योजिता ।',
 'logdelete-failure' => 'नामाभिलेखदृश्यता सपला नाभवत् । $1',
-'revdel-restore' => 'दà¥\83षà¥\8dà¤\9fिविषयà¤\83 परिवर्त्यताम्',
+'revdel-restore' => 'दà¥\83शà¥\8dयता परिवर्त्यताम्',
 'pagehist' => 'पृष्ठस्य इतिहासः',
 'deletedhist' => 'परिमार्जितेतिहासः ।',
 'revdelete-hide-current' => '$2 $1 दिनाङ्कितस्य गोपने दोषः । एतत् प्रकृतावतरणम्, एतत् न गोपनीयम् ।',
@@ -1227,30 +1225,32 @@ You can still [$1 view this revision]",
 'titlematches' => 'पुटशीर्षिकामेलाः ।',
 'textmatches' => 'पुटपाठस्य मेलाः',
 'notextmatches' => 'न कस्यापि पृष्ठस्य पाठः अस्य सममस्ति',
-'prevn' => 'पà¥\8dराà¤\95à¥\8dतनानि {{PLURAL:$1|$1}}',
-'nextn' => 'à¤\85à¤\97à¥\8dरिमाणि {{PLURAL:$1|$1}}',
-'prevn-title' => 'पà¥\8dराà¤\95à¥\8dतन-{{PLURAL:$1|फलितमà¥\8d| à¤«à¤²à¤¿à¤¤à¤¾à¤¨à¤¿}}',
-'nextn-title' => 'पà¥\8dराà¤\95à¥\8dतन-{{PLURAL:$1|फलितमà¥\8d| à¤«à¤²à¤¿à¤¤à¤¾à¤¨à¤¿}}',
+'prevn' => 'पà¥\81रसà¥\8dतातà¥\8d {{PLURAL:$1|$1}}',
+'nextn' => 'परसà¥\8dतातà¥\8d {{PLURAL:$1|$1}}',
+'prevn-title' => 'पà¥\81रसà¥\8dतातà¥\8d {{PLURAL:$1|परिणामà¤\83|परिणामाà¤\83}}',
+'nextn-title' => 'परसà¥\8dतातà¥\8d {{PLURAL:$1|परिणामà¤\83|परिणामाà¤\83}}',
 'shown-title' => 'प्रत्येकस्मिन् पृष्ठे $1 {{PLURAL:$1|फलितम्|फलितानि}} दर्श्यताम्',
 'viewprevnext' => 'दर्श्यताम् ($1 {{int:pipe-separator}} $2) ($3)',
 'searchmenu-exists' => 'अस्मिन् विकिमध्ये "[[:$1]]"नामकं पृष्ठं विद्यते।',
-'searchmenu-new' => "'''अस्यां विक्यां \"[[:\$1]]\" इति पृष्ठं सृज्यताम्!'''",
-'searchprofile-articles' => 'आन्तर्यम्',
-'searchprofile-project' => 'सहायता प्रकल्पपृष्ठानि च',
-'searchprofile-images' => 'बहुमाध्यमः',
+'searchmenu-new' => '<srong> अस्मिन् विकिजालस्थाने "[[:$1]]" इदं पृष्ठं सृज्यताम् ।
+</strong>
+{{PLURAL:$2|0=|तव अन्वेषणस्य परिणामोपि दृश्यताम् ।|तव अन्वेषणस्य परिणामाः अपि दृश्यन्ताम्}}',
+'searchprofile-articles' => 'आन्तर्विषकं पृष्ठं',
+'searchprofile-project' => 'साहाय्यं, प्रकल्पपृष्ठानि च',
+'searchprofile-images' => 'माध्यमसमुच्चयः',
 'searchprofile-everything' => 'सर्वम्',
 'searchprofile-advanced' => 'प्रगतम्',
 'searchprofile-articles-tooltip' => '$1 स्थले अन्विष्यताम्',
 'searchprofile-project-tooltip' => '$1 स्थले अन्विष्यताम्',
 'searchprofile-images-tooltip' => 'सञ्चिका अन्विष्यताम्',
 'searchprofile-everything-tooltip' => '(चर्चापृष्ठानि अविहाय) सर्वत्र अन्विष्यताम्',
-'searchprofile-advanced-tooltip' => 'विशà¥\87षनामसà¥\8dथानेषु अन्विष्यताम्',
+'searchprofile-advanced-tooltip' => 'नामाà¤\95ाशेषु अन्विष्यताम्',
 'search-result-size' => '$1 ({{PLURAL:$2|1 शब्दः|$2 शब्दाः}})',
 'search-result-category-size' => '{{PLURAL:$1|1 सदस्यः|$1 सदस्याः}} ({{PLURAL:$2|1 उपवर्गः|$2 उपर्गाः}}, {{PLURAL:$3|1 सञ्चिका|$3 सञ्चिकाः}})',
 'search-result-score' => 'सम्बन्धः $1% ।',
-'search-redirect' => '($1 à¤\87तà¥\8dयतà¥\8dर अनुप्रेषितम्)',
+'search-redirect' => '($1 à¤¤à¤\83 अनुप्रेषितम्)',
 'search-section' => '(विभागः $1)',
-'search-suggest' => 'किं भवतः आशयः एवमस्ति : $1',
+'search-suggest' => 'किं भवतः/भवत्याः आशयः एवमस्ति : $1',
 'search-interwiki-caption' => 'बन्धु-प्रकल्पाः',
 'search-interwiki-default' => '$1 परिणामाः :',
 'search-interwiki-more' => '(अधिकानि)',
@@ -1260,8 +1260,8 @@ You can still [$1 view this revision]",
 'searchall' => 'सर्वाणि',
 'showingresults' => "निम्नगतक्रमाङ्कस्य '''$2''' तः आरभ्य अधिकतमं परिणामः'''$1''' {{PLURAL:$1| दर्शितः}}।",
 'showingresultsnum' => "निम्नगतक्रमाङ्क'''$2'''तः आरभ्य अधिकतमः '''$3''' परिणामः {{PLURAL:$3|दर्शितः}}।",
-'showingresultsheader' => "'''$4''' à¤\87तà¥\8dयà¥\87तसà¥\8dय {{PLURAL:$5|'''$3'''सà¥\8dय '''$1'''  à¤«à¤²à¤¿à¤¤à¤®à¥\8d|'''$3'''सà¥\8dय '''$1 - $2'''  à¤«à¤²à¤¿à¤¤à¤¾à¤¨à¤¿}}",
-'search-nonefound' => 'भवतः अपेक्षानुगुणं फलितं न किमपि विद्यते ।',
+'showingresultsheader' => "'''$4''' à¤\87तà¥\8dयà¥\87तसà¥\8dमà¥\88 {{PLURAL:$5|'''$1''' à¤ªà¤°à¤¿à¤£à¤¾à¤®à¤\83 '''$3''' à¤\87तà¥\8dयà¥\87षà¥\81|'''$1 - $2''' à¤ªà¤°à¤¿à¤£à¤¾à¤®à¤¾à¤\83 '''$3''' à¤\87तà¥\8dयà¥\87षà¥\81}}",
+'search-nonefound' => 'भवतः/भवत्याः अपेक्षानुगुणं परिणामः न विद्यते ।',
 'powersearch-legend' => 'प्रगतम् अन्वेषणम्',
 'powersearch-ns' => 'नामाकाशेषु अन्विष्यताम्:',
 'powersearch-redir' => 'अनुप्रेषणानां सूचिका दर्श्यताम्',
@@ -1275,7 +1275,7 @@ You can still [$1 view this revision]",
 
 # Preferences page
 'preferences' => 'इष्टतमानि',
-'mypreferences' => 'मम à¤\87षà¥\8dà¤\9fतमानि',
+'mypreferences' => 'इष्टतमानि',
 'prefs-edits' => 'सम्पादनानां सख्याः',
 'prefs-skin' => 'त्वक्',
 'skin-preview' => 'प्राग्दृश्यम्',
@@ -1543,23 +1543,23 @@ You can still [$1 view this revision]",
 'recentchanges-legend' => 'सद्योजातानां परिवर्तनानां विकल्पाः',
 'recentchanges-summary' => 'अस्मिन् विकियोजनायां सद्योजातानि परिवर्तनानि दर्श्यन्ताम्',
 'recentchanges-feed-description' => 'अस्मिन् विकियोजनायां सद्योजातानि परिवर्तनानि दर्श्यन्ताम्',
-'recentchanges-label-newpage' => 'à¤\8fतसà¥\8dमातà¥\8d à¤¸à¤®à¥\8dपादनातà¥\8d à¤¨à¥\82तनà¤\82 à¤ªà¥\83षà¥\8dठà¤\82 à¤¸à¥\83षà¥\8dà¤\9fमसà¥\8dति',
+'recentchanges-label-newpage' => 'à¤\85नà¥\87न à¤¸à¤®à¥\8dपादनà¥\87न à¤¨à¥\82तनपà¥\83षà¥\8dठसà¥\8dय à¤°à¤\9aना à¤\85भà¥\82तà¥\8d à¥¤',
 'recentchanges-label-minor' => 'इदं लघु परिवर्तनम्',
-'recentchanges-label-bot' => 'à¤\8fतदà¥\8d à¤¯à¤¨à¥\8dतà¥\8dरà¥\87ण à¤\95à¥\83तà¤\82 à¤¸à¤®à¥\8dपादनमà¥\8d à¤\86सà¥\80त्',
-'recentchanges-label-unpatrolled' => 'à¤\8fतदà¥\8d à¤¸à¤®à¥\8dपादनमà¥\8d à¤\8fतावता à¤ªà¤°à¤¿à¤¶à¥\80लितà¤\82 à¤¨à¤¾à¤¸à¥\8dति ।',
+'recentchanges-label-bot' => 'बà¥\8bà¤\9fà¥\8d-दà¥\8dवारा à¤\95à¥\83तà¤\82 à¤¸à¤®à¥\8dपादनमà¥\87तत्',
+'recentchanges-label-unpatrolled' => 'à¤\8fतावता à¤\85सà¥\8dय à¤¸à¤®à¥\8dपादनसà¥\8dय à¤ªà¤°à¤¿à¤¶à¥\80लिनà¤\82 à¤¨à¤¾à¤­à¥\82तà¥\8d ।',
 'rcnotefrom' => "अधः '''$2''' तः  ('''$1''' पर्यन्तं) परिवर्तनानि दर्शितानि सन्ति ।",
-'rclistfrom' => '$1 à¤¤à¤\83 à¤\9cातानि à¤¨à¥\82तनानि à¤ªà¤°à¤¿à¤µà¤°à¥\8dतनानि à¤¦à¤°à¥\8dशà¥\8dयताम्',
-'rcshowhideminor' => '$1 à¤²à¤\98à¥\82नि सम्पादनानि',
+'rclistfrom' => '$1 à¤ªà¤¶à¥\8dà¤\9aातà¥\8d à¤\9cातानि à¤¨à¥\82तनानि à¤ªà¤°à¤¿à¤µà¤°à¥\8dतनानि à¤¦à¥\83शà¥\8dयनà¥\8dताम्',
+'rcshowhideminor' => '$1 à¤²à¤\98à¥\81सम्पादनानि',
 'rcshowhidebots' => '$1 बोट् इत्येतानि',
-'rcshowhideliu' => '$1 à¤ªà¥\8dरविषà¥\8dà¤\9fाः योजकाः',
+'rcshowhideliu' => '$1 à¤ªà¤\9eà¥\8dà¤\9cà¥\80à¤\95à¥\83ताः योजकाः',
 'rcshowhideanons' => 'अनामकाः योजकाः $1',
 'rcshowhidepatr' => '$1 ईक्षितसम्पादनानि',
 'rcshowhidemine' => '$1 मम सम्पादनानि',
-'rclinks' => 'à¤\85नà¥\8dतिमानि $1 à¤ªà¤°à¤¿à¤µà¤°à¥\8dतनानि à¤\85नà¥\8dतिमà¥\87षà¥\81 $2 à¤¦à¤¿à¤¨à¥\87षà¥\81, à¤¦à¥\83शà¥\8dयतामà¥\8d<br />$3',
+'rclinks' => 'à¤\85नà¥\8dतिमà¥\87षà¥\81 $2 à¤¦à¤¿à¤¨à¥\87षà¥\81 à¤\9cातानि à¤\85नà¥\8dतिमानि $1 à¤ªà¤°à¤¿à¤µà¤°à¥\8dतनानि à¤¦à¥\83शà¥\8dयतामà¥\8d <br />$3',
 'diff' => 'भेदः',
 'hist' => 'इतिहासः',
 'hide' => 'गोप्यताम्',
-'show' => 'दरà¥\8dश्यताम्',
+'show' => 'दà¥\83श्यताम्',
 'minoreditletter' => '(लघु)',
 'newpageletter' => '(नवीनम्)',
 'boteditletter' => '(बोट्)',
@@ -1568,7 +1568,7 @@ You can still [$1 view this revision]",
 'rc_categories_any' => 'कश्चित्',
 'rc-change-size-new' => '$1 {{PLURAL:$1|byte|bytes}} परिवर्तनपश्चात् ।',
 'newsectionsummary' => '/* $1 */ नवीन विभागः',
-'rc-enhanced-expand' => 'विवरणानि à¤¦à¤°à¥\8dशà¥\8dयनà¥\8dतामà¥\8d (à¤\9cावालिपिà¤\83 à¤\85पà¥\87à¤\95à¥\8dषà¥\8dयतà¥\87)',
+'rc-enhanced-expand' => 'विवरणानि à¤¦à¥\83शà¥\8dयनà¥\8dतामà¥\8d',
 'rc-enhanced-hide' => 'विवरणानि गोप्यन्ताम्',
 'rc-old-title' => 'मूलरूपेण $1 इति रचितम् ।',
 
@@ -1577,9 +1577,9 @@ You can still [$1 view this revision]",
 'recentchangeslinked-feed' => 'पृष्ठ-सम्बन्धितानि परिवर्तनानि',
 'recentchangeslinked-toolbox' => 'पृष्ठसम्बद्धानि परिवर्तनानि',
 'recentchangeslinked-title' => '"$1" इत्यस्मिन् जातानि परिवर्तनानि',
-'recentchangeslinked-summary' => "à¤\8fषा à¤µà¤¿à¤¶à¥\87षपà¥\83षà¥\8dठसमà¥\8dबदà¥\8dधà¥\87षà¥\81 à¤ªà¥\84षà¥\8dठà¥\87षà¥\81 à¤\85थवा à¤µà¤°à¥\8dà¤\97विशà¥\87षà¥\87 à¤\85नà¥\8dतरà¥\8dभà¥\82तà¥\87षà¥\81 à¤ªà¥\83षà¥\8dठà¥\87षà¥\81 à¤¸à¤¦à¥\8dयà¥\8bà¤\9cातानाà¤\82 à¤ªà¤°à¤¿à¤µà¤°à¥\8dतनानामà¥\8d à¤\86वलिà¤\83
+'recentchangeslinked-summary' => "विशà¥\87षपà¥\83षà¥\8dठà¥\87षà¥\81 à¤µà¤°à¥\8dà¤\97ानà¥\8dतरà¥\8dà¤\97तपà¥\83षà¥\8dठà¥\87षà¥\81 à¤µà¤¾ à¤¸à¤¦à¥\8dयà¥\8bà¤\9cातानाà¤\82 à¤ªà¤°à¤¿à¤µà¤°à¥\8dतनानामà¥\8d à¤\8fषा à¤\86वलिà¤\83 
 
-[[Special:Watchlist|भवतः अवेक्षणसूच्यां]] विद्यमानानि पृष्ठानि '''स्थूलाक्षरैः''' दर्शितानि।",
+[[Special:Watchlist|भवतः/भवत्याः अवेक्षणावलिः]] अत्र विद्यमानानि पृष्ठानि '''स्थूलाक्षरैः''' दर्शितानि।",
 'recentchangeslinked-page' => 'पृष्ठ-नाम :',
 'recentchangeslinked-to' => 'अस्मिन् स्थाने अस्य पृष्ठस्य संबद्धानां पृष्ठानां परिवर्तनानि दर्श्यन्ताम्',
 
@@ -1609,7 +1609,7 @@ To include a file in a page, use a link in one of the following forms:
 'uploadlogpagetext' => 'अधः सद्यः काले उत्तारितसञ्चिकानाम् आवली अस्ति ।
 अधिकदृश्यविवरणार्थम् एतत् पश्यतु [[Special:NewFiles|gallery of new files]]',
 'filename' => 'सञ्चिकानाम',
-'filedesc' => 'सारांशः :',
+'filedesc' => 'सारांशः',
 'fileuploadsummary' => 'संग्रहः :',
 'filereuploadsummary' => 'सञ्चिकापरिवर्तनानि ।',
 'filestatus' => 'प्रतिकृत्यधिकारस्य स्थितिः ।',
@@ -1838,22 +1838,22 @@ See https://www.mediawiki.org/wiki/Manual:Image_Authorization.',
 # File description page
 'file-anchor-link' => 'सञ्चिका',
 'filehist' => 'सञ्चिकायाः इतिहासः',
-'filehist-help' => 'सà¤\9eà¥\8dà¤\9aिà¤\95ा à¤¤à¤¤à¥\8dसमयà¥\87 à¤\95à¥\80दà¥\83शà¥\80 à¤\86सà¥\80दिति à¤¦à¥\8dरषà¥\8dà¤\9fà¥\81à¤\82 à¤¦à¤¿à¤¨à¤¾à¤\82कः/समयः नुद्यताम् ।',
+'filehist-help' => 'सà¤\9eà¥\8dà¤\9aिà¤\95ा à¤¤à¤¤à¥\8dसमयà¥\87 à¤\95à¥\80दà¥\83शà¥\80 à¤\86सà¥\80दिति à¤¦à¥\8dरषà¥\8dà¤\9fà¥\81à¤\82 à¤¦à¤¿à¤¨à¤¾à¤\99à¥\8dकः/समयः नुद्यताम् ।',
 'filehist-deleteall' => 'सर्वान् परिमर्जतु ।',
 'filehist-deleteone' => 'विलोप',
 'filehist-revert' => 'प्रतिनिवर्त्यताम्',
-'filehist-current' => 'सदà¥\8dयà¥\8bà¤\9cातमà¥\8d',
+'filehist-current' => 'वरà¥\8dतमानà¤\83',
 'filehist-datetime' => 'दिनाङ्कः/समयः',
-'filehist-thumb' => 'à¤\85à¤\82à¤\97à¥\81षà¥\8dठनà¤\96ाà¤\95ारमà¥\8d',
-'filehist-thumbtext' => '$1 à¤¸à¤®à¤¯à¥\87 à¤µà¤¿à¤¦à¥\8dयमानायाà¤\83 à¤\86वà¥\83तà¥\8dतà¥\87à¤\83 à¤\85à¤\82à¤\97à¥\81षà¥\8dठनà¤\96ाà¤\95ारमà¥\8d',
+'filehist-thumb' => 'लà¤\98à¥\8dवाà¤\95à¥\83तिà¤\83',
+'filehist-thumbtext' => '$1 à¤\87तà¥\8dयसà¥\8dय à¤¸à¤\82सà¥\8dà¤\95रणसà¥\8dय à¤²à¤\98à¥\81सà¥\8dवरà¥\82पमà¥\8d à¥¤',
 'filehist-nothumb' => 'अङ्गुष्टनखाकारकं नाश्ति ।',
 'filehist-user' => 'योजकः',
 'filehist-dimensions' => 'आयामाः',
 'filehist-filesize' => 'सञ्चिकाकारः ।',
 'filehist-comment' => 'टिप्पणी',
 'filehist-missing' => 'सञ्चिका विनष्टा ।',
-'imagelinks' => 'सà¤\82à¤\9aिà¤\95ा à¤¯à¤¤à¥\8dर à¤\89पयà¥\81à¤\95à¥\8dता',
-'linkstoimage' => '{{PLURAL:$1|अधोलिखितं पृष्ठं| अधोलिखितानि $1 पृष्ठाणि}} इदं संचिकां प्रति संबंधनं {{PLURAL:$1|करोति| कुर्वन्ति}}।',
+'imagelinks' => 'सà¤\9eà¥\8dà¤\9aिà¤\95ायाà¤\83 à¤\89पयà¥\8bà¤\97à¤\83',
+'linkstoimage' => '{{PLURAL:$1|अधो निर्दिष्टपृष्ठस्य परिसन्धयः|$1 अधो निर्दिष्टपृष्ठानां परिसन्धिः} अत्र {{PLURAL:$1|सल्लग्नाः सन्ति|सल्लग्ना अस्ति}}:',
 'linkstoimage-more' => '{{PLURAL:$1|$1}} तः अधिकपुटानि अस्यां सञ्चिकायां योज्यन्ते । 
 अधोनिदेशितसूची सञ्चिकाभिः योजनीयपुटानि पश्यति ।{{PLURAL:$1|$1 पृष्ठ|$1 पृष्ठ}} 
 [[Special:WhatLinksHere/$2|पूर्णसूची]] अपि लभ्यते ।',
@@ -1864,8 +1864,8 @@ See https://www.mediawiki.org/wiki/Manual:Image_Authorization.',
 'sharedupload' => 'इयं संचिका $1 इत्यस्मादस्ति, एषा खलु अन्येष्वपि प्रकल्पेषु प्रयोक्तुं शक्यते।',
 'sharedupload-desc-there' => 'एषा सञ्चिका $1 तथा अन्यप्रकल्पेन च उपयुक्ता ।
 इत्योप्यतिशयसूचनार्थं $2 सञ्चिकाविवरणपुटं पश्यतु ।',
-'sharedupload-desc-here' => 'एषा सञ्चिका $1 इत्यतः उद्धृता अन्यासु योजनासु उपयोगार्हा ।
-à¤\85सà¥\8dयाà¤\83 à¤¸à¤\9eà¥\8dà¤\9aिà¤\95ायाà¤\83  [$2 à¤¸à¤\9eà¥\8dà¤\9aिà¤\95ाविवरणपà¥\83षà¥\8dठमà¥\8d] à¤\87तà¥\8dयतà¥\8dर à¤\89पलभà¥\8dयमानà¤\82 à¤µà¤¿à¤µà¤°à¤£à¤®à¥\8d à¤\85धà¥\8bलिà¤\96ितà¤\82 à¤¯à¤¥à¤¾ ।',
+'sharedupload-desc-here' => '$1 इत्यतः उद्धृता एषा सञ्चिका अन्येषु प्रकल्पेषु उपयोगार्हा ।
+à¤\85सà¥\8dयाà¤\83 à¤¸à¤\9eà¥\8dà¤\9aिà¤\95ायाà¤\83  [$2 à¤¸à¤\9eà¥\8dà¤\9aिà¤\95ाविवरणपà¥\83षà¥\8dठमà¥\8d] à¤\87तà¥\8dयतà¥\8dर à¤\89पलभà¥\8dयमानà¤\82 à¤µà¤¿à¤µà¤°à¤£à¤®à¥\8d à¤\85धà¥\8bलिà¤\96ितà¤\82 à¤µà¤°à¥\8dततà¥\87 ।',
 'sharedupload-desc-edit' => '    एषा सञ्चिका $1 इत्यतः उद्धृता अन्यासु योजनासु उपयोगार्हा । 
 अस्याः सञ्चिकायाः [$2 सञ्चिकाविवरणपृष्ठम्] इत्यत्र उपलभ्यमानं विवरणम् अधोलिखितं यथा ।',
 'sharedupload-desc-create' => 'एषा सञ्चिका $1 इत्यतः उद्धृता अन्यासु योजनासु उपयोगार्हा । 
@@ -2030,7 +2030,7 @@ See https://www.mediawiki.org/wiki/Manual:Image_Authorization.',
 'listusers-creationsort' => 'सर्जनदिनाङ्कैः वर्गीकरोतु ।',
 'usereditcount' => '$1 {{PLURAL:$1|दिनम्|दिनानि}}',
 'usercreated' => '$1 दिने $2 समये रचितम् योजकनाम $3',
-'newpages' => 'नवà¥\80नपà¥\83षà¥\8dठाà¤\83',
+'newpages' => 'नवà¥\80नपà¥\83षà¥\8dठानि',
 'newpages-username' => 'योजकनामन्:',
 'ancientpages' => 'प्राचीनतमानि पृष्ठानि',
 'move' => 'चाल्यताम्',
@@ -2182,7 +2182,7 @@ See https://www.mediawiki.org/wiki/Manual:Image_Authorization.',
 
 # Watchlist
 'watchlist' => 'मम अवेक्षणसूची',
-'mywatchlist' => 'मम à¤\85वà¥\87à¤\95à¥\8dषणसà¥\82à¤\9aà¥\80',
+'mywatchlist' => 'à¤\85वà¥\87à¤\95à¥\8dषणावलिà¤\83',
 'watchlistfor2' => 'हि $1 $2',
 'nowatchlist' => 'अवलोकनावल्यां पदार्थः नास्ति ।',
 'watchlistanontext' => 'अवलोकनपट्टिकायां पुटं दृष्टुं सम्पादयितुं वा  $1  करोतु ।',
@@ -2399,7 +2399,7 @@ $2 द्वारा सम्पादितां अन्तिमावृ
 'undeleterevision-missing' => 'अमान्या अथवा विलुप्ता पुनरावृत्तिः । भवान् प्रदुष्टानुबन्धयुक्तः अथवा पुनरावृत्तिः पुनस्थापिता अथवा लेखागारात् अपनीता ।',
 'undelete-nodiff' => 'पूर्वतनपुनरावृत्तिः न दृष्टा ।',
 'undeletebtn' => 'पुन्थापयतु ।',
-'undeletelink' => 'दà¥\83शà¥\8dयतामà¥\8d/पà¥\8dरतà¥\8dयानà¥\80यतामà¥\8d',
+'undeletelink' => 'दृश्यताम्/प्रत्यानयताम्',
 'undeleteviewlink' => 'दृश्यताम्',
 'undeleteinvert' => 'चयनं परिवर्तयतु ।',
 'undeletecomment' => 'कारणम् :',
@@ -2428,8 +2428,8 @@ $2 द्वारा सम्पादितां अन्तिमावृ
 'undelete-show-file-submit' => 'आम्',
 
 # Namespace form on various pages
-'namespace' => 'नामाकाशः :',
-'invert' => 'à¤\9aयनà¤\82 à¤µà¤¿à¤ªà¤°à¥\80तà¥\80à¤\95रà¥\8bतà¥\81',
+'namespace' => 'नामाकाशः:',
+'invert' => 'विरà¥\81दà¥\8dधà¤\9aयनमà¥\8d',
 'tooltip-invert' => 'चितनामस्थाने परिवर्तनं गोपयितुं मञ्जूषाम् अर्गलयतु ।',
 'namespace_association' => 'सम्बद्धं नामस्थानम् ।',
 'tooltip-namespace_association' => 'चितनामस्थानेन सह सम्बद्धं विषयनामस्थानम् अथवा सम्भाषणम् अपि उपादातुम् इमां मञ्जूषाम् अर्गलयतु ।',
@@ -2438,7 +2438,7 @@ $2 द्वारा सम्पादितां अन्तिमावृ
 # Contributions
 'contributions' => 'प्रयोक्तॄणां योगदानानि',
 'contributions-title' => '$1 इत्येतस्य कृते योजकानां योगदानानि',
-'mycontris' => 'मम à¤¯à¥\8bà¤\97दानानि',
+'mycontris' => 'योगदानानि',
 'contribsub2' => '$1 इत्येतदर्थम् ($2)',
 'nocontribs' => 'एतादृशयोग्यताभिः समं परिवर्तनानि न दृष्टानि ।',
 'uctop' => '(शीर्षम्)',
@@ -2508,7 +2508,7 @@ $2 द्वारा सम्पादितां अन्तिमावृ
 'ipbenableautoblock' => 'अनेन योजकेन उपयुक्तम् ऐपिसङ्केतम्, अग्रे अनेन योजकेन सम्पादयितुं प्रयतमानम् ऐपिसङ्केतं च स्वयम् अवरुद्धं करोतु ।',
 'ipbsubmit' => 'एतं योजकम् अवरुणद्धु ।',
 'ipbother' => 'अन्यः समयः ।',
-'ipboptions' => '२ à¤¹à¥\8bराà¤\83:2 hours,१ à¤¦à¤¿à¤¨à¤®à¥\8d:1 day,३ à¤¦à¤¿à¤¨à¤¾à¤¨à¤¿:3 days,१ à¤¸à¤ªà¥\8dताहà¤\83:1 week,२ à¤¸à¤ªà¥\8dताहà¥\8c:2 weeks,१ à¤®à¤¾à¤¸à¤\83:1 month,३ à¤®à¤¾à¤¸à¤¾à¤\83:3 months,६ à¤®à¤¾à¤¸à¤¾à¤\83:6 months,१ à¤µà¤°à¥\8dषà¤\83:1 year,अनन्तम्:infinite',
+'ipboptions' => '२ à¤¹à¥\8bरà¥\87:2 hours,१ à¤¦à¤¿à¤¨à¤®à¥\8d:1 day,३ à¤¦à¤¿à¤¨à¤¾à¤¨à¤¿:3 days,१ à¤¸à¤ªà¥\8dताहà¤\83:1 week,२ à¤¸à¤ªà¥\8dताहà¥\8c:2 weeks,१ à¤®à¤¾à¤¸à¤\83:1 month,३ à¤®à¤¾à¤¸à¤¾à¤\83:3 months,६ à¤®à¤¾à¤¸à¤¾à¤\83:6 months,१ à¤µà¤°à¥\8dषमà¥\8d:1 year,अनन्तम्:infinite',
 'ipbhidename' => 'सम्पादनेभ्यः आवलीभ्यः च योजकनाम सङ्गोपयतु ।',
 'ipbwatchuser' => 'अस्य योजकस्य योजकपुटानि सम्भाषणपुटानि च अवलोकयतु ।',
 'ipb-disableusertalk' => 'एतं योजकम् अवरोधकाले स्वस्य सम्भाषणपुटस्य सम्पानात् निवारयतु ।',
@@ -2556,9 +2556,9 @@ $2 द्वारा सम्पादितां अन्तिमावृ
 'blocklist-nousertalk' => 'स्वस्य सम्भाषणपुटं सम्पादयितुं न शक्यते ।',
 'ipblocklist-empty' => 'अवरोधावली रिक्ता अस्ति ।',
 'ipblocklist-no-results' => 'अभ्यर्थितः ऐपिसङ्केतः अथवा अभ्यर्थितः योजकनाम अवरुद्धं न ।',
-'blocklink' => 'à¤\85वरà¥\8bधà¤\83 à¤\95à¥\8dरियताम्',
-'unblocklink' => 'निरà¥\8bधà¤\83 à¤\85पास्यताम्',
-'change-blocklink' => 'विभाà¤\97ः परिवर्त्यताम्',
+'blocklink' => 'à¤\85वरà¥\81दà¥\8dधà¥\8dयताम्',
+'unblocklink' => 'à¤\85वरà¥\8bधà¤\83 à¤¨à¤¿à¤°à¤¸à¥\8dत्यताम्',
+'change-blocklink' => 'à¤\85वरà¥\8bधः परिवर्त्यताम्',
 'contribslink' => 'योगदानम्',
 'emaillink' => 'विद्युन्मानपत्रं प्रेषयतु ।',
 'autoblocker' => 'भवतः ऐपि सङ्केतः स्वयम् अवरुद्धः यः सद्यः काले एव [[User:$1|$1]]" इत्यनेन उपयुक्तः । 
@@ -2687,7 +2687,7 @@ $2 इति प्रकारस्य अवरोधं कर्तुं 
 'movesubpagetext' => '$1 {{PLURAL:$1|उपपुटम्|उपपुटानि }}अस्य पुटस्य उपपुटानि अधः दर्शितानि ।',
 'movenosubpage' => 'अस्य पुटस्य उपपुटानि न सन्ति ।',
 'movereason' => 'कारणम् :',
-'revertmove' => 'पà¥\8dरतिनिवरà¥\8dतà¥\8dयताम्',
+'revertmove' => 'पà¥\8dरतà¥\8dयावरà¥\8dतनम्',
 'delete_and_move' => 'अपमर्जनं चालनं च ।',
 'delete_and_move_text' => '==अपमर्जनम् आवश्यकम्==
 लक्षितपुटं "[[:$1]]" पूर्वमेव अस्ति ।
@@ -2715,7 +2715,7 @@ $2 इति प्रकारस्य अवरोधं कर्तुं 
 'file-exists-sharedrepo' => 'विभक्तकोशे चितसञ्चिकानाम प्रथममेव उपयोगे अस्ति  । अन्यं नाम चिनोतु ।',
 
 # Export
-'export' => 'पà¥\83षà¥\8dठानाà¤\82 à¤¨à¤¿à¤°à¥\8dयातà¤\82 à¤\95रà¥\8bतà¥\81',
+'export' => 'पà¥\83षà¥\8dठानि à¤\85नà¥\8dयतà¥\8dर à¤ªà¥\8dरà¥\87षà¥\8dयतामà¥\8d',
 'exporttext' => 'विशेष पुटस्य पाठम् अथवा सम्पादनेतिहासं निर्हर्तुं शक्नोति । अथवा पुटसमूहम् उपोतं कर्तुमपि शक्नोति ।
 एतत् [[Special:Import|आयातपुटं]] अस्य साहाय्येन मीडियाविक्याः प्रयोगं कृत्वा अन्यविकीतः आयातं कर्तुं शक्नोति ।
 पुटानि नर्हर्तुम् अधो दत्तपाठमञ्जूषायां शीर्शकं लिखतु । एकस्य शीर्षकस्य एका पङ्क्तिः । अपि च वर्तमानावृत्त्या सह प्राचीनावृत्तिमपि इच्छति वा नेति अथवा गतसम्पादनस्य विषयज्ञानेन सह केवलं वर्नमानावृत्तिम् इच्छाति । 
@@ -2831,26 +2831,26 @@ $2 इति प्रकारस्य अवरोधं कर्तुं 
 'javascripttest-qunit-heading' => 'मिडियाविक्याः जवालिपेः Qघटकस्य परीक्षाप्रणाली ।',
 
 # Tooltip help for the actions
-'tooltip-pt-userpage' => 'भवतः योजकपृष्ठम्',
+'tooltip-pt-userpage' => 'भवतः/भवत्याः योजकपृष्ठम्',
 'tooltip-pt-anonuserpage' => 'ऐपिसङ्केतार्थं योजकपुटं भवान् सम्पादयति एवम्..',
-'tooltip-pt-mytalk' => 'भवतः सम्भाषणपृष्ठम्',
+'tooltip-pt-mytalk' => 'भवतः/भवत्याः सम्भाषणपृष्ठम्',
 'tooltip-pt-anontalk' => 'एतस्मात् ऐपिसङ्केतात् सम्पादनस्य परिचर्चा ।',
-'tooltip-pt-preferences' => 'भवतः इष्टतमानि',
-'tooltip-pt-watchlist' => 'भवदà¥\8dभिà¤\83 à¤ªà¤°à¤¿à¤µà¤°à¥\8dतनानि à¤¨à¤¿à¤°à¥\80à¤\95à¥\8dषà¥\8dयमाणानाà¤\82 à¤ªà¥\83षà¥\8dठानाà¤\82 à¤¸à¥\82à¤\9aà¥\80',
-'tooltip-pt-mycontris' => 'भवतः योगदानानाम् आवली',
+'tooltip-pt-preferences' => 'भवतः/भवत्याः इष्टतमानि',
+'tooltip-pt-watchlist' => 'भवतà¤\83/भवतà¥\8dयाà¤\83 à¤¨à¤¿à¤°à¥\80à¤\95à¥\8dषासà¥\82à¤\9aà¥\8dयाà¤\82 à¤µà¤¿à¤¦à¥\8dयमानानाà¤\82 à¤ªà¥\83षà¥\8dठानामà¥\8d à¤\86वलिà¤\83',
+'tooltip-pt-mycontris' => 'भवतः/भवत्याः योगदानस्य आवलिः',
 'tooltip-pt-login' => 'सम्प्रवेशाय प्रोत्सहामहे । परन्तु सम्प्रवेशः ऐच्छिकः ।',
 'tooltip-pt-logout' => 'निर्गमनम्',
 'tooltip-ca-talk' => 'पृष्ठाऽन्तर्गताय विषयाय चर्चा',
 'tooltip-ca-edit' => 'इदं पृष्ठं सम्पादयितुं शक्यते । रक्षणात्पूर्वं कृपया प्राग्दृश्यं दृश्यताम् ।',
-'tooltip-ca-addsection' => 'नà¥\82तनà¤\83 à¤µà¤¿à¤­à¤¾à¤\97à¤\83 à¤\86रभà¥\8dयतामà¥\8d',
-'tooltip-ca-viewsource' => 'इदं पृष्ठं संरक्षितं विद्यते। भवान् अस्य स्रोतः द्रष्टुम् अर्हति।',
+'tooltip-ca-addsection' => 'नूतनविभागः आरभ्यताम्',
+'tooltip-ca-viewsource' => 'इदं पृष्ठं संरक्षितं विद्यते । अस्य स्रोतं द्रष्टुं शक्यते ।',
 'tooltip-ca-history' => 'अस्य पृष्ठस्य पुरातनाऽऽवृत्तिः',
 'tooltip-ca-protect' => 'इदं पृष्ठं संरक्ष्यताम्',
 'tooltip-ca-unprotect' => 'अस्य पुटास्य सुरक्षां परिवर्तयतु ।',
 'tooltip-ca-delete' => 'इदं पृष्ठम् अपाक्रियताम्',
 'tooltip-ca-undelete' => 'अस्य पुटस्य अपमर्जनात् पूर्वम् अस्य सम्पादनानि पुनस्थापयतु ।',
-'tooltip-ca-move' => 'à¤\87दà¤\82 à¤ªà¥\83षà¥\8dठà¤\82 à¤\9aाल्यताम्',
-'tooltip-ca-watch' => 'इदं पृष्ठं भवतः अवेक्षणसूच्यां योज्यताम्',
+'tooltip-ca-move' => 'à¤\85सà¥\8dय à¤ªà¥\83षà¥\8dठसà¥\8dय à¤¨à¤¾à¤® à¤ªà¤°à¤¿à¤µà¤°à¥\8dत्यताम्',
+'tooltip-ca-watch' => 'इदं पृष्ठं भवतः/भवत्याः अवेक्षणावल्यां योज्यताम्',
 'tooltip-ca-unwatch' => 'इदं पृष्ठं भवतः अवेक्षणसूच्याः निष्कास्यताम्',
 'tooltip-search' => '{{SITENAME}} अन्विष्यताम्',
 'tooltip-search-go' => 'समानशिरोनामयुक्तं पृष्ठं विद्यते चेत् तत्र गम्यताम्',
@@ -2885,8 +2885,8 @@ $2 इति प्रकारस्य अवरोधं कर्तुं 
 'tooltip-ca-nstab-category' => 'वर्गाणां पृष्ठं दृश्यताम्',
 'tooltip-minoredit' => 'इदं परिवर्तनं लघुपरिवर्तनरूपेण अङ्क्यताम्',
 'tooltip-save' => 'परिवर्तनानि रक्ष्यन्ताम्',
-'tooltip-preview' => 'भवता कृतानां परिवर्तनानां प्राग्दृश्यं दृश्यताम्, रक्षणात्पूर्वं कृपया इदम् उपयुज्यताम्।',
-'tooltip-diff' => 'पाठà¥\87 à¤­à¤µà¤¤à¤¾ à¤\95à¥\83तानि à¤ªà¤°à¤¿à¤µà¤°à¥\8dतनानि à¤¦à¥\83शà¥\8dयनà¥\8dतामà¥\8d।',
+'tooltip-preview' => 'भवता/भवत्या कृतानां परिवर्तनानां प्राग्दृश्यं दृश्यताम्, रक्षणात्पूर्वं कृपया इदम् उपयुज्यताम्।',
+'tooltip-diff' => 'भवता/भवतà¥\8dया à¤\85तà¥\8dर à¤\95à¥\83तानि à¤ªà¤°à¤¿à¤µà¤°à¥\8dतनानि à¤¦à¥\8dरषà¥\8dà¤\9fà¥\81à¤\82 à¤¶à¤\95à¥\8dयतà¥\87',
 'tooltip-compareselectedversions' => 'पृष्ठस्य द्वयोः चितयोः आवृत्त्योः भेदः दृश्यताम्',
 'tooltip-watch' => 'इदं पृष्ठं भवतः अवेक्षणसूच्यां योज्यताम्',
 'tooltip-watchlistedit-normal-submit' => 'शीर्षकानि अपनयतु ।',
@@ -2898,7 +2898,7 @@ $2 इति प्रकारस्य अवरोधं कर्तुं 
 
 अस्य सारांशे अपाकरणस्य कारणमपि लेखितुं शक्यते ।',
 'tooltip-preferences-save' => 'आद्यताः रक्षतु ।',
-'tooltip-summary' => 'सà¤\82à¤\95à¥\8dषिपà¥\8dतà¤\83 सारांशः योज्यताम्',
+'tooltip-summary' => 'सà¤\99à¥\8dà¤\95à¥\8dषिपà¥\8dतसारांशः योज्यताम्',
 
 # Metadata
 'notacceptable' => 'भवतः ग्रहकस्य पठनेच्छारूपेण विकिवितारकः दत्तपाठं प्रकल्पितुं नैव शक्नोति ।',
@@ -3013,13 +3013,13 @@ $2 इति प्रकारस्य अवरोधं कर्तुं 
 'thumbsize' => 'सङ्कुचितास्य आकारः ।',
 'widthheightpage' => '$1 × $2, $3 {{PLURAL:$1|पुटम्|पुटानि}} प्रयुक्तानि ।',
 'file-info' => 'सञ्चिकाकारः : $1, MIME प्रकारः $2',
-'file-info-size' => '$1 Ã\97 $2 à¤ªà¤¿à¤\95à¥\8dसà¥\87लानि, à¤¸à¤\82चिकायाः आकारः: $3, MIME-प्रकारः: $4',
+'file-info-size' => '$1 Ã\97 $2 à¤\9aितà¥\8dराणवà¤\83 (pixels), à¤¸à¤\9eà¥\8dचिकायाः आकारः: $3, MIME-प्रकारः: $4',
 'file-info-size-pages' => '$1 × $2  पिक्सेल्, सञ्चिकायाः आकारः :  $3 , MIME प्रकारः :  $4 ,  $5   {{PLURAL:$5|पुटम्|पुटानि}}',
 'file-nohires' => 'उच्चतरं विभेदनं नोपलब्धम्',
 'svg-long-desc' => 'SVG संचिका, साधारणतया $1 × $2 पिक्सेलानि, संचिकायाः आकारः : $3',
 'svg-long-desc-animated' => 'आश्वसिता SVG संचिका, साधारणतया $1 × $2 पिक्सेलानि, संचिकायाः आकारः : $3',
 'svg-long-error' => 'एषा अमान्या SVG सञ्चिका : $1',
-'show-big-image' => 'पà¥\82रà¥\8dणà¤\82 à¤µà¤¿à¤­à¥\87दनमà¥\8d',
+'show-big-image' => 'मà¥\82लसà¤\9eà¥\8dà¤\9aिà¤\95ा',
 'show-big-image-preview' => 'अस्य पूर्वावलोकनस्य आकारः : $1',
 'show-big-image-other' => 'अन्याः {{PLURAL:$2| प्रस्तवः|प्रस्तावाः}}:  $1 ।',
 'show-big-image-size' => '$1 × $2  पिक्सेल्',
@@ -3059,10 +3059,10 @@ $2 इति प्रकारस्य अवरोधं कर्तुं 
 पङ्क्त्यां विद्यमाना प्रथमा परिसन्धिः (link) दोषपूर्णया सञ्चिकया सह परिसन्धिता (linked) स्यादेव । तस्यामेव पङ्क्तौ उत्तरोत्तरं विद्यमानाः परिसन्धयः अपवादिताः ज्ञेयाः, अर्थात् अत्र तेषां पृष्ठानाम् आवलिरेव भविष्यति, येषु एषा सञ्चिका विद्यते ।',
 
 # Metadata
-'metadata' => 'à¤\85धिदतà¥\8dतानि',
-'metadata-help' => 'à¤\85सà¥\8dयाà¤\82 à¤¸à¤\9eà¥\8dà¤\9aिà¤\95ायामà¥\8d à¤\85तिरिà¤\95à¥\8dताà¤\83 à¤µà¤¿à¤·à¤¯à¤¾à¤\83 à¤¸à¤¨à¥\8dति, à¤\95दाà¤\9aितà¥\8d à¤\86à¤\82à¤\95िà¤\95-à¤\9bायाà¤\9aितà¥\8dरà¤\97à¥\8dराहà¤\95à¥\87न à¤¸à¥\8dà¤\95à¥\8dयानरà¥\8d à¤\87तà¥\8dयनà¥\87न à¤µà¤¾ à¤¸à¥\8dरषà¥\8dà¤\9fाà¤\83 à¤µà¤¾ à¤\86à¤\82à¤\95िà¤\95à¥\80à¤\95à¥\83ताà¤\83 à¤µà¤¾ à¤¸à¥\8dयà¥\81à¤\83 à¥¤
+'metadata' => 'पà¥\8dरदतà¥\8dताà¤\82शà¤\83 (दतà¥\8dताà¤\82शविषयà¤\95दतà¥\8dताà¤\82शà¤\83 à¤\85यमà¥\8d)',
+'metadata-help' => 'à¤\85नà¥\87न à¤¸à¤¹ à¤µà¤¿à¤¸à¥\8dतà¥\83तमाहितà¥\80 à¤¸à¤²à¥\8dलà¤\97à¥\8dना à¤\85सà¥\8dति, à¤ªà¥\8dरतिबिमà¥\8dबà¤\97à¥\8dराहà¤\95à¥\87न (scanner) à¤\85à¤\99à¥\8dà¤\95à¥\80यà¤\9bायाà¤\9aितà¥\8dरà¤\97à¥\8dराहà¤\95à¥\87न (digital camera ) à¤µà¤¾ à¤\85सà¥\8dयाà¤\83 à¤¸à¤\9eà¥\8dà¤\9aिà¤\95ायाà¤\83 à¤°à¤\9aना à¤\9cाता à¤¸à¥\8dयातà¥\8d à¥¤ 
 
-यदि à¤\8fषा à¤¸à¤\9eà¥\8dà¤\9aिà¤\95ा à¤®à¥\82लावसà¥\8dथातà¤\83 à¤ªà¤°à¤¿à¤µà¤°à¥\8dतिता à¤\85सà¥\8dति, à¤¤à¤°à¥\8dहि à¤\85तà¥\8dर à¤\95ानिà¤\9aिदà¥\8d à¤µà¤¿à¤µà¤°à¤£à¤¾à¤¨à¤¿ à¤ªà¤°à¤¿à¤µà¤°à¥\8dतिताà¤\82 à¤¸à¤\82à¤\9aिà¤\95ाà¤\82 à¤ªà¥\82रà¥\8dणतया à¤¨ à¤ªà¥\8dरदरà¥\8dशयà¥\87यà¥\81à¤\83 ।',
+à¤\8fषा à¤¸à¤\9eà¥\8dà¤\9aिà¤\95ा à¤¯à¤¦à¤¿ à¤®à¥\82लावसà¥\8dथातà¥\8d à¤ªà¤°à¤¿à¤µà¤°à¥\8dतà¥\8dयतà¥\87, à¤¤à¤°à¥\8dहि à¤\85तà¥\8dरसà¥\8dथानि à¤\95ानिà¤\9aितà¥\8d à¤µà¤¿à¤µà¤°à¤£à¤¾à¤¨à¤¿ à¤ªà¤°à¤¿à¤µà¤°à¥\8dतितसà¤\9eà¥\8dà¤\9aिà¤\95ायाà¤\82 à¤ªà¥\82रà¥\8dणतया à¤¨ à¤¦à¥\83शà¥\8dयनà¥\8dतà¥\87 ।',
 'metadata-expand' => 'विस्तारितानि विवरणानि दर्शयतु',
 'metadata-collapse' => 'विस्तारितानि विवरणानि लोपयतु',
 'metadata-fields' => 'अस्मिन् तालिकायां दर्शिता सूचना संचिकायाः अधस्तात् मेटाडाटा इत्यस्मिन् सदा दर्शिता भविष्यति।
index 159079f..a67597c 100644 (file)
@@ -982,8 +982,6 @@ IP-аадырыһа эрэ көстөр.
 'revdelete-show-file-submit' => 'Сөп',
 'revdelete-selected' => "'''[[:$1]] сирэй {{PLURAL:$2|талыллыбыт торума|талыллыбыт торумнара}}:'''",
 'logdelete-selected' => "'''{{PLURAL:$1|Сирэй талыллыбыт историята|Сирэй талыллыбыт историялара}}:'''",
-'revdelete-text' => "'''Сотуллубут барыллар сирэй историятыгар киириэхтэрэ, ол гынан баран сорох барыллар көннөрү киһиэхэ көстүөхтэрэ суоҕа.'''
-{{SITENAME}} дьаһабыллара кистэммит суруктары көрөр уонна сотуллубуту төттөрү төннөрөр кыахтаахтар (эбии хааччахтааһын турбатах буоллаҕына).",
 'revdelete-confirm' => 'Бука диэн кырдьык бу дьайыыны онороргун, содула туох буоларын өйдүүргүн уонна [[{{MediaWiki:Policy-url}}|сиэри]] тутуһаргын бигэргэт.',
 'revdelete-suppress-text' => "Кистээһин маннык түбэлтэлэргэ '''эрэ''' оҥоһуллар:
 
index e7e29dd..7bb2808 100644 (file)
@@ -919,8 +919,6 @@ All'amministratura è ancora possibili [$1 talìari lu confrontu] si nicissariu.
 'revdelete-show-file-submit' => 'Sì',
 'revdelete-selected' => "'''{{PLURAL:$2|Virsioni silizziunata|Virsioni silizziunati}} di [[:$1]]:'''",
 'logdelete-selected' => "'''{{PLURAL:$1|Eventu dû riggistru silizziunatu|Eventi dû riggistru silizziunati}}:'''",
-'revdelete-text' => "'''Li virsioni cancillati rèstanu visìbbili ntâ cronoluggìa dâ pàggina, mentri lu testu cuntinutu nun è accissìbbili a lu pùbbricu.'''
-L'àutri amministratura dû situ ponnu accèdiri comu è gghiè a li cuntinuti ammucciati e ripristinàrili attraversu sta stissa nterfaccia, siddu nun hannu statu mpustati àutri limitazzioni n fasi di nstallazzioni dû situ.",
 'revdelete-suppress-text' => "La rimozzioni havi a essiri utilizzata '''sulu''' ni sti casi:
 * Dati pirsonali inoppurtuni
 *: ''ndirizzi, nnummara di telefunu, codici fiscali, ecc.''",
index aa5f76d..362471b 100644 (file)
@@ -49,9 +49,9 @@ $messages = array(
 'tog-enotifminoredits' => 'Send me ae wab-mail fer wee eedits o pages n files ava',
 'tog-enotifrevealaddr' => 'Shaw ma email address in notification mails',
 'tog-shownumberswatching' => 'Shaw the nummer o watching uisers',
-'tog-oldsig' => 'Existin signatur:',
+'tog-oldsig' => 'Exeestin signatur:',
 'tog-fancysig' => 'Treat signature as wikitext (wioot aen autæmatic airtin)',
-'tog-uselivepreview' => 'Uise live preview (experimental)',
+'tog-uselivepreview' => 'Uise live luik ower (experimental)',
 'tog-forceeditsummary' => 'Gie me ae jottin when Ah dinnae put in aen eidit owerview',
 'tog-watchlisthideown' => 'Skauk ma eidits frae the watchleet',
 'tog-watchlisthidebots' => 'Skauk bot eidits frae the watchleet',
@@ -94,7 +94,7 @@ $messages = array(
 'january' => 'Januair',
 'february' => 'Febuair',
 'march' => 'Mairch',
-'april' => 'Aprile',
+'april' => 'Apryle',
 'may_long' => 'Mey',
 'june' => 'Juin',
 'july' => 'Julie',
@@ -104,7 +104,7 @@ $messages = array(
 'november' => 'November',
 'december' => 'December',
 'january-gen' => 'Januair',
-'february-gen' => 'Februar',
+'february-gen' => 'Febuair',
 'march-gen' => 'Mairch',
 'april-gen' => 'Aprile',
 'may-gen' => 'Mey',
@@ -114,7 +114,7 @@ $messages = array(
 'september-gen' => 'September',
 'october-gen' => 'October',
 'november-gen' => 'November',
-'december-gen' => 'December',
+'december-gen' => 'Dizember',
 'jan' => 'Jan',
 'feb' => 'Feb',
 'mar' => 'Mai',
@@ -157,7 +157,7 @@ $messages = array(
 'listingcontinuesabbrev' => 'cont.',
 'index-category' => "Index't pages",
 'noindex-category' => 'Noindexed pages',
-'broken-file-category' => 'Pages wi broken file airtins',
+'broken-file-category' => 'Pages wi broken file links',
 
 'about' => 'Aboot',
 'article' => 'Content page',
@@ -183,13 +183,13 @@ $messages = array(
 # Vector skin
 'vector-action-addsection' => 'Add topic',
 'vector-action-delete' => 'Delyte',
-'vector-action-move' => 'Flit',
+'vector-action-move' => 'Muiv',
 'vector-action-protect' => 'Fend',
 'vector-action-undelete' => 'Ondelyte',
 'vector-action-unprotect' => 'Chynge protection',
 'vector-view-create' => 'Mak',
 'vector-view-edit' => 'Eedit',
-'vector-view-history' => 'See history',
+'vector-view-history' => 'See histerie',
 'vector-view-view' => 'Read',
 'vector-view-viewsource' => 'View soorce',
 'actions' => 'Actions',
@@ -198,15 +198,15 @@ $messages = array(
 
 'navigation-heading' => 'Navigâtion menu',
 'errorpagetitle' => 'Mistak',
-'returnto' => 'Return tae $1.',
+'returnto' => 'Return til $1.',
 'tagline' => 'Frae {{SITENAME}}',
 'help' => 'Help',
 'search' => 'Rake',
 'searchbutton' => 'Rake',
 'go' => 'Gang',
 'searcharticle' => 'Gang',
-'history' => 'Page history',
-'history_short' => 'History',
+'history' => 'Page histerie',
+'history_short' => 'Histerie',
 'updatedmarker' => 'chynged sin ma hindermast visit',
 'printableversion' => 'Prent version',
 'permalink' => 'Permanent airtin',
@@ -242,15 +242,15 @@ $messages = array(
 'mediawikipage' => 'View message page',
 'templatepage' => 'View template page',
 'viewhelppage' => 'View help page',
-'categorypage' => 'Scance category page',
-'viewtalkpage' => 'Scance ower collogue',
+'categorypage' => 'See categerie page',
+'viewtalkpage' => 'See tauk',
 'otherlanguages' => 'In ither leids',
 'redirectedfrom' => '(Reguidit frae $1)',
-'redirectpagesub' => 'Redirect page',
+'redirectpagesub' => 'Reguidal page',
 'lastmodifiedat' => 'This page wis hindermaist chynged $2, $1.',
 'viewcount' => 'This page haes been accesst $1 {{PLURAL:$1|once|$1 times}}.',
 'protectedpage' => 'Protectit page',
-'jumpto' => 'Lowp tae:',
+'jumpto' => 'Jump til:',
 'jumptonavigation' => 'navigation',
 'jumptosearch' => 'rake',
 'view-pool-error' => 'Sorrie, the servers ar owerlaided at the moment.
@@ -285,7 +285,7 @@ $1',
 'badaccess-group0' => "Ye'r no permited tae dae whit ye hae requestit!",
 'badaccess-groups' => 'The action ye hae requestit is limitit tae uisers in {{PLURAL:$2|the group|ane o the groups}}: $1.',
 
-'versionrequired' => 'Version $1 of MediaWiki requirit',
+'versionrequired' => 'Version $1 o MediaWiki needit',
 'versionrequiredtext' => 'Version $1 o MediaWiki is requirit tae uise this page. Tak a keek at the [[Special:Version|version page]].',
 
 'ok' => 'Okay',
@@ -300,9 +300,9 @@ $1',
 'editold' => 'eedit',
 'viewsourceold' => 'ken soorce',
 'editlink' => 'eedit',
-'viewsourcelink' => 'view soorce',
+'viewsourcelink' => 'see soorce',
 'editsectionhint' => 'Eedit section: $1',
-'toc' => 'Table o contents',
+'toc' => 'Contents',
 'showtoc' => 'shaw',
 'hidetoc' => 'scouk',
 'collapsible-collapse' => 'Collapse.',
@@ -317,7 +317,7 @@ $1',
 'site-atom-feed' => '$1 Atom Feed',
 'page-rss-feed' => '"$1" RSS Feed',
 'page-atom-feed' => '"$1" Atom Feed',
-'red-link-title' => '$1 (page disna exist)',
+'red-link-title' => '$1 (page disna exeest)',
 'sort-descending' => 'Sort descending.',
 'sort-ascending' => 'Sort ascending.',
 
@@ -335,9 +335,9 @@ $1',
 
 # Main script and global functions
 'nosuchaction' => 'Nae sic action',
-'nosuchactiontext' => "The action specifiee'd bi the URL isna recognised
-Ye micht hae mistyped the URL, or follaed a wrang link
-This micht forby be caused by a bug in the saftware uised by {{SITENAME}}.",
+'nosuchactiontext' => 'The action speceefieed bi the URL isna recognised
+Ye micht hae mistyped the URL, or follaed ae wrang link
+This micht forby be caused bi ae bug in the saffware uised bi {{SITENAME}}.',
 'nosuchspecialpage' => 'Nae sic byordinar page',
 'nospecialpagetext' => '<strong>Ye hae requestit aen onvalid byordinar page.</strong>
 
@@ -360,10 +360,10 @@ likelie fer routine database maintenance; efter that it'll be back til normal.
 The admeenstration that lockit it gied this explanation: $1",
 'missing-article' => 'The database didna fynd the tex o ae page that it shid hae foond, cawed "$1" $2.
 
-Maistly this is caused bi follaein aen ootdated diff or histerie link til ae page that haes been delytit.
+Maistlie this is caused bi follaein aen ootdated diff or histerie link til ae page that haes been delytit.
 
 Gif this isna the case, ye micht hae foond ae bug in the saffware.
-Please lat aen [[Special:ListUsers/sysop|admeenistrater]] ken aboot this, makin note o the URL.',
+Please lat aen [[Special:ListUsers/sysop|admeenistrater]] ken aneat this, makin note o the URL.',
 'missingarticle-rev' => '(reveesion#: $1)',
 'missingarticle-diff' => '(Diff: $1, $2)',
 'readonly_lag' => 'The database haes been autaematically lockit while the sclave database servers catch up tae the maister',
@@ -371,8 +371,8 @@ Please lat aen [[Special:ListUsers/sysop|admeenistrater]] ken aboot this, makin
 'internalerror_info' => 'Internal mistak: $1',
 'fileappenderrorread' => 'Coudna read "$1" durin append.',
 'fileappenderror' => 'Coudna append "$1" til "$2".',
-'filecopyerror' => 'Cuidna copy file "$1" tae "$2".',
-'filerenameerror' => 'Cuidna rename file "$1" tae "$2".',
+'filecopyerror' => 'Cuidna copie file "$1" til "$2".',
+'filerenameerror' => 'Cuidna rename file "$1" til "$2".',
 'filedeleteerror' => 'Cuidna delyte file "$1".',
 'directorycreateerror' => 'Culdnae mak directory "$1".',
 'filenotfound' => 'Cuidna fin file "$1".',
@@ -392,14 +392,14 @@ It gae nae explanâtion.',
 'perfcachedts' => 'The follaein data is cached, n wis hindermaist updated $1. Ae maist muckkle o {{PLURAL:$4|yin result is|$4 results ar}} available in the cache.',
 'querypage-no-updates' => 'Updates for this page ar disablit at the meenit. Data here wilnae be refreshit at the meenit.',
 'viewsource' => 'View soorce',
-'viewsource-title' => 'View soorce fer $1',
+'viewsource-title' => 'See soorce fer $1',
 'actionthrottled' => 'Action devalit',
 'actionthrottledtext' => "Aes aen anti-spam meisur, ye'r limitit fae daein this action ower monie times in aen ower short time, n ye'v exceedit this limit. Please try again in ae few minutes.",
-'protectedpagetext' => 'This page haes been protected fer tae prevent eiditing or ither actions.',
+'protectedpagetext' => 'This page haes been protected fer tae hider eeditin or ither actions.',
 'viewsourcetext' => 'Ye can leuk at n copie the soorce o this page:',
 'viewyourtext' => 'Ye can see n copie the soorce o <strong>yer eedits</strong> til this page:',
-'protectedinterface' => 'This page provides interface tex fer the saffware oan this wiki, n is protected fer tae prevent abuise.
-Tae add or chynge owersets fer aw wikis, please uise [//translatewiki.net/ translatewiki.net], the MediaWiki localisation project.',
+'protectedinterface' => 'This page provides interface tex fer the saffware oan this wiki, n is protected fer tae hinder abuise.
+Tae add or chynge owersets fer aw wikis, please uise [//translatewiki.net/ translatewiki.net], the MediaWiki localisation waurk.',
 'editinginterface' => "<strong>Warnishment:</strong> Ye'r eiditing ae page that is uised tae provide interface tex fer the saffware.
 Chynges til this page will affect the appearance o the uiser interface fer ither uisers oan this wiki.
 Tae add or chynge owersets fer aw wikis, please uise [//translatewiki.net/ translatewiki.net], the MediaWiki localisation project.",
@@ -413,13 +413,13 @@ $2',
 'myprivateinfoprotected' => 'Ye dinna hae permeession tae eidit yer private information.',
 'mypreferencesprotected' => 'Ye dinna hae permeession tae eidit yer preferences.',
 'ns-specialprotected' => 'Byordinar pages canna be editit.',
-'titleprotected' => "This teetle haes been protectit frae bein makkit by [[User:$1|$1]].
-The grunds for this are: ''$2''.",
+'titleprotected' => "This teetle haes been protectit fae bein makit bi [[User:$1|$1]].
+The groonds fer this ar: ''$2''.",
 'filereadonlyerror' => 'Canna modify the file "$1" cause the file repository "$2" is in read-yinly mode.
 
 The administrater that lock\'t it affered this explanation: "$3".',
-'invalidtitle-knownnamespace' => 'Onvalid title wi namespace "$2" n tex "$3"',
-'invalidtitle-unknownnamespace' => 'Onvalid title wi onkent namespace nummer $1 n tex "$2"',
+'invalidtitle-knownnamespace' => 'Onvalit title wi namespace "$2" n tex "$3"',
+'invalidtitle-unknownnamespace' => 'Onvalit title wi onkent namespace nummer $1 n tex "$2"',
 'exception-nologin' => 'No loggit in',
 'exception-nologin-text' => 'Please [[Special:Userlogin|log in]] tae be able tae access this page or action.',
 'exception-nologin-text-manual' => 'Please $1 tae be able tae access this page or action.',
@@ -432,19 +432,19 @@ The administrater that lock\'t it affered this explanation: "$3".',
 # Login and logout pages
 'logouttext' => "<strong>Ye'r nou loggit oot.</strong>
 
-Note that some pages micht continue tae be displayed as gif ye were still loggit in, til ye clear yer brouser cache.",
+Mynd that some pages micht continue tae be displeyed aes gif ye were still loggit in, til ye clear yer brouser cache.",
 'welcomeuser' => 'Weelcome, $1!',
-'welcomecreation-msg' => 'Yer accoont haes been creatit.
-Ye can chynge yer {{SITENAME}} [[Special:Preferences|preferences]] gif ye like.',
+'welcomecreation-msg' => 'Yer accoont haes been cræftit.
+Ye can chynge yer {{SITENAME}} [[Special:Preferences|preeferences]] gif ye like.',
 'yourname' => 'Yer uiser name',
 'userlogin-yourname' => 'Uisername',
 'userlogin-yourname-ph' => 'Enter yer uisername',
 'createacct-another-username-ph' => 'Enter the uisername',
-'yourpassword' => 'Passwird:',
+'yourpassword' => 'Passwaird:',
 'userlogin-yourpassword' => 'Passwaird.',
 'userlogin-yourpassword-ph' => 'Enter yer passwaird',
 'createacct-yourpassword-ph' => 'Enter ae passwaird',
-'yourpasswordagain' => 'Retype passwird:',
+'yourpasswordagain' => 'Retype passwaird:',
 'createacct-yourpasswordagain' => 'Confirm passwaird.',
 'createacct-yourpasswordagain-ph' => 'Enter passwaird again.',
 'remembermypassword' => 'Mynd ma login oan this brouser (fer $1 {{PLURAL:$1|day|days}} at the maist)',
@@ -490,7 +490,7 @@ Uise the form ablow tae log in as anither uiser.",
 'createacct-imgcaptcha-ph' => 'Enter the tex ye see abuin',
 'createacct-submit' => 'Mak yer accoont',
 'createacct-another-submit' => 'Mak anither accoont',
-'createacct-benefit-heading' => '{{SITENAME}} is made bi fowk like ye.',
+'createacct-benefit-heading' => '{{SITENAME}} is makit bi fowk like ye.',
 'createacct-benefit-body1' => '{{PLURAL:$1|eidit|eidits}}',
 'createacct-benefit-body2' => '{{PLURAL:$1|page|pages}}.',
 'createacct-benefit-body3' => 'recent {{PLURAL:$1|contreebuter|contreebuters}}',
@@ -506,17 +506,17 @@ Ensure that ye have cookies enabled, relaid this page n gie it anither shote.',
 'noname' => "Ye hivna specifee'd a valid uisername.",
 'loginsuccesstitle' => 'Login fine',
 'loginsuccess' => 'Ye\'re nou loggit in tae {{SITENAME}} as "$1".',
-'nosuchuser' => 'The\'r nae sic uiser as "$1".
-Uiser names are case-sensitive.
-Check yer spellin, or uise [[Special:UserLogin/signup|mak a new accoont]].',
+'nosuchuser' => 'Thaur\'s nae sic uiser aes "$1".
+Uiser names ar case-sensiteeve.
+Check yer speelin, or [[Special:UserLogin/signup|mak ae new accoont]].',
 'nosuchusershort' => 'The\'r nae sic uiser as "$1". Check yer spellin.',
-'nouserspecified' => 'Ye hae tae merk up a uisername.',
+'nouserspecified' => 'Ye hae tae merk up ae uisername.',
 'login-userblocked' => 'Uiser "$1" is blockit. Log-in naw permitit.',
 'wrongpassword' => 'The password ye entered is wrang. Please gie it anither shot.',
 'wrongpasswordempty' => 'The password ye entered is blank. Please gie it anither shot.',
 'passwordtooshort' => 'Yer password is ower short.
 It maun hae at laest {{PLURAL:$1|1 chairacter|$1 chairacters}}.',
-'password-name-match' => 'Yer password maun be different fae yer uisername.',
+'password-name-match' => 'Yer passwaird maun be different fae yer uisername.',
 'password-login-forbidden' => 'The uise o this uisername n passwaird haes been ferbidden.',
 'mailmypassword' => 'Reset password',
 'passwordremindertitle' => 'Password reminder frae {{SITENAME}}',
@@ -528,8 +528,8 @@ Gif some ither bodie makit this request, or gif ye hae myndit yer passwaird, n y
 'noemail' => 'Thaur\'s nae wab-mail address recordit fer uiser "$1".',
 'noemailcreate' => 'Ye need tae provide ae valid wab-mail address.',
 'passwordsent' => 'A new password haes been sent tae the e-mail address registert for "$1". Please log in again efter ye receive it.',
-'blocked-mailpassword' => 'Yer IP address is blockit frae editin, sae it
-canna uise the password recovery function, for tae prevent abuiss.',
+'blocked-mailpassword' => 'Yer IP address is blockit fae eeditin, sae it
+canna uise the passwaird recoverie function, for tae hinder abuiss.',
 'eauthentsent' => "Ae confirmation wab-mail haes been sent til the speceefied wab-mail address.
 Afore oni ither wab-mail is sent til the accoont, ye'll hae tae follae the instructions in the wab-mail, sae as tae confirm that the accoont is reallie yers.",
 'throttled-mailpassword' => 'Ae password reset wab-mail haes awreadie been sent, wiin the laist {{PLURAL:$1|hoor|$1 hoors}}.
@@ -546,7 +546,7 @@ Nae wab-mail will be sent fer oni o the follaein features.',
 Please enter ae weel-formattit address or mak that field tuim.',
 'cannotchangeemail' => 'Accoont wab-mail addresses canna be chynged oan this wiki.',
 'emaildisabled' => 'This site canna send wab-mails.',
-'accountcreated' => 'Accoont creatit',
+'accountcreated' => 'Accoont cræftit',
 'accountcreatedtext' => 'The uiser accoont fer [[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|tauk]]) haes been cræftit.',
 'createaccount-title' => 'Accoont makin for {{SITENAME}}',
 'createaccount-text' => 'Somebodie cræftit aen accoont fer yer wab-mail address oan {{SITENAME}} ($4) named "$2", wi passwaird "$3".
@@ -554,14 +554,15 @@ Ye shid log in n chynge yer passwaird nou.
 
 Ye can ignore this message, gif this accoont wis cræftit bi mistak.',
 'usernamehasherror' => 'Uisername canna contain hash chairacters',
-'login-throttled' => "Ye'v made ower moni recent login attempts.
-Please wait $1 afore trying again.",
+'login-throttled' => "Ye'v makit ower monie recynt login attempts.
+Please wait $1 afore giein it anither gae.",
 'login-abort-generic' => 'Yer login wisna successful - Aborted',
 'loginlanguagelabel' => 'Leid: $1',
 'suspicious-userlogout' => 'Yer request tae log oot wis denied cause it luiks like it wis sent bi ae broken brouser or caching proxy.',
 'createacct-another-realname-tip' => 'Real name is aen optie.
 Gif ye chuise tae provide it, this will be uised fer giein the uiser attreebution fer their wark.',
 'pt-login' => 'Log in',
+'pt-login-button' => 'Log in',
 'pt-createaccount' => 'Mak accoont',
 'pt-userlogout' => 'Log oot',
 
@@ -572,15 +573,15 @@ Gif ye chuise tae provide it, this will be uised fer giein the uiser attreebutio
 
 # Change password dialog
 'changepassword' => 'Chynge password',
-'resetpass_announce' => 'Tae finish loggin in, ye maun set ae new password.',
+'resetpass_announce' => 'Tae finish loggin in, ye maun set ae new passwaird.',
 'resetpass_header' => 'Chynge accoont password',
-'oldpassword' => 'Auld password',
+'oldpassword' => 'Auld passwaird',
 'newpassword' => 'New passwaird:',
 'retypenew' => 'Retype new passwaird:',
 'resetpass_submit' => 'Set passwaird n log in',
 'changepassword-success' => 'Yer passwaird chynge wis braw!',
-'changepassword-throttled' => "Ye'v made ower moni recent login attempts.
-Please wait $1 afore trying again.",
+'changepassword-throttled' => "Ye'v makit ower monie recynt login attempts.
+Please wait $1 afore giein it anither gae.",
 'resetpass_forbidden' => 'Passwords canna be chynged',
 'resetpass-no-info' => 'Ye maun be loggit in tae access this page directly.',
 'resetpass-submit-loggedin' => 'Chynge passwaird',
@@ -639,8 +640,8 @@ Temperie passwaird: $2',
 'changeemail-password' => 'Yer {{SITENAME}} passwaird:',
 'changeemail-submit' => 'Chynge wab-mail',
 'changeemail-cancel' => 'Cancel.',
-'changeemail-throttled' => "Ye'v made ower moni recent login attempts.
-Please wait $1 afore trying again.",
+'changeemail-throttled' => "Ye'v makit ower monie recynt login attempts.
+Please wait $1 afore giein it anither gae.",
 
 # Special:ResetTokens
 'resettokens' => 'Reset tokens.',
@@ -681,15 +682,15 @@ Ye shid dae it gif ye accidentally shaired theim wi somebodie or gif yer accoont
 'minoredit' => 'This is ae smaa eedit',
 'watchthis' => 'Leuk ower this page',
 'savearticle' => 'Hain page',
-'preview' => 'Scance',
-'showpreview' => 'Scance ower',
+'preview' => 'Luikower',
+'showpreview' => 'Shaw luikower',
 'showlivepreview' => 'Live leuk ower',
 'showdiff' => 'Shaw chynges',
 'anoneditwarning' => "<strong>Warnishment:</strong>Ye'r naw loggit in. Yer IP address will be recordit in this page's eedit histerie.",
-'anonpreviewwarning' => "<em>Ye'r no loggit in. hainin will record yer IP address in this page's eidit history.</em>",
+'anonpreviewwarning' => "<em>Ye'r no loggit in. Hainin will record yer IP address in this page's eedit histerie.</em>",
 'missingsummary' => '<strong>Mynd:</strong> Ye\'v naw gien aen eedit owerview. Gif ye clap oan "{{int:savearticle}}" again, yer eedit will be haint wioot ane.',
 'missingcommenttext' => 'Please enter a comment ablo.',
-'missingcommentheader' => '<strong>Mynd:</strong> Ye\'v naw provided ae subject/heidline fer this comment.
+'missingcommentheader' => '<strong>Mynd:</strong> Ye\'v na gien ae subject/heidline fer this comment.
 Gif ye clap "{{int:savearticle}}" again, yer eedit will be hained wioot yin.',
 'summary-preview' => 'Ootline leuk ower:',
 'subject-preview' => 'Subject/headline leuk ower:',
@@ -707,34 +708,34 @@ Ye can contact $1 or anither [[{{MediaWiki:Grouppage-sysop}}|admeenistrater]] ta
 Ye canna uise the "wab-mail this uiser" feature onless ae valid wab-mail address is speceefied in yer [[Special:Preferences|accoont preferences]] n ye\'v naw been blockit fae uisin it.
 Yer current IP address is $3, n the block ID is #$5.
 Please incluide aw the abuin details in onie speirins that ye mak.',
-'autoblockedtext' => 'Yer IP address haes been autæmaticly blockit cause it wis uised bi anither uiser, wha wis blockit bi $1.
-The raison gieen is:
+'autoblockedtext' => 'Yer IP address haes been autæmateeclie blockit cause it wis uised bi anither uiser that wis blockit bi $1.
+The raison gien is:
 
 :<em>$2</em>
 
 * Stairt o block: $8
-* Expiry o block: $6
+* Expirie o block: $6
 * Intended blockee: $7
 
-Ye can contact $1 or yin o the ither [[{{MediaWiki:Grouppage-sysop}}|admeenistræters]] tae discuss the block.
+Ye can contact $1 or yin o the ither [[{{MediaWiki:Grouppage-sysop}}|admeenistraters]] tae discuss the block.
 
-Note that ye canna uise the "wab-mail this uiser" feature onless ye hae ae valid wab-mail address registered in yer [[Special:Preferences|uiser preferences]] an ye haena been blockit fae uising it.
+Mynd that ye canna uise the "wab-mail this uiser" feature onless ye hae ae valid wab-mail address registered in yer [[Special:Preferences|uiser preeferances]] n ye\'v na been blockit fae uisin it.
 
-Yer current IP address is $3, an the block ID is #$5.
-Please inclæde aw abuin details in oni speirins ye mak.',
+Yer current IP address is $3, n the block ID is #$5.
+Please incluid aw abuin details in onie speirins that ye mak.',
 'blockednoreason' => 'nae grunds put',
-'whitelistedittext' => 'Ye hae tae $1 tae edit pages.',
+'whitelistedittext' => 'Pleas $1 tae eedit pages.',
 'confirmedittext' => 'Ye maun confirm yer wab-mail address afore eeditin pages. Please set n validate yer wab-mail address throogh yer [[Special:Preferences|uiser settins]].',
 'nosuchsectiontitle' => 'Canna find section',
-'nosuchsectiontext' => 'Ye tried tae eidit ae section that disna exist.
-It micht hae been muived or delytit while ye were viewing the page.',
+'nosuchsectiontext' => 'Ye tried tae eedit ae section that disna exeest.
+It micht hae been muived or delytit while ye were luikin at the page.',
 'loginreqtitle' => 'Login Requirit!',
 'loginreqlink' => 'log in',
-'loginreqpagetext' => 'Ye maun $1 tae view ither pages.',
+'loginreqpagetext' => 'Please $1 tae see ither pages.',
 'accmailtitle' => 'Passwaird sent.',
 'accmailtext' => 'Ae randomly generated passwaird fer [[User talk:$1|$1]] haes been sent til $2. It can be chynged oan the <em>[[Special:ChangePassword|chynge passwaird]]</em> page upo loggin in.',
 'newarticle' => '(New)',
-'newarticletext' => "Ye'v follaed ae link til ae page that disna exist yet. Tae mak the page, stairt typin in the kist ablo (see the [[{{MediaWiki:Helppage}}|heelp page]] fer mair info). Gif ye'r here bi mistak, juist clap yer brouser's '''back''' button.",
+'newarticletext' => "Ye'v follaed ae link til ae page that disna exeest yet. Tae cræft the page, stairt typin in the kist ablo (see the [[{{MediaWiki:Helppage}}|heelp page]] fer mair info). Gif ye'r here bi mistak, jist clap yer brouser's <strong>back</strong> button.",
 'anontalkpagetext' => "----
 <em>This is the discussion page fer aen anonymoos uiser that's naw cræftit aen accoont yet, or that disna uise it.</em>
 We maun therefore uise the numerical IP address tae identifie him/her.
@@ -746,14 +747,14 @@ Ye can [[Special:Search/{{PAGENAME}}|rake fer this page teitle]] in ither pages,
  or [{{fullurl:{{FULLPAGENAME}}|action=edit}} eidit this page].</span>',
 'noarticletext-nopermission' => 'There isna oni tex in this page the nou.
 Ye can [[Special:Search/{{PAGENAME}}|rake fer this page title]] in ither pages, or <span class="plainlinks">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} rake the relatit logs]</span>, but ye dina hae permeession tae mak this page.',
-'missing-revision' => 'The reveesion #$1 o the page named "{{PAGENAME}}" disna exist.
+'missing-revision' => 'The reveesion #$1 o the page named "{{PAGENAME}}" disna exeest.
 
-This is usuallie caused bi follaein aen ootdated histerie link til ae page that haes been delytit.
+This is uissuallie caused bi follaein aen ootdated histerie link til ae page that haes been delytit.
 Details can be foond in the [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} delytion log].',
 'userpage-userdoesnotexist' => 'Uiser accoont "<nowiki>$1</nowiki>" hasnae been registerit. Please check gin ye wint tae mak or eidit this page.',
 'userpage-userdoesnotexist-view' => 'Uiser accoont "$1" isna registered.',
-'blocked-notice-logextract' => 'This uiser is currently blockit.
-The latest block log entry is provided ablow fer reference:',
+'blocked-notice-logextract' => 'This uiser is nou blockit.
+The laitest block log entrie is gien ablo fer referance:',
 'clearyourcache' => "<strong>Tak tent:</strong> Efter hainin, ye micht hae tae bipass yer brouser's cache tae see the chynges.
 * <strong>Firefox / Safari:</strong> Haud <em>Shift</em> while clapin <em>Relaid</em>, or press either <em>Ctrl-F5</em> or <em>Ctrl-R</em> (<em>⌘-R</em> oan ae Mac)
 * <strong>Google Chrome:</strong> Press <em>Ctrl-Shift-R</em> (<em>⌘-Shift-R</em> on a Mac)
@@ -774,7 +775,7 @@ It's no been hained yet!</strong>",
 'previewnote' => '<strong>Mynd that this is yinly ae scænce-ower.</strong>
 Yer chynges hae no been hained yet!',
 'continue-editing' => 'Gae til eiditing area',
-'previewconflict' => 'This scance reflects the tex in the upper tex eiditin area like it will kythe gin ye chuise tae hain.',
+'previewconflict' => 'This luikower reflects the tex in the upper tex eeditin airt like it will kith gif ye chuise tae hain.',
 'session_fail_preview' => "'''Sairy! We culdnae process yer eidit acause o ae loss o term data.'''
 Please gie it anither gae. Gin it disnae wairk still, gie [[Special:UserLogout|loggin oot]] n loggin back in again ae gae.",
 'session_fail_preview_html' => '<strong>Sairrie! We coudna process yer eedit cause o ae loss o session data.</strong>
@@ -783,9 +784,9 @@ Please gie it anither gae. Gin it disnae wairk still, gie [[Special:UserLogout|l
 
 <strong>Gif this is ae legeetimate eedit attempt, please gei it anither gae.</strong>
 Gif it still disna wairk, try [[Special:UserLogout|loggin oot]] n loggin back in.',
-'token_suffix_mismatch' => '<strong>Yer eidit haes been rejectit acause yer client made ae richt mess o the punctuation characters in the eidit token.</strong>
-The eidit haes been rejectit tae hinder corruption o the page tex.
-This whiles happens when ye ar uisin ae bruken web-based anonymous proxie service.',
+'token_suffix_mismatch' => "<strong>Yer eedit haes been rejectit cause yer client makit ae richt mess o the punctuation chairacters in the eedit token.</strong>
+The eedit haes been rejectit tae hinder rot o the page tex.
+This whiles happens when ye'r uisin ae broken wab-based anonymoos proxie service.",
 'edit_form_incomplete' => '<strong>Some pairts o the eedit form didna reach the server; dooble-check that yer edits ar intact n gie it anither gae.</strong>',
 'editing' => 'Editin $1',
 'creating' => 'Makin $1',
@@ -814,13 +815,13 @@ It canna be hained.",
 Ye micht wish tae copie n paste yer tex intil ae tex file n hain it fer later.
 
 The admeenistræter that lockit it affered this explanation: $1",
-'protectedpagewarning' => '<strong>Warnishment: This page haes been protectit sae that yinly uisers wi admeenistræter preevileges can eidit it.</strong>
-The latest log entrie is provided ablo fer reference:',
-'semiprotectedpagewarning' => '<strong>Note:</strong> This page haes been protected sae that yinly registered uisers can eidit it.
-The latest log entry is provided ablow fer reference:',
+'protectedpagewarning' => '<strong>Warnishment: This page haes been protectit sae that yinlie uisers wi admeenistrater preevileges can eedit it.</strong>
+The latest log entrie is gien ablo fer referance:',
+'semiprotectedpagewarning' => '<strong>Mynd:</strong> This page haes been protectit sae that yinlie registered uisers can eedit it.
+The latest log entrie is gien ablo fer referance:',
 'cascadeprotectedwarning' => '<strong>Warnishment:</strong> This page haes been lockit sae that yinlie uisers wi admeenisræter richts can eidit it, acause it is inclædit in the follaein cascade-protectit {{PLURAL:$1|page|pages}}:',
-'titleprotectedwarning' => '<strong>Warnishment: This page haes been protected sae that [[Special:ListGroupRights|speecific richts]] ar needed tae mak it.</strong>
-The laitest log entry is provided ablo fer reference:',
+'titleprotectedwarning' => '<strong>Warnishment: This page haes been protectit sae that [[Special:ListGroupRights|speceefic richts]] ar needed tae cræft it.</strong>
+The laitest log entrie is gien ablo fer referance:',
 'templatesused' => '{{PLURAL:$1|Template|Templates}} uised oan this page:',
 'templatesusedpreview' => '{{PLURAL:$1|Template|Templates}} uised in this scænce-ower:',
 'templatesusedsection' => '{{PLURAL:$1|Template|Templates}} uised in this section:',
@@ -840,14 +841,14 @@ Ye can gang back n eedit aen exestin page, or [[Special:UserLogin|log in or cræ
 Ye shid check that it is guid tae keep eeditin this page.
 The delytion n muiv log fer this page is providit here fer conveeniance:",
 'moveddeleted-notice' => 'This page haes been delytit. 
-The delytion n muiv log fer the page ar providit ablo fer referance.',
+The delytion n muiv log fer the page ar gien ablo fer referance.',
 'log-fulllog' => 'View ful log',
 'edit-hook-aborted' => 'Eedit abortit bi huik.
 It gae naw explanation.',
 'edit-gone-missing' => 'Coudna update the page.
-It appears tae hae been deletit.',
+It appears tae hae been delytit.',
 'edit-conflict' => 'Eedit confleect.',
-'edit-no-change' => 'Yer eedit wis ignored cause nae chynge wis made til the tex.',
+'edit-no-change' => 'Yer eedit wis ignored cause nae chynge wis makit til the tex.',
 'postedit-confirmation' => 'Yer eedit wis hained.',
 'edit-already-exists' => 'Coudna mak ae new page.
 It awreadie exists.',
@@ -869,8 +870,8 @@ Gif ye\'r loggit in, ye can disable this warnishment in the "{{int:prefs-editing
 
 It shid hae less than $2 {{PLURAL:$2|caw|caws}}, thaur {{PLURAL:$1|is nou $1 caw|ar noo $1 caws}}.',
 'expensive-parserfunction-category' => 'Pages wi ower moni expensive parser function caws',
-'post-expand-template-inclusion-warning' => "'''Wairnin:''' Template include size is tae lairge. 
-Some templates wull nae be included.",
+'post-expand-template-inclusion-warning' => '<strong>Warnishment Template incluid size is owermuckle. 
+Some templates will na be incluidit.',
 'post-expand-template-inclusion-category' => 'Pages whaur template include size is exceeded',
 'post-expand-template-argument-warning' => '<strong>Warnishment:</strong> This page hauds at least the ae template argument that haes aen ower muckle expansion size.
 Thir arguments hae been left oot.',
@@ -889,16 +890,16 @@ Thir arguments hae been left oot.',
 # "Undo" feature
 'undo-success' => 'The eidit can be ondun. Please check the chynges albo tae check that this is whit ye wint tae dae, n than hain the chynges albo tae be duin ondaein the eidit.',
 'undo-failure' => 'The edit culdnae be undone acause o conflictin edits inatween.',
-'undo-norev' => 'The eidit coudna be ondone cause it disna exist or wis deletit.',
+'undo-norev' => 'The eedit coudna be ondun cause it disna exeest or wis delytit.',
 'undo-nochange' => 'The edit appears tae hae awready been ondone.',
 'undo-summary' => 'Ondae reveesion $1 bi [[Special:Contributions/$2|$2]] ([[User talk:$2|Tauk]])',
 'undo-summary-username-hidden' => "Ondae reveesion $1 bi ae skauk't uiser",
 
 # Account creation failure
 'cantcreateaccounttitle' => 'Canna mak accoont',
-'cantcreateaccount-text' => "Accoont makkin frae this IP address ('''$1''') haes been blockit by [[User:$3|$3]].
+'cantcreateaccount-text' => "Accoont cræftin fae this IP address ('''$1''') haes been blockit bi [[User:$3|$3]].
 
-The grund for this, given by $3 is ''$2''",
+The raison fer this, gien bi $3 is ''$2''",
 'cantcreateaccount-range-text' => "Accoont cræftin fae IP addresses in the range '''$1''', that inclædes yer IP address ('''$4'''), haes been blockit bi [[User:$3|$3]].
 
 The raison gien bi $3 is ''$2''",
@@ -906,13 +907,13 @@ The raison gien bi $3 is ''$2''",
 # History pages
 'viewpagelogs' => 'Leuk at logs fer this page',
 'nohistory' => "Thaur's nae eedit histerie fer this page.",
-'currentrev' => 'Current reveision',
+'currentrev' => 'Reveesion the nou',
 'currentrev-asof' => 'Latest reveesion aes o $1',
-'revisionasof' => 'Reveision as o $1',
+'revisionasof' => 'Reveesion aes o $1',
 'revision-info' => 'Reveesion aes o $1 bi $2',
-'previousrevision' => '← Aulder reveision',
-'nextrevision' => 'Newer reveision →',
-'currentrevisionlink' => 'see current reveision',
+'previousrevision' => '← Aulder reveesion',
+'nextrevision' => 'Newer reveesion →',
+'currentrevisionlink' => 'Latest reveesion',
 'cur' => 'nou',
 'next' => 'neist',
 'last' => 'hind',
@@ -920,8 +921,8 @@ The raison gien bi $3 is ''$2''",
 'page_last' => 'hindermaist',
 'histlegend' => 'Diff selection: Maurk the radio kists o the reveesions tae compare n hit enter or the button at the bottom.<br />
 Legend: <strong>({{int:cur}})</strong> = differance wi laitest reveesion, <strong>({{int:last}})</strong> = differance wi preceedin reveesion, <strong>{{int:minoreditletter}}</strong> = smaa eidit.',
-'history-fieldset-title' => 'Browse history',
-'history-show-deleted' => 'Deletit only',
+'history-fieldset-title' => 'Brouse histerie',
+'history-show-deleted' => 'Delytit yinlie',
 'histfirst' => 'auldest',
 'histlast' => 'newest',
 'historysize' => '({{PLURAL:$1|1 byte|$1 bytes}})',
@@ -965,18 +966,20 @@ Ye can still [$1 view this diff] gif ye wish tee proceed.',
 Ye can see this diff; details can be foond in the [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} delytion log].",
 'rev-suppressed-diff-view' => 'Yin o the reveesions o this diff haes been <strong>suppressed</strong>.
 Ye can view this diff; details can be foond in the [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} suppression log].',
-'rev-delundel' => 'chynge veesibility',
+'rev-delundel' => 'chynge veesibilitie',
 'rev-showdeleted' => 'shaw',
 'revisiondelete' => 'Delyte/ondelyte reveesions',
 'revdelete-nooldid-title' => 'Onvalid target reveesion',
 'revdelete-nooldid-text' => "Aither ye'v naw speceefied ae tairget reveesion(s) tae perform this function, the speceefied reveesion disna exeest, or ye'r attemptin tae skauk the Nou reveesion.",
-'revdelete-no-file' => 'The file speecified disna exist.',
-'revdelete-show-file-confirm' => 'Ar ye sair ye wish tae view ae deletit reveesion o the file "<nowiki>$1</nowiki>" fae $2 at $3?',
+'revdelete-no-file' => 'The file speceefied disna exeest.',
+'revdelete-show-file-confirm' => 'Ar ye sair ye wish tae see ae delytit reveesion o the file "<nowiki>$1</nowiki>" fae $2 at $3?',
 'revdelete-show-file-submit' => 'Ai',
 'revdelete-selected' => '<strong>{{PLURAL:$2|Selected reveesion|Selected reveesions}} o [[:$1]]:</strong>',
 'logdelete-selected' => "'''{{PLURAL:$1|Selectit log event|Selectit log events}}:'''",
-'revdelete-text' => '<strong>Delytit reveesions n events will still kyth in the page histerie n logs, but pairts o thair content will be onaccessible til the publeec.</strong>
-Ither admeenistraters oan {{SITENAME}} will still be able tae access the skaukt content n can ondelyte it again throogh this same interface, onless addeetional restreections ar set.',
+'revdelete-text-text' => 'Delytit reveesions will still kith in the page histerie, bit pairts o thair content will be onaccessible til the publeec.',
+'revdelete-text-file' => 'Delytit file versions will still kith in the file histerie, bit pairts o thair content will be onaccessible til the publeec.',
+'logdelete-text' => 'Delytit log events will still kith in the logs, bit pairts o thair content will be onaccessible til the publeec.',
+'revdelete-text-others' => 'Ither admeenistraters oan {{SITENAME}} will still be able tae access the skaukt content n can ondelyte it again throoch this same interface, onless addeetional restreections ar set.',
 'revdelete-confirm' => "Please confirm that ye'r ettlin tae dae this, that ye unnerstaunn the consequences, n that ye'r daein this in accordance wi [[{{MediaWiki:Policy-url}}|the policie]].",
 'revdelete-suppress-text' => 'Suppression shid <strong>yinly</strong> be uised fer the follaein cases:
 * poteentiallie libeloos information
@@ -1002,9 +1005,9 @@ $1',
 'logdelete-success' => '<strong>Log veesibeelitie successfully set.</strong>',
 'logdelete-failure' => '<strong>Log veesibddlitie coudna be set:</strong>
 $1',
-'revdel-restore' => 'change visibility',
-'pagehist' => 'Page history',
-'deletedhist' => 'Deletit histerie',
+'revdel-restore' => 'chynge veesibeelitie',
+'pagehist' => 'Page histerie',
+'deletedhist' => 'Delytit histerie',
 'revdelete-hide-current' => "Mistak skaukin the eitem dated $2, $1: This is the current reveesion.
 It cannna be skauk't.",
 'revdelete-show-no-access' => 'Mistak shawin the eitem dated $2, $1: This eitem haes been maurked "restreected".
@@ -1015,7 +1018,7 @@ Ye dinna hae access til it.',
 'revdelete-no-change' => '<strong>Warnishment:</strong> The eetem dated $2, $1 awreadie haed the requested veesibeelitie settins.',
 'revdelete-concurrent-change' => "Mistak modifiein the eitem dated $2, $1: Its status appears tae'v been chynged bi some ither bodie while ye attempted tae modifie it.
 Please check the logs.",
-'revdelete-only-restricted' => 'Mistak hidin the eetem dated $2, $1: Ye canna suppress eetems fae sicht bi admeenistraters wioot selectin yin o the ither veesibeelitie opties ava.',
+'revdelete-only-restricted' => 'Mistak skaukin the eetem dated $2, $1: Ye canna suppress eetems fae sicht bi admeenistraters wioot selectin yin o the ither veesibeelitie opties ava.',
 'revdelete-reason-dropdown' => '*Commyn delete raisons
 ** Copiericht violation
 ** Onappropriate comment or personal information
@@ -1040,15 +1043,15 @@ Mak sair that this chynge will maintain historical page conteenuitie.',
 'mergehistory-into' => 'Destinâtion page:',
 'mergehistory-list' => 'Mergeable eidit histerie',
 'mergehistory-merge' => 'The follaein reveesions o [[:$1]] can be merged intil [[:$2]].
-Uise the radio button column tae merge in yinly the reveesions makit at n afore the speecified time.
-Mynd that uisin the navigâtion links will reset this column.',
+Uise the radio button column tae merge in yinlie the reveesions cræftit at n afore the speceefied time.
+Mynd that uisin the naveegation links will reset this column.',
 'mergehistory-go' => 'Shaw mergeable eidits',
 'mergehistory-submit' => 'Merge reveesions',
 'mergehistory-empty' => 'Naw reveesions can be merged.',
 'mergehistory-success' => '$3 {{PLURAL:$3|reveesion|reveesions}} o [[:$1]] successfully merged intil [[:$2]].',
 'mergehistory-fail' => 'Onable tae perform histerie merge, please recheck the page n time parameters.',
-'mergehistory-no-source' => 'Source page $1 disna exist.',
-'mergehistory-no-destination' => 'Destinâtion page $1 disna exist.',
+'mergehistory-no-source' => 'Soorce page $1 disna exeest.',
+'mergehistory-no-destination' => 'Destination page $1 disna exeest.',
 'mergehistory-invalid-source' => 'Source page maun be ae valid title.',
 'mergehistory-invalid-destination' => 'Destinâtion page maun be ae valid title.',
 'mergehistory-autocomment' => 'Merged [[:$1]] intil [[:$2]]',
@@ -1064,13 +1067,13 @@ Mynd that uisin the navigâtion links will reset this column.',
 
 # Diffs
 'history-title' => 'Reveesion histerie o "$1"',
-'difference-title' => 'Difference atween reveesions of "$1"',
+'difference-title' => 'Difference atween reveesions o "$1"',
 'difference-title-multipage' => 'Difference atween pages "$1" n "$2"',
 'difference-multipage' => '(Difference atween pages)',
 'lineno' => 'Line $1:',
 'compareselectedversions' => 'Compare selectit versions',
 'showhideselectedversions' => 'Chynge veesibeelitie o selected reveesions',
-'editundo' => 'undo',
+'editundo' => 'ondae',
 'diff-empty' => '(Naw difference)',
 'diff-multi-sameuser' => '({{PLURAL:$1|yin intermeediate reveesion|$1 intermeediate reveesions}} bi the same uiser naw shawn)',
 'diff-multi-otherusers' => '({{PLURAL:$1|yin intermeediate reveesion|$1 intermeediate reveesions}} bi {{PLURAL:$2|yin ither uiser|$2 uisers}} no shawn)',
@@ -1082,7 +1085,7 @@ Details can be foond in the [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENA
 
 # Search results
 'searchresults' => 'Rake results',
-'searchresults-title' => 'Rake affcome fer "$1"',
+'searchresults-title' => 'Rake ootcome fer "$1"',
 'toomanymatches' => 'Ower moni matches were returned, please try ae different speirin',
 'titlematches' => 'Airticle teitle matches',
 'textmatches' => 'Page tex matches',
@@ -1094,7 +1097,7 @@ Details can be foond in the [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENA
 'shown-title' => 'Shaw $1 {{PLURAL:$1|ootcome|ootcomes}} per page',
 'viewprevnext' => 'View ($1 {{int:pipe-separator}} $2) ($3)',
 'searchmenu-exists' => "'''There is a page named \"[[:\$1]]\" oan this wiki.'''",
-'searchmenu-new' => '<strong>Cræft the page "[[:$1]]" oan this wiki!</strong> {{PLURAL:$2|0=|See the page foond wi yer rake ava.|See the rake affcome foond ava.}}',
+'searchmenu-new' => '<strong>Cræft the page "[[:$1]]" oan this wiki!</strong> {{PLURAL:$2|0=|See the page foond wi yer rake ava.|See the rake ootcome foond ava.}}',
 'searchprofile-articles' => 'Content pages',
 'searchprofile-project' => 'Heelp n Waurk pages',
 'searchprofile-images' => 'Multimedia',
@@ -1108,21 +1111,21 @@ Details can be foond in the [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENA
 'search-result-size' => '$1 ({{PLURAL:$2|1 word|$2 words}})',
 'search-result-category-size' => '{{PLURAL:$1|1 member|$1 members}} ({{PLURAL:$2|1 subcategory|$2 subcategories}}, {{PLURAL:$3|1 file|$3 files}})',
 'search-result-score' => 'Relevanc: $1%',
-'search-redirect' => '(redirect $1)',
+'search-redirect' => '(reguide $1)',
 'search-section' => '(section $1)',
 'search-file-match' => '(matches file content.)',
 'search-suggest' => 'Did ye mean: $1',
 'search-interwiki-caption' => "Sister projec's",
-'search-interwiki-default' => "$1 results':",
+'search-interwiki-default' => 'Ootcomes fae $1:',
 'search-interwiki-more' => '(mair)',
 'search-relatedarticle' => 'Relatit',
 'searcheverything-enable' => 'Rake in aw namespaces',
 'searchrelated' => 'related',
 'searchall' => 'aw',
 'showingresults' => "Shawin ablo up tae {{PLURAL:$1|'''1''' result|'''$1''' results}} stertin wi #'''$2'''.",
-'showingresultsinrange' => 'Shawin ablo up til {{PLURAL:$1|<strong>1</strong> affcome|<strong>$1</strong> affcome}} in range #<strong>$2</strong> til #<strong>$3</strong>.',
+'showingresultsinrange' => 'Shawin ablo up til {{PLURAL:$1|<strong>1</strong> ootcome|<strong>$1</strong> ootcome}} in range #<strong>$2</strong> til #<strong>$3</strong>.',
 'showingresultsnum' => "Shawin ablo {{PLURAL:$3|'''1''' result|'''$3''' results}} stertin wi #'''$2'''.",
-'showingresultsheader' => '{{PLURAL:$5|Affcome <strong>$1</strong> o <strong>$3</strong>|Affcomes <strong>$1 - $2</strong> o <strong>$3</strong>}} fer <strong>$4</strong>',
+'showingresultsheader' => '{{PLURAL:$5|Ootcome <strong>$1</strong> o <strong>$3</strong>|Ootcomes <strong>$1 - $2</strong> o <strong>$3</strong>}} fer <strong>$4</strong>',
 'search-nonefound' => 'Thaur were naw ootcomes matchin the speiring.',
 'powersearch-legend' => 'Advanced rake',
 'powersearch-ns' => 'Rake in namespaces:',
@@ -1156,25 +1159,25 @@ Details can be foond in the [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENA
 'prefs-watchlist-token' => 'Watchleet token:',
 'prefs-misc' => 'Antrin settins',
 'prefs-resetpass' => 'Chynge passwaird',
-'prefs-changeemail' => 'Chynge email address',
+'prefs-changeemail' => 'Chynge Wab-mail address',
 'prefs-setemail' => 'Set ae wab-mail address',
 'prefs-email' => 'Wab-mail opties',
 'prefs-rendering' => 'Appearence',
 'saveprefs' => 'Hain preferences',
-'restoreprefs' => 'Restore aw default settings (in aw sections)',
+'restoreprefs' => 'Restore aw defaut settins (in aw sections)',
 'prefs-editing' => 'Editin',
 'rows' => 'Raws:',
 'searchresultshead' => 'Rake result settins',
-'stub-threshold' => 'Threshold for <a href="#" class="stub">stub link</a> formattin (bytes):',
+'stub-threshold' => 'Threeshaud fer <a href="#" class="stub">stub link</a> formattin (bytes):',
 'stub-threshold-disabled' => 'Tuckie',
-'recentchangesdays' => 'Days tae shaw in recent chynges:',
+'recentchangesdays' => 'Days tae shaw in recynt chynges:',
 'recentchangesdays-max' => 'Mucklest $1 {{PLURAL:$1|day|days}}',
-'recentchangescount' => 'Nummer o eidits tae shaw bi defaut:',
+'recentchangescount' => 'Nummer o eedits tae shaw bi defaut:',
 'prefs-help-recentchangescount' => 'This includes recent chynges, page histories, n logs.',
 'prefs-help-watchlist-token2' => 'This is the hidlins key til the wab feed o yer watchleet. Onibodie wha kens this can read yer watchleet, sae dinna shair it. Gif ye need to, [[Special:ResetTokens|Ye can reset it]].',
 'savedprefs' => 'Yer preferences haes been hained.',
-'timezoneuseserverdefault' => 'Uise wiki default ($1)',
-'timezoneuseoffset' => 'Ither (specify offset)',
+'timezoneuseserverdefault' => 'Uise wiki defaut ($1)',
+'timezoneuseoffset' => 'Ither (speceefie affset)',
 'servertime' => 'Server time the nou',
 'guesstimezone' => 'Fill in frae brouser',
 'timezoneregion-africa' => 'Africae',
@@ -1193,9 +1196,9 @@ Details can be foond in the [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENA
 'prefs-files' => 'Files',
 'prefs-custom-css' => 'Custom CSS',
 'prefs-custom-js' => 'Custom JS',
-'prefs-common-css-js' => 'Shared CSS/JavaScript for aw skins:',
-'prefs-reset-intro' => 'Ye can uise this page tae reset yer preferences tae the steid defaults.
-This cannae be unduin.',
+'prefs-common-css-js' => 'Shaired CSS/JavaScript fer aw skins:',
+'prefs-reset-intro' => 'Ye can uise this page tae reset yer preeferances til the steid defauts.
+This canna be ondun.',
 'prefs-emailconfirm-label' => 'Wab-mail confirmation:',
 'youremail' => 'Yer email:',
 'username' => '{{GENDER:$1|Uisername}}:',
@@ -1205,13 +1208,13 @@ This cannae be unduin.',
 'yourrealname' => 'Yer real name:',
 'yourlanguage' => 'Interface leid:',
 'yourvariant' => 'Content leid variant',
-'prefs-help-variant' => 'Yer preferred variant or orthography tae display the content pages o this wiki in.',
+'prefs-help-variant' => 'Yer preferred variant or orthographie tae displey the content pages o this wiki in.',
 'yournick' => 'New seegnatur:',
-'prefs-help-signature' => 'Comments on collogue pages should be signed wi "<nowiki>~~~~</nowiki>", which will be convertit intae yer signatur an a timestamp.',
+'prefs-help-signature' => 'Comments oan talk pages shid be signed wi "<nowiki>~~~~</nowiki>", this will be convertit intil yer signatur n ae timestamp.',
 'badsig' => 'Raw signature nae guid; check HTML tags.',
 'badsiglength' => 'Yer nickname is ower lang; it haes tae be $1 {{PLURAL:$1|character|characters}} or less.',
-'yourgender' => 'Hou dae ye prefer tae be describit?',
-'gender-unknown' => 'I prefer nae tae say',
+'yourgender' => 'Hou dae ye prefer tae be described?',
+'gender-unknown' => 'Ah prefer tae na say',
 'gender-male' => 'He eedits wiki pages',
 'gender-female' => 'She eedits wiki pages',
 'prefs-help-gender' => 'Settin this preference is aen optie.
@@ -1238,7 +1241,7 @@ Yer wab-mail address isna revealed whan ither uisers contact ye.',
 'prefs-displaysearchoptions' => 'Displey opties',
 'prefs-displaywatchlist' => 'Displey opties',
 'prefs-diffs' => 'Diffs',
-'prefs-help-prefershttps' => 'This preference will tak effect on yer next login.',
+'prefs-help-prefershttps' => 'This preeferance will tak effect oan yer nex login.',
 'prefs-tabs-navigation-hint' => 'Tip: Ye can uise the cair n richt arrae keys tae naveegate atween the tabs in the tabs leet.',
 
 # User preference: email validation using jQuery
@@ -1246,35 +1249,35 @@ Yer wab-mail address isna revealed whan ither uisers contact ye.',
 'email-address-validity-invalid' => 'Enter ae valid wab-mail address',
 
 # User rights
-'userrights' => 'Uiser richts management',
+'userrights' => 'Uiser richts managemant',
 'userrights-lookup-user' => 'Manish uiser boorachs',
 'userrights-user-editname' => 'Enter a uisername:',
 'editusergroup' => 'Eidit uiser boorach',
 'editinguser' => 'Chynging uiser richts o uiser <strong>[[User:$1|$1]]</strong> $2',
-'userrights-editusergroup' => 'Edit uiser groups',
-'saveusergroups' => 'Save uiser groups',
+'userrights-editusergroup' => 'Eedit uiser groops',
+'saveusergroups' => 'Hain uiser groops',
 'userrights-groupsmember' => 'Member o:',
-'userrights-groupsmember-auto' => 'Implicit member o:',
+'userrights-groupsmember-auto' => 'Impleecit memmer o:',
 'userrights-groups-help' => "Ye can alter the groops this uiser is in:
 * Ae checkit kist means that the uiser is in that groop.
 * Aen oncheckit kist means that the uiser's no in that groop.
 * Ae * indicates that ye cannae remuiv the groop yince ye'v added it, or vice versa.",
 'userrights-reason' => 'Raison:',
-'userrights-no-interwiki' => 'Ye dae nae hae permission tae edit uiser richts on ither wikis.',
-'userrights-nodatabase' => 'Database $1 daes nae exist or is nae local.',
+'userrights-no-interwiki' => 'Ye dinna hae permission tae eedit uiser richts oan ither wikis.',
+'userrights-nodatabase' => 'Database $1 disna exeest or isna local.',
 'userrights-nologin' => 'Ye maun [[Special:UserLogin|log in]] wi aen admeenistrater accoont tae assign uiser richts.',
-'userrights-notallowed' => 'Ye dae nae hae permission tae add or remove uiser richts.',
-'userrights-changeable-col' => 'Groups ye can chynge',
-'userrights-unchangeable-col' => 'Groups ye cannae chynge',
+'userrights-notallowed' => 'Ye dinna hae permission tae add or remuiv uiser richts.',
+'userrights-changeable-col' => 'Groops that ye can chynge',
+'userrights-unchangeable-col' => 'Groops ye canna chynge',
 'userrights-conflict' => 'Conflict o uiser richts chynges! Please luikower n confirm yer chynges.',
-'userrights-removed-self' => 'Ye successfully removed yer ain richts. As such, ye are no langer able tae access this page.',
+'userrights-removed-self' => "Ye'v successfulie remuived yer ain richts. N sae, ye'r naw langer able tae access this page.",
 
 # Groups
 'group' => 'Groop:',
 'group-user' => 'Uisers',
-'group-autoconfirmed' => 'Autoconfirmed uisers',
+'group-autoconfirmed' => 'Autæconfirmed uisers',
 'group-bot' => 'Bots',
-'group-sysop' => 'Admeenistrators',
+'group-sysop' => 'Admeenistraters',
 'group-suppress' => 'Owersichts',
 'group-all' => '(aw)',
 
@@ -1291,33 +1294,33 @@ Yer wab-mail address isna revealed whan ither uisers contact ye.',
 
 # Rights
 'right-edit' => 'Eedit pages',
-'right-createpage' => 'Create pages (which are nae discussion pages)',
+'right-createpage' => 'Cræft pages (that arna tauk pages)',
 'right-createtalk' => 'Cræft discussion pages',
-'right-createaccount' => 'Create new uiser accoonts',
-'right-minoredit' => 'Mark edits as smaa',
-'right-move' => 'Flit pages',
-'right-move-subpages' => 'Flit pages wi thair subpages',
-'right-move-rootuserpages' => 'Flit ruit uiser pages',
-'right-movefile' => 'Flit files',
-'right-suppressredirect' => 'Nae create redirects frae soorce pages when flittin pages',
+'right-createaccount' => 'Cræft new uiser accoonts',
+'right-minoredit' => 'Maurk eedits aes smaa',
+'right-move' => 'Muiv pages',
+'right-move-subpages' => 'Muiv pages wi thair subpages',
+'right-move-rootuserpages' => 'Muiv ruit uiser pages',
+'right-movefile' => 'Muiv files',
+'right-suppressredirect' => 'Na cræft reguidals fae soorce pages whan muivin pages',
 'right-upload' => 'Uplaid files',
-'right-reupload' => 'Owerwrite existin files',
-'right-reupload-own' => 'Owerwrite existin files uplaidit bi anesel',
-'right-reupload-shared' => 'Owerride files on the shared media repository locally',
-'right-upload_by_url' => 'Uplaid files frae a URL',
-'right-purge' => 'Purge the steid cache for a page wioot confirmation',
-'right-autoconfirmed' => 'Nae be affectit bi IP-based rate leemits',
+'right-reupload' => 'Owerwrite exeestin files',
+'right-reupload-own' => 'Owerwrite exeestin files uplaidit bi yersel',
+'right-reupload-shared' => 'Owerride files oan the shaired media repositerie locallie',
+'right-upload_by_url' => 'Uplaid files fae ae URL',
+'right-purge' => 'Purge the steid cache fer ae page wioot confirmation',
+'right-autoconfirmed' => 'Na be affectit bi IP-based rate leemits',
 'right-bot' => 'Be treatit aes aen autæmatit process',
-'right-nominornewtalk' => 'Nae hae smaa edits tae discussion pages trigger the new messages prompt',
+'right-nominornewtalk' => 'Na hae smaa eedits til discussion pages trigger the new messages prompt',
 'right-apihighlimits' => 'Uise heicher leemits in API queries',
 'right-writeapi' => 'Uise o the write API',
 'right-delete' => 'Delyte pages',
-'right-bigdelete' => 'Delete pages wi lairge histories',
+'right-bigdelete' => 'Delyte pages wi muckle histeries',
 'right-deletelogentry' => 'Delyte n ondelyte speceefic log entries',
 'right-deleterevision' => 'Delyte n ondylete speceefic reveesions o pages',
-'right-deletedhistory' => 'View deletit history entries, wioot thair associatit text',
+'right-deletedhistory' => 'See delytit histerie entries, wioot thair associatit tex',
 'right-deletedtext' => 'See delytit tex n chynges atween delytit reveesions',
-'right-browsearchive' => 'Rake deletit pages',
+'right-browsearchive' => 'Rake delytit pages',
 'right-undelete' => 'Ondelyte ae page',
 'right-suppressrevision' => 'Luikower n restore reveesions skaukt fae admeenistraters',
 'right-suppressionlog' => 'see preevate logs',
@@ -1371,7 +1374,7 @@ Yer wab-mail address isna revealed whan ither uisers contact ye.',
 'action-createpage' => 'cræft pages',
 'action-createtalk' => 'cræft discussion pages',
 'action-createaccount' => 'cræft this uiser accoont',
-'action-minoredit' => 'maurk this eedit aes minor',
+'action-minoredit' => 'maurk this eedit aes smaa',
 'action-move' => 'muiv this page',
 'action-move-subpages' => 'mui this page, n its subpages',
 'action-move-rootuserpages' => 'muiv ruit uiser pages',
@@ -1411,13 +1414,13 @@ Yer wab-mail address isna revealed whan ither uisers contact ye.',
 'enhancedrc-since-last-visit' => '$1 {{PLURAL:$1|sin laist veesit}}',
 'enhancedrc-history' => 'histeri',
 'recentchanges' => 'Recent chynges',
-'recentchanges-legend' => 'Recent changes options',
+'recentchanges-legend' => 'Recynt chynges opties',
 'recentchanges-summary' => 'Follae the maist recent chynges tae the wiki on this page.',
 'recentchanges-noresult' => 'Naw chynges durin the gien period matchin thir guidins.',
 'recentchanges-feed-description' => 'Follae the maist recent chynges tae the wiki in this feed.',
 'recentchanges-label-newpage' => 'This edit created a freish page',
 'recentchanges-label-minor' => 'This is ae smaa eedit',
-'recentchanges-label-bot' => 'This edit wis performed bi a bot',
+'recentchanges-label-bot' => 'This eedit wis performed bi ae bot',
 'recentchanges-label-unpatrolled' => 'This edit haes nae yet bin patrolled',
 'recentchanges-label-plusminus' => 'The page size chynged bi this nummer o bytes',
 'recentchanges-legend-newpage' => '(see [[Special:NewPages|leet o new pages]] ava)',
@@ -1470,20 +1473,20 @@ Pages oan [[Special:Watchlist|yer watchleet]] ar <strong>baud</strong.',
 # Upload
 'upload' => 'Uplaid file',
 'uploadbtn' => 'Uplaid file',
-'reuploaddesc' => 'Gang back tae the uplaid form.',
+'reuploaddesc' => 'Gang back til the uplaid form.',
 'upload-tryagain' => 'Haunn in modified file descreeption',
 'uploadnologin' => 'Nae loggit in',
 'uploadnologintext' => 'Please $1 tae uplaid files.',
 'upload_directory_missing' => 'The uplaid directerie ($1) is missin n coudna be cræftit bi the wabserver.',
 'upload_directory_read_only' => 'The uplaid directerie ($1) is naw writable bi the wabserver.',
 'uploaderror' => 'Uplaid mistak',
-'upload-recreate-warning' => "'''Warnishment: Ae file bi that name haes been delytir or muived.'''
+'upload-recreate-warning' => "'''Warnishment: Ae file bi that name haes been delytit or muived.'''
 
-The delytion n muiv log fer this page ar provided here fer conveeeniance:",
+The delytion n muiv log fer this page ar gien here fer conveeneeance:",
 'uploadtext' => 'Uise the form ablo tae uplaid files.
 Tae see or rake preeveeooslie uplaided files gang til the [[Special:FileList|leet o uplaided files]], (re)uplaids ar loggit in the [[Special:Log/upload|uplaid log]] ava, delytions in the [[Special:Log/delete|delytion log]].
 
-Tae incluide ae file in ae page, uise ae link in yin o the follaein forms:
+Tae incluid ae file in ae page, uise ae link in yin o the follaein forms:
 * <strong><code><nowiki>[[</nowiki>{{ns:file}}<nowiki>:File.jpg]]</nowiki></code></strong> tae uise the ful version o the file
 * <strong><code><nowiki>[[</nowiki>{{ns:file}}<nowiki>:File.png|200px|thumb|left|alt tex]]</nowiki></code></strong> tae uise ae 200 pixel wide rendeetion in ae kist in the cair margin wi "alt tex" aes descreeption
 * <strong><code><nowiki>[[</nowiki>{{ns:media}}<nowiki>:File.ogg]]</nowiki></code></strong> fer linkin directlie til the file wioot displeyin the file.',
@@ -1503,7 +1506,7 @@ Tae incluide ae file in ae page, uise ae link in yin o the follaein forms:
 'minlength1' => 'Filenames maun be at least yin letter.',
 'illegalfilename' => 'The filename "$1" haes chairacters that\'s naw permitit in page teitles. Please rename the file n gie uplaidin it anither shote.',
 'filename-toolong' => 'Filenames canna be langer than 240 bytes.',
-'badfilename' => 'Eimage name haes been chynged tae "$1".',
+'badfilename' => 'Filename haes been chynged til "$1".',
 'filetype-mime-mismatch' => 'File exteension ".$1" disna match the detected MIME type o the file ($2).',
 'filetype-badmime' => 'Files o the MIME type "$1" ar no permitit tae be uplaided.',
 'filetype-bad-ie-mime' => 'Canna uplaid this file cause Internet Explorer wid detect it aes "$1", n this is ae non-permitit n potentiallie dangeroos file type.',
@@ -1602,9 +1605,9 @@ $1',
 'upload-file-error-text' => 'Aen internal mitake occurred whan attemptin tae cræft ae temperie file oan the server.
 Please contact aen [[Special:ListUsers/sysop|admeenistrater]].',
 'upload-misc-error' => 'Onkent uplaid mistake',
-'upload-misc-error-text' => 'Aen onkent error occurred durin the uplaid.
-Please vereefie that the URL is valid n accessible n gie it anither gae.
-Gif the proablem perseests, contact aen [[Special:ListUsers/sysop|admeenistrater]].',
+'upload-misc-error-text' => 'Aen onkent mistak occurred during the uplaid.
+Please vereefie that the URL is valit n accessible n gie it anither gae.
+Gif the proablem persists, contact aen [[Special:ListUsers/sysop|admeenistrater]].',
 'upload-too-many-redirects' => 'The URL contained oewr monie reguidals',
 'upload-unknown-size' => 'Onkent size',
 'upload-http-error' => 'Aen HTTP mistake occurred: $1',
@@ -1701,8 +1704,8 @@ Fr optimal securitie, img_auth.php is disabled.',
 
 # Some likely curl errors. More could be added from <http://curl.haxx.se/libcurl/c/libcurl-errors.html>
 'upload-curl-error6' => 'Coudna reach URL',
-'upload-curl-error6-text' => 'The URL provided coudna be reached.
-Please double-check that the URL is correct n the site is up.',
+'upload-curl-error6-text' => 'The URL gien coudna be reached.
+Please dooble-check that the URL is correct n the site is up.',
 'upload-curl-error28' => 'Uplaid timeoot',
 'upload-curl-error28-text' => 'The site tuik ower lang tae respond.
 Please check that the site is up, wait ae short while n gei it anither gae.
@@ -1732,7 +1735,7 @@ Ye micht want tae try at ae less busie time.',
 
 # File description page
 'file-anchor-link' => 'Eimage',
-'filehist' => 'File history',
+'filehist' => 'File histerie',
 'filehist-help' => 'Clap oan ae date/time tae view the file aes it appeared at that time.',
 'filehist-deleteall' => 'delyte aw',
 'filehist-deleteone' => 'delyte',
@@ -1751,7 +1754,7 @@ Ye micht want tae try at ae less busie time.',
 'linkstoimage-more' => 'Mair than $1 {{PLURAL:$1|page links|pages link}} til this file.
 The follaein leet shaws the {{PLURAL:$1|first page link|first $1 page links}} til this file yinlie.
 Ae [[Special:WhatLinksHere/$2|ful leet]] is available.',
-'nolinkstoimage' => "The'r nae pages airts tae this eimage.",
+'nolinkstoimage' => "Thaur's nae pages that link til this eemage.",
 'morelinkstoimage' => 'See [[Special:WhatLinksHere/$1|mair links]] til this file.',
 'linkstoimage-redirect' => '$1 (file reguidal) $2',
 'duplicatesoffile' => 'The follaein {{PLURAL:$1|file is ae dupleecate|$1 files ar dupleecates}} o this file ([[Special:FileDuplicateSearch/$2|mair details]]):',
@@ -1779,7 +1782,7 @@ Perhaps ye want tae eedit the deescreeption oan its [$2 file deescreeption page]
 'filerevert-defaultcomment' => 'Reverted til version aes o $2, $1',
 'filerevert-submit' => 'Revert',
 'filerevert-success' => "'''[[Media:$1|$1]]''' haes been reverted til the [$4 version aes o $3, $2].",
-'filerevert-badversion' => "Thaur's naw preeveeoos local version o this file wi the provided timestamp.",
+'filerevert-badversion' => "Thaur's naw preeveeoos local version o this file wi the gien timestamp.",
 
 # File deletion
 'filedelete' => 'Delyte $1',
@@ -1863,8 +1866,8 @@ Input: contenttype/subtype, e.g. <code>image/jpeg</code>.',
 'pageswithprop-prophidden-binary' => 'binarie propertie value skaukt ($1)',
 
 'doubleredirects' => 'Dooble reguidals',
-'doubleredirectstext' => 'This page leets pages that redirect til ither redirect pages.
-Ilka rou contains airtins til the first and seicont redirect, aes weel aes the terget o the secont redirect, whilk is usually the "real" terget page whaur the first redirect shid point.
+'doubleredirectstext' => 'This page leets pages that reguide til ither reguidal pages.
+Ilka raw contains links til the first n seicont reguidals, n the tairget o the seicont reguidal ava, this is uisuallie the "real" tairget page whaur the first reguidal shid poynt.
 <del>Crossed oot</del> entries hae been solved.',
 'double-redirect-fixed-move' => '[[$1]] haes been muived.
 It nou reguides til [[$2]].',
@@ -1889,11 +1892,11 @@ It nou reguides til [[$2]].',
 'nlinks' => '$1 {{PLURAL:$1|link|links}}',
 'nmembers' => '$1 {{PLURAL:$1|membir|membirs}}',
 'nmemberschanged' => '$1 → $2 {{PLURAL:$2|memmer|memmers}}',
-'nrevisions' => '$1 {{PLURAL:$1|reveision|reveisions}}',
+'nrevisions' => '$1 {{PLURAL:$1|reveesion|reveesions}}',
 'nviews' => '$1 {{PLURAL:$1|view|views}}',
 'nimagelinks' => 'Uised oan $1 {{PLURAL:$1|page|pages}}',
 'ntransclusions' => 'uised oan $1 {{PLURAL:$1|page|pages}}',
-'specialpage-empty' => "Thaur's naw affcomes fer this report.",
+'specialpage-empty' => "Thaur's naw ootcomes fer this report.",
 'lonelypages' => 'Orphant pages',
 'lonelypagestext' => "The follaein pages'r naw linkt fae or transcluided intil ither pages in {{SITENAME}}.",
 'uncategorizedpages' => 'Uncategoreised pages',
@@ -1904,7 +1907,7 @@ It nou reguides til [[$2]].',
 'unusedimages' => 'Unuised images',
 'wantedcategories' => 'Wantit categories',
 'wantedpages' => 'Wantit pages',
-'wantedpages-badtitle' => 'Onvalid title in affcome set: $1',
+'wantedpages-badtitle' => 'Onvalid title in ootcome set: $1',
 'wantedfiles' => 'Wantit files',
 'wantedfiletext-cat' => 'The follaein files ar uised but dinna exeest. Files fae foreign repositeries micht be leetit despite exeestin. Onie sic false poseeteeves will be <del>struck oot</del>. Addeetionallie, pages that embed files that dinna exeest ar leetit in [[:$1]].',
 'wantedfiletext-nocat' => 'The follaein files ar uised but dinna exeest. Files fae foreign repositeries micht be leetit despite exeestin. Onie sic false poseeteeves will be <del>struck oot</del>.',
@@ -1912,7 +1915,7 @@ It nou reguides til [[$2]].',
 'mostlinked' => 'Maist airtit-til pages',
 'mostlinkedcategories' => 'Maist airtit-til categories',
 'mostlinkedtemplates' => 'Maist linkt-til templates',
-'mostcategories' => 'Airticles wi the maist categories',
+'mostcategories' => 'Airticles wi the maist categeries',
 'mostimages' => 'Maist uised eimages',
 'mostinterwikis' => 'Pages wi the maist interwikis',
 'mostrevisions' => 'Maist revised airticles',
@@ -1937,7 +1940,7 @@ It nou reguides til [[$2]].',
 'protectedpages-unknown-timestamp' => "Onken't",
 'protectedpages-unknown-performer' => "Onken't user",
 'protectedtitles' => 'Pretectit titles',
-'protectedtitles-summary' => 'This page leets titles that ar nou protectit fae cræftin. Fer a leet of exeesting pages that ar protectit, see [[{{#special:ProtectedPages}}]].',
+'protectedtitles-summary' => 'This page leets titles that ar nou protectit fae cræftin. Fer ae leet o exeestin pages that ar protectit, see [[{{#special:ProtectedPages}}]].',
 'protectedtitlesempty' => 'Naw titles ar the Nou protected wi thir parameters.',
 'listusers' => 'Uiser leet',
 'listusers-editsonly' => 'Shaw yinlie uisers wi eedits',
@@ -1948,8 +1951,8 @@ It nou reguides til [[$2]].',
 'newpages' => 'New pages',
 'newpages-username' => 'Uisername:',
 'ancientpages' => 'Auldest pages',
-'move' => 'Flit',
-'movethispage' => 'Flit this page',
+'move' => 'Muiv',
+'movethispage' => 'Muiv this page',
 'unusedimagestext' => 'The follaein files exeest but arna embeddit in onie page.
 Please mynd that ither wab sites micht link til ae file wi ae direct URL, n sae micht still be leetit here despite being in acteeve uiss.',
 'unusedcategoriestext' => 'The follaein category pages exists, tho nae ither airticle or category maks uiss o thaim.',
@@ -1982,7 +1985,7 @@ Ye can narrae doon the whit ye see bi selectin ae log type, the uisername (case-
 
 # Special:AllPages
 'allpages' => 'Aw pages',
-'alphaindexline' => '$1 tae $2',
+'alphaindexline' => '$1 til $2',
 'nextpage' => 'Neist page ($1)',
 'prevpage' => 'Page afore ($1)',
 'allpagesfrom' => 'Shaw pages stairtin at:',
@@ -2007,7 +2010,7 @@ Ye can narrae doon the whit ye see bi selectin ae log type, the uisername (case-
 See [[Special:WantedCategories|wanted categeries]] ava.',
 'categoriesfrom' => 'Displey categeries stairtin at:',
 'special-categories-sort-count' => 'sairt bi coont',
-'special-categories-sort-abc' => 'sairt by the alphabet',
+'special-categories-sort-abc' => 'sairt bi the alphabet',
 
 # Special:DeletedContributions
 'deletedcontributions' => 'Delytit uiser contreebutions',
@@ -2121,8 +2124,8 @@ Futur chynges til this page n its associated tauk page will be leeted thaur.',
 'watchmethod-recent' => 'checkin recent eedits fer watched pages',
 'watchmethod-list' => 'checking watched pages fer recent eedits',
 'watchlistcontains' => 'Yer watchleet contains $1 {{PLURAL:$1|page|pages}}.',
-'iteminvalidname' => "Trouble wi eitem '$1', invalid name...",
-'wlnote2' => 'Ablow ar the chynges in the hainmaist {{PLURAL:$1|hour|<strong>$1</strong> hours}}, as of $3, $2.',
+'iteminvalidname' => "Proablem wi eetem '$1', onvalit name...",
+'wlnote2' => 'Ablo ar the chynges in the hainmaist {{PLURAL:$1|hoor|<strong>$1</strong> hours}}, aes o $3, $2.',
 'wlshowlast' => 'Shaw lest $1 hours $2 days $3',
 'watchlist-options' => 'Watchleet options',
 
@@ -2173,7 +2176,7 @@ $UNWATCHURL
 
 Feedback n further asseestance:
 {{canonicalurl:{{MediaWiki:Helppage}}}}',
-'created' => 'creatit',
+'created' => 'cræftit',
 'changed' => 'chynged',
 
 # Delete
@@ -2192,9 +2195,9 @@ n that ye'r daein this in accord wi [[{{MediaWiki:Policy-url}}]].",
 'actionfailed' => 'Action failed',
 'deletedtext' => '"$1" haes been delytit. See $2 fer ae record o recent delytions.',
 'dellogpage' => 'Delytion log',
-'dellogpagetext' => 'Ablo is a leet o the maist recent deletions.',
+'dellogpagetext' => 'Ablo is ae leet o the maist recynt delytions.',
 'deletionlog' => 'delytion log',
-'reverted' => 'Revertit tae aulder reveision',
+'reverted' => 'Revertit til aulder reveesion',
 'deletecomment' => 'Raeson:',
 'deleteotherreason' => 'Ither/addeetional raison:',
 'deletereasonotherlist' => 'Ither raeson',
@@ -2267,6 +2270,8 @@ Ye can chynge this page's protection level, but it will na affect the cascadin p
 'protect-level-autoconfirmed' => 'Allou yinly autæconfirmed uisers',
 'protect-level-sysop' => 'Allou admeenistraters yinly',
 'protect-summary-cascade' => 'cascadin',
+'protect-expiring' => 'dees $1 (UTC)',
+'protect-expiring-local' => 'dees $1',
 'protect-expiry-indefinite' => 'indefineet',
 'protect-cascade' => 'Protect pages incluided in this page (cascadin protection)',
 'protect-cantedit' => 'Ye canna chynge the protection levels o this page cause ye dinna hae permeession tae eedit it.',
@@ -2289,7 +2294,7 @@ Ye can chynge this page's protection level, but it will na affect the cascadin p
 
 # Restrictions (nouns)
 'restriction-edit' => 'Eidit',
-'restriction-move' => 'Flit',
+'restriction-move' => 'Muiv',
 'restriction-create' => 'Mak',
 'restriction-upload' => 'Uplaid',
 
@@ -2299,7 +2304,7 @@ Ye can chynge this page's protection level, but it will na affect the cascadin p
 'restriction-level-all' => 'onie level',
 
 # Undelete
-'undelete' => 'Restore delyte page',
+'undelete' => 'See delytit page',
 'undeletepage' => 'See n restore delytit pages',
 'undeletepagetitle' => '<strong>The follaein conseests o delytit reveesions o [[:$1|$1]]</strong>.',
 'viewdeletedpage' => 'View delyte pages',
@@ -2319,10 +2324,10 @@ shawn in the owerview ablo, alang wi parteeculars o the uisers that haed eiditit
 'undeleterevision-missing' => 'Onvalid or missin reveesion.
 Ye micht hae ae bad link, or the reveesion micht hae been restored or remuived fae the archive.',
 'undelete-nodiff' => 'Naw preeveeoos reveesion foond.',
-'undeletelink' => 'view/restore',
+'undeletelink' => 'see/restore',
 'undeleteviewlink' => 'view',
 'undeletecomment' => 'Raison:',
-'undeletedrevisions' => '{{PLURAL:$1|1 reveision|$1 reveisions}} restored',
+'undeletedrevisions' => '{{PLURAL:$1|1 reveesion|$1 reveesions}} restored',
 'undeletedrevisions-files' => '{{PLURAL:$1|1 reveesion|$1 reveesions}} n {{PLURAL:$2|1 file|$2 files}} restored',
 'cannotundelete' => 'Ondelyte failed:
 $1',
@@ -2375,9 +2380,9 @@ $1',
 'sp-contributions-talk' => 'tauk',
 'sp-contributions-userrights' => 'uiser richts management',
 'sp-contributions-blocked-notice' => 'This uiser is nou blockit.
-The latest block log entrie is providit ablo fer referance:',
+The latest block log entrie is gien ablo fer referance:',
 'sp-contributions-blocked-notice-anon' => 'This IP address is blockit the nou.
-The latest block log entrie is providit ablo fer referance:',
+The latest block log entrie is gien ablo fer referance:',
 'sp-contributions-search' => 'Rake fer contreebutions',
 'sp-contributions-suppresslog' => 'suppressed uiser contreebutions',
 'sp-contributions-username' => 'IP address or uisername:',
@@ -2386,11 +2391,11 @@ The latest block log entrie is providit ablo fer referance:',
 'sp-contributions-submit' => 'Rake',
 
 # What links here
-'whatlinkshere' => 'Whit airts tae here',
+'whatlinkshere' => 'Whit links here',
 'whatlinkshere-title' => 'Pages that link til "$1"',
 'whatlinkshere-page' => 'Page:',
-'linkshere' => "The follaein pages airts tae '''[[:$1]]''':",
-'nolinkshere' => "Nae pages airt tae '''[[:$1]]'''.",
+'linkshere' => 'The follaein pages link til <strong>[[:$1]]</strong>:',
+'nolinkshere' => "Nae pages link wi '''[[:$1]]'''.",
 'nolinkshere-ns' => 'No pages aiet til <strong>[[:$1]]</strong> in the choosen namespace.',
 'isredirect' => 'reguidal page',
 'istemplate' => 'transclusion',
@@ -2410,7 +2415,7 @@ The latest block log entrie is providit ablo fer referance:',
 'unblock' => 'Onblock uiser',
 'blockip' => 'Block uiser',
 'blockip-legend' => 'Block uiser',
-'blockiptext' => 'Uise the form ablo tae block write access frae a specific IP address or uisername. This shuid be duin juist tae prevent vandalism, and in accord wi [[{{MediaWiki:Policy-url}}|policy]]. Fill in a specific raeson ablo (for exemplar, citin parteicular pages that wis damaged).',
+'blockiptext' => 'Uise the form ablo tae block write access fae ae speceefic IP address or uisername. This shid be dun juist tae hinder vandaleesm, n in accord wi [[{{MediaWiki:Policy-url}}|policie]]. Fil in ae speceefic raison ablo (fer exemplar, citin parteecular pages that were vandalised).',
 'ipadressorusername' => 'IP Address or uisername',
 'ipbexpiry' => 'Expirie:',
 'ipbreason' => 'Raeson:',
@@ -2441,11 +2446,11 @@ The latest block log entrie is providit ablo fer referance:',
 'ipb-confirmhideuser' => 'Ye\'r aboot tae block ae uiser wi "skauk uiser" enabled. This will suppress the uiser\'s name in aw leets n log entries. Ar ye sair that ye want tae dae that?',
 'ipb-confirmaction' => 'Gif ye\'r sair that ye reelie want tae dae it, please check the "{{int:ipb-confirm}}" field at the bottom.',
 'ipb-edit-dropdown' => 'Eedit block raisons',
-'ipb-unblock-addr' => 'Unblock $1',
+'ipb-unblock-addr' => 'Onblock $1',
 'ipb-unblock' => 'Onblock ae uisername or IP address',
 'ipb-blocklist' => 'See exeestin blocks',
 'ipb-blocklist-contribs' => 'Contreebutions fer $1',
-'unblockip' => 'Unblock uiser',
+'unblockip' => 'Onblock uiser',
 'unblockiptext' => 'Uise the form ablo tae restore screevin richts
 til aen afore-blockit IP address or uisername.',
 'ipusubmit' => 'Remuive this block',
@@ -2476,16 +2481,16 @@ til aen afore-blockit IP address or uisername.',
 'ipblocklist-empty' => 'The block leet is tuim.',
 'ipblocklist-no-results' => 'The requested IP address or uisername isna blockit.',
 'blocklink' => 'block',
-'unblocklink' => 'unblock',
+'unblocklink' => 'onblock',
 'change-blocklink' => 'chynge block',
-'contribslink' => 'contreibs',
+'contribslink' => 'contreebs',
 'emaillink' => 'send wab-mail',
 'autoblocker' => 'Autaematicallie blockit sin yer IP address haes been uised recentlie bi "[[User:$1|$1]]". The raeson gien fer $1\'s block is "$2"',
 'blocklogpage' => 'Block log',
 'blocklog-showlog' => 'This uiser haes been blockit afore.
-The block log is provided ablo fer reeferance:',
+The block log is gien ablo fer referance:',
 'blocklog-showsuppresslog' => 'This uiser haes been blockit n skaukt afore.
-The suppress log is provided ablo fer reeferance:',
+The suppress log is gien ablo fer referance:',
 'blocklogentry' => 'blockit [[$1]] wi aen expirie time o $2 $3',
 'reblock-logentry' => 'chynged block settins fer [[$1]] wi ae diein time o $2 $3',
 'blocklogtext' => 'This is ae log o uiser blockin n onblockin actions. Autaematiclie blockit IP addresses isna leetit. See the [[Special:BlockList|block leet]] fer the leet o bans n blocks oan the nou.',
@@ -2540,19 +2545,19 @@ Tae lock or lowse the database, this needs tae be writable bi the wab server.',
 
 # Move page
 'move-page' => 'Muiv $1',
-'move-page-legend' => 'Flit page',
+'move-page-legend' => 'Muiv page',
 'movepagetext' => "Uisin the form ablo will rename ae page, muivin aw o its histerie til the new name.
 The auld title will become ae reguidal page til the new title.
-Ye can update reguidals that point til the oreeginal title autaematiclie.
-Gif ye chuis no tae, be sair tae check fer [[Special:DoubleRedirects|dooble]] or [[Special:BrokenRedirects|broken reguidals]].
-Ye'r responsible fer makin sair that airtins continue tae pynt til whaur they'r supposed to gae.
+Ye can update reguidals that poynt til the oreeginal title autæmateeclie.
+Gif ye chuise na tae, be sair tae check fer [[Special:DoubleRedirects|dooble]] or [[Special:BrokenRedirects|broken reguidals]].
+Ye'r responsible fer makin sair that links continue tae poynt til whaur thay'r supposed to gae.
 
-Note that the page will <strong>no</strong> be muived gif there is awreadie ae page at the new title, onless the latter is ae reguidal n haes nae past eidit histerie.
+Mynd that the page will <strong>na</strong> be muived gif thaur is awreadie ae page at the new title, onless the latter is ae reguidal n haes nae past eedit histerie.
 This means that ye can rename ae page back til whaur it wis renamed fae gif ye mak ae mistak, n ye canna owerwrite aen exeestin page.
 
 <strong>Warnishment!</strong>
-This can be ae drastic n onexpected chynge fer ae popular page;
-please be sair ye unnerstaun the consequences o this afore proceedin.",
+This can be ae drasteec n onexpectit chynge fer ae popular page;
+please be sair ye unnerstaunn the consequences o this afore proceedin.",
 'movepagetext-noredirectfixer' => "Uising the form ablo will rename ae page, muivin aw o its histerie til the new name.
 The auld title will become ae reguidal page til the new title.
 Be sair tae check fer [[Special:DoubleRedirects|dooble]] or [[Special:BrokenRedirects|broken reguidals]].
@@ -2569,16 +2574,16 @@ please be sair that ye unnerstaun the consequences o this afore preceedin.",
 *Ye oncheck the kist ablo.
 
 In thae cases, ye will hae tae muiv or merge the page manuallie gif ye sae desire.',
-'movearticle' => 'Flit page:',
+'movearticle' => 'Muiv page:',
 'moveuserpage-warning' => "<strong>Warnishment:</strong> Ye'r aboot tae muiv ae uiser page. Please tak tent that yinlie the page will be muivd n the uiser will <em>naw</em> be renamed.",
 'movenologintext' => 'Ye maun be a registert uiser n [[Special:UserLogin|loggit in]] tae muiv ae page.',
 'movenotallowed' => 'Ye dinna hae permeession tae muiv pages.',
 'movenotallowedfile' => 'Ye dinna hae permeession tae muiv files.',
 'cant-move-user-page' => 'Ye dinna hae permeession tae muiv uiser pages (aside fae subpages).',
 'cant-move-to-user-page' => 'Ye dinna hae permeession tae muiv ae page til ae uiser page (except til ae uiser subpage).',
-'newtitle' => 'Tae new teitle',
+'newtitle' => 'Til new teitle',
 'move-watch' => 'Watch soorce page n tairget page',
-'movepagebtn' => 'Flit page',
+'movepagebtn' => 'Muiv page',
 'pagemovedsub' => 'Flittin succeedit',
 'movepage-moved' => '<strong>"$1" has been muived til "$2"</strong>',
 'movepage-moved-redirect' => 'Ae reguidal haes been cræftit.',
@@ -2592,7 +2597,7 @@ In thae cases, ye will hae tae muiv or merge the page manuallie gif ye sae desir
 'movepage-page-moved' => 'The page $1 haes been muived til $2.',
 'movepage-page-unmoved' => 'The page $1 coudna be muived til $2.',
 'movepage-max-pages' => 'The mmucklest o $1 {{PLURAL:$1|page|pages}} haes been muived n naw mair will be muived autæmateeclie.',
-'movelogpage' => 'Flit log',
+'movelogpage' => 'Muiv log',
 'movelogpagetext' => "A leet o pages that's flitted is ablo.",
 'movesubpagetext' => 'This page haes $1 {{PLURAL:$1|subpage|subpages}} shawn ablo.',
 'movenosubpage' => 'This page haes naw subpages.',
@@ -2603,8 +2608,8 @@ In thae cases, ye will hae tae muiv or merge the page manuallie gif ye sae desir
 
 The destination airticle "[[:$1]]" aareadies exists. Div ye want tae delyte it fer tae mak wey fer the muiv?',
 'delete_and_move_confirm' => 'Ai, delyte the page',
-'delete_and_move_reason' => 'Deletit fer tae mak way fer muiv fae "[[$1]]"',
-'selfmove' => 'Ootgaun n incomin teitles ar the same; canna flit ae page ower itsel.',
+'delete_and_move_reason' => 'Delytit fer tae mak wa fer muiv fae "[[$1]]"',
+'selfmove' => 'Ootgaun n incomin teitles ar the same; canna muiv ae page ower itsel.',
 'immobile-source-namespace' => 'Canna muiv pages in namespace "$1"',
 'immobile-target-namespace' => 'Canna muiv pages intil namespace "$1"',
 'immobile-target-namespace-iw' => 'Interwiki link isna ae valeed tairget fer page muiv.',
@@ -2617,10 +2622,10 @@ The destination airticle "[[:$1]]" aareadies exists. Div ye want tae delyte it f
 'imageinvalidfilename' => 'The tairget filename is onvalit',
 'fix-double-redirects' => 'Update onie reguidals that poynt til the oreeginal title',
 'move-leave-redirect' => 'Lea ae reguidal ahint',
-'protectedpagemovewarning' => '<strong>Warnishment:</strong> This page haes been protected sae that yinly uisers wi admeenistrater preevileges can muiv it.
-The latest log entry is provided ablo fer reference:',
-'semiprotectedpagemovewarning' => '<strong>Note:</strong> This page has been protected sae that yinly registered uisers can muiv it.
-The hainmaist log entry is provided ablow fer reference:',
+'protectedpagemovewarning' => '<strong>Warnishment:</strong> This page haes been protected sae that yinlie uisers wi admeenistrater preevleges can muiv it.
+The latest log entrie is gien ablo fer referance:',
+'semiprotectedpagemovewarning' => '<strong>Mynd:</strong> This page haes been protected sae that yinlie registered uisers can muiv it.
+The hainmaist log entrie is gien ablo fer referance:',
 'move-over-sharedrepo' => '== File exeests ==
 [[:$1]] exeests oan ae shaired reposeeterie. Muiving ae file til this title will owerride the shaired file.',
 'file-exists-sharedrepo' => 'The filename chosen is awreadie in uise oan ae shaired reposeeterie.
@@ -2637,7 +2642,7 @@ In the latter case ye can uise ae link ava, fer example [[{{#Special:Export}}/{{
 'exportall' => 'Export aw pages',
 'exportcuronly' => 'Inclæde juist the nou reveesion, naw the ful histerie',
 'exportnohistory' => '----
-<strong>Note:</strong> Exporting the ful histerie o pages through this form has been disabled caus o performance raisons.',
+<strong>Mynd:</strong> Exportin the ful histerie o pages throogh this form haes been disabled cause o performance raisons.',
 'exportlistauthors' => 'Incluid ae ful leet o contreebuters fer ilka page',
 'export-addcattext' => 'Add pages fae categerie:',
 'export-addnstext' => 'Add pages fae namespace:',
@@ -2670,7 +2675,7 @@ Please veesit [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisatio
 $2',
 'djvu_page_error' => 'DjVu page oot o range',
 'djvu_no_xml' => 'Onable tae fetch XML fer DjVu file',
-'thumbnail-temp-create' => 'Onable tae cræft temparie thummnail file',
+'thumbnail-temp-create' => 'Onable tae cræft temprie thummnail file',
 'thumbnail-dest-create' => 'Onable tae hain thummnail til desteenation',
 'thumbnail_invalid_params' => 'Onvalit thummnail parameters',
 'thumbnail_dest_directory' => 'Onable tae cræft desteenation directerie',
@@ -2725,6 +2730,9 @@ Please gie it anither gae.',
 'import-rootpage-nosubpage' => 'Namespace "$1" o the ruit page disna permit subpages.',
 
 # Import log
+'importlogpagetext' => 'Admeenistrateeve imports o pages wi eedit histerie fae ither wikis.',
+'import-logentry-upload' => 'imported [[$1]] bi file uplaid',
+'import-logentry-upload-detail' => '$1 {{PLURAL:$1|reveesion|reveesions}}',
 'import-logentry-interwiki-detail' => '$1 {{PLURAL:$1|reveesion|reveesions}} fae $2',
 
 # JavaScriptTest
@@ -2748,7 +2756,7 @@ Please gie it anither gae.',
 'tooltip-pt-logout' => 'Log oot',
 'tooltip-ca-talk' => 'Discussion aneat the content page',
 'tooltip-ca-edit' => 'Ye can eedit this page. Please uise the luikower button afore hainin',
-'tooltip-ca-addsection' => 'Stairt a new section',
+'tooltip-ca-addsection' => 'Stairt ae new section',
 'tooltip-ca-viewsource' => 'This page is protectit.
 Ye can view its soorce',
 'tooltip-ca-history' => 'Bygane reveesions o this page',
@@ -2756,22 +2764,22 @@ Ye can view its soorce',
 'tooltip-ca-unprotect' => 'Chynge protection o this page',
 'tooltip-ca-delete' => 'Delyte this page',
 'tooltip-ca-undelete' => 'Restore the eedits dun oan this page afore it wis delytit',
-'tooltip-ca-move' => 'Flit this page',
-'tooltip-ca-watch' => 'Add this page tae yer watchleet',
+'tooltip-ca-move' => 'Muiv this page',
+'tooltip-ca-watch' => 'Add this page til yer watchleet',
 'tooltip-ca-unwatch' => 'Remove this page frum yer watchleet',
 'tooltip-search' => 'Rake {{SITENAME}}',
-'tooltip-search-go' => 'Gang til ae page wi this exact name gif exists',
+'tooltip-search-go' => 'Gang til ae page wi this exact name gif exeests',
 'tooltip-search-fulltext' => 'Rake the pages fer this tex',
-'tooltip-p-logo' => 'Gang tae the Main Page',
-'tooltip-n-mainpage' => 'Gang tae the Main Page',
-'tooltip-n-mainpage-description' => 'Gang tae the Main Page',
+'tooltip-p-logo' => 'Gang til the Main Page',
+'tooltip-n-mainpage' => 'Gang til the Main Page',
+'tooltip-n-mainpage-description' => 'Gang til the Main Page',
 'tooltip-n-portal' => 'Aneat the project, whit ye can dae, whaur tae fynd things',
 'tooltip-n-currentevents' => "Fin' background speirins oan current events",
 'tooltip-n-recentchanges' => 'The leet o recent chynges in the wiki',
 'tooltip-n-randompage' => 'Laid ae random page',
 'tooltip-n-help' => 'The steid tae fynd oot',
 'tooltip-t-whatlinkshere' => "List o' a' wiki pages that link 'ere",
-'tooltip-t-recentchangeslinked' => 'Recent changes in pages linked frae this page',
+'tooltip-t-recentchangeslinked' => 'Recynt chynges in pages linkt fae this page',
 'tooltip-feed-rss' => 'RSS feed fer this page',
 'tooltip-feed-atom' => 'Atom feed fer this page',
 'tooltip-t-contributions' => "View this uiser's contreebutions",
@@ -2792,7 +2800,7 @@ Ye can view its soorce',
 'tooltip-ca-nstab-category' => 'View the categerie page',
 'tooltip-minoredit' => 'Mairk this as a smaa edit',
 'tooltip-save' => 'Hain yer chynges',
-'tooltip-preview' => 'Scance ower yer chynges, please uise this afore hainin!',
+'tooltip-preview' => 'Luikower yer chynges, please uise this afore hainin!',
 'tooltip-diff' => 'Shaw the chynges that ye makit til the tex.',
 'tooltip-compareselectedversions' => 'See the differs atween the twa selectit versions o this page.',
 'tooltip-watch' => 'Add this page tae yer watchleet',
@@ -2842,6 +2850,7 @@ Div <strong>NAW</strong> ful this in!',
 'pageinfo-robot-noindex' => 'Na permitit',
 'pageinfo-views' => 'Nummer o luiks',
 'pageinfo-watchers' => 'Nummer o page watchers',
+'pageinfo-few-watchers' => 'Less than $1 {{PLURAL:$1|watcher|watchers}}',
 'pageinfo-redirects-name' => 'Nummer o reguidals til this page',
 'pageinfo-subpages-name' => 'Nummer o subpages o this page',
 'pageinfo-subpages-value' => '$1 ($2 {{PLURAL:$2|reguidal|reguidals}}; $3 {{PLURAL:$3|non-reguidal|non-reguidals}})',
@@ -2874,7 +2883,7 @@ Div <strong>NAW</strong> ful this in!',
 'markedaspatrolled' => 'Merkit as patrolled',
 'markedaspatrolledtext' => 'The selected reveesion o [[:$1]] haes been maurked aes patrolled.',
 'rcpatroldisabled' => 'Recynt chynges patrol disabled',
-'rcpatroldisabledtext' => 'The Recent Changes Patrol feature is disabled the nou.',
+'rcpatroldisabledtext' => 'The Recynt Chynges Patrol featur is disabled the nou.',
 'markedaspatrollederror' => 'Canna maurk aes patrowed',
 'markedaspatrollederrortext' => 'Ye need tae speceefie ae reveesion tae maurk aes patrowed.',
 'markedaspatrollederror-noautopatrol' => "Ye'r na permitit tae maurk yer ain chynges aes patrowed.",
@@ -2917,15 +2926,15 @@ Bi executin it, yer system micht be compromised.',
 'file-info-gif-looped' => "luip't",
 'file-info-png-looped' => "luip't",
 'file-info-png-repeat' => 'pleyed $1 {{PLURAL:$1|time|times}}',
-'file-no-thumb-animation' => '<strong>Note: Due til techneecal limitations, thummnails o this file will naw be animated.</strong>',
-'file-no-thumb-animation-gif' => '<strong>Note: Due til technical limitations, thumbnails o hich resolution GIF eimages sic as this will no be animated.</strong>',
+'file-no-thumb-animation' => '<strong>Mynd: Due til techneecal limitations, thummnails o this file will na be animated.</strong>',
+'file-no-thumb-animation-gif' => '<strong>Mynd: Due til techneecal limitations, thummnails o hei resolution GIF eemages sic aes this will na be animated.</strong>',
 
 # Special:NewFiles
 'newimages' => 'Gallery o new files',
 'imagelisttext' => 'Ablo is a leet o $1 {{PLURAL:$1|eimage|eimages}} sortit $2.',
 'newimages-summary' => 'This byordinair page shaws the last uplaidit files.',
 'newimages-label' => 'Filename (or ae pairt o it):',
-'noimages' => 'Naething tae see.',
+'noimages' => 'Nawthing tae see.',
 'ilsubmit' => 'Rake',
 'bydate' => 'bi date',
 'sp-newimages-showfrom' => 'Shaw new files stairtin fae $2, $1',
@@ -2955,7 +2964,7 @@ Ainlie leet items (lines stairtin wi *) ar considered. The foremaist link oan ae
 Gif the file haes bin modified fae its oreeginal state, some details micht naw fullie reflect the modified file.',
 'metadata-expand' => 'Shaw extendit details',
 'metadata-collapse' => 'Skauk extendit details',
-'metadata-fields' => "Image metadata fields leeted in this message wull be inclæded oan eimage page displey whan the metadata buird is collaps't. Ithers wull be skauk't bi defaut. 
+'metadata-fields' => "Eemage metadata fields leetit in this message will be incluidit oan eemage page displey whan the metadata buird is collaps't. Ithers will be skaukt bi defaut. 
 * mak
 * model
 * datetimeoreeginal
@@ -2965,13 +2974,14 @@ Gif the file haes bin modified fae its oreeginal state, some details micht naw f
 * focallength
 * airtist
 * copiericht
-* eimagedescreeption
-* gpslatitude
-* gpslangitude
-* gpsaltitude",
+* eemagedescreeption
+* gpslateetuid
+* gpslangeetuid
+* gpsalteetuid",
 
 # Exif tags
 'exif-imagelength' => 'Heicht',
+'exif-photometricinterpretation' => 'Pixel composeetion',
 'exif-samplesperpixel' => 'Nummer o components',
 'exif-ycbcrsubsampling' => 'Subsamplin ratio o Y til C',
 'exif-ycbcrpositioning' => 'Y n C poseetionin',
@@ -3076,6 +3086,7 @@ Gif the file haes bin modified fae its oreeginal state, some details micht naw f
 'exif-datetimeexpires' => 'Dinna uise efter',
 'exif-datetimereleased' => 'Released oan',
 'exif-originaltransmissionref' => 'Oreeginal transmeession location code',
+'exif-identifier' => 'Identefier',
 'exif-lens' => 'Lens uised',
 'exif-serialnumber' => 'Serial nummer o camera',
 'exif-cameraownername' => 'Ainer o camera',
@@ -3123,7 +3134,7 @@ Gif the file haes bin modified fae its oreeginal state, some details micht naw f
 
 'exif-colorspace-65535' => 'Oncalibratit',
 
-'exif-componentsconfiguration-0' => 'disna exist',
+'exif-componentsconfiguration-0' => 'disna exeest',
 
 'exif-exposureprogram-0' => 'Na defined',
 'exif-exposureprogram-3' => 'Apertur prioritie',
@@ -3254,6 +3265,7 @@ Gif the file haes bin modified fae its oreeginal state, some details micht naw f
 'exif-iimcategory-dis' => 'Disasters n accidants',
 'exif-iimcategory-fin' => 'Economie n business',
 'exif-iimcategory-hth' => 'The Heal',
+'exif-iimcategory-hum' => 'Fawk interest',
 'exif-iimcategory-lab' => 'Laber',
 'exif-iimcategory-lif' => 'Lifestyle n leisure',
 'exif-iimcategory-pol' => 'Poleeteecs',
@@ -3320,50 +3332,185 @@ tae cancel the wab-mail address confirmation:
 $5
 
 This confirmation code will die oan $4.',
+'confirmemail_body_set' => 'Somebodie, proablie ye, fae IP address $1,
+haes set the wab-mail address o the accoont "$2" til this address oan {{SITENAME}}.
+
+Tae confirm that this accoont reallie dis belang til ye n acteevate
+wab-mail featurs oan {{SITENAME}}, apen this link in yer brouser:
+
+$3
+
+Gif the accoont dis *na* belang til ye, follae this link
+tae cancel the wab-mail address confirmation:
+
+$5
+
+This confirmation code will dee at $4.',
+'confirmemail_invalidated' => 'Wab-mail address confirmation canceled',
+'invalidateemail' => 'Cancel wab-mail confirmation',
+
+# Scary transclusion
+'scarytranscludedisabled' => '[Interwiki transcluidin is disabled]',
+'scarytranscludefailed' => '[Template fetch failed fer $1]',
+'scarytranscludefailed-httpstatus' => '[Template fetch failed fer $1: HTTP $2]',
+'scarytranscludetoolong' => '[URL is ower lang]',
 
 # Delete conflict
 'deletedwhileediting' => '<strong>Warnishment:</strong> This page wis delytit efter ye stairted eeditin!',
 'confirmrecreate' => 'Uiser [[User:$1|$1]] ([[User talk:$1|tauk]]) delytit this page efter ye stairted eiditin wi raison:
 : <em>$2</em>
 Please confirm that ye reallie want tae recræft this page.',
+'confirmrecreate-noreason' => 'Uiser [[User:$1|$1]] ([[User talk:$1|tauk]]) delytit this page efter ye stairted eeditin. Please confirm that ye reallie want tae recræft this page.',
+'recreate' => 'Recræft',
 
 # action=purge
 'confirm_purge_button' => 'OK',
 'confirm-purge-top' => 'Clair the cache o this page?',
+'confirm-purge-bottom' => 'Purgin ae page clears the cache n forces the maist recynt reveesion tae appear.',
+
+# action=watch/unwatch
+'confirm-watch-top' => 'Add this page til yer watchleet?',
+'confirm-unwatch-top' => 'Remuiv this page fae yer watchleet?',
 
 # Multipage image navigation
+'imgmultipageprev' => '← preeveeoos page',
+'imgmultipagenext' => 'nex page →',
 'imgmultigo' => 'Gang!',
+'imgmultigoto' => 'Gang til page $1',
+
+# Language selector for translatable SVGs
+'img-lang-default' => '(defaut leid)',
+'img-lang-info' => 'Render this eemage in $1. $2',
+'img-lang-go' => 'Gang',
 
 # Table pager
 'table_pager_next' => 'Page aifter',
 'table_pager_prev' => 'Page afore',
+'table_pager_last' => 'Laist page',
+'table_pager_limit' => 'Shaw $1 eetems per page',
+'table_pager_limit_label' => 'Eetems per page:',
 'table_pager_limit_submit' => 'Gang',
 'table_pager_empty' => 'Nae results',
 
 # Auto-summaries
 'autosumm-blank' => 'Blanked the page',
 'autosumm-replace' => "Replacin page wi '$1'",
-'autoredircomment' => 'Reguidin tae [[$1]]',
+'autoredircomment' => 'Reguidin til [[$1]]',
+'autosumm-new' => 'Cræftit page wi "$1"',
+
+# Live preview
+'livepreview-loading' => 'Laidin...',
+'livepreview-ready' => 'Laidin... Readie!',
+'livepreview-failed' => 'Live luikower failed!
+Gie normal luikower ae gae.',
+'livepreview-error' => 'Failed tae connect: $1 "$2".
+Gie normal luikower ae gae.',
+
+# Friendlier slave lag warnings
+'lag-warn-normal' => 'Chynges newer than $1 {{PLURAL:$1|seicont|seiconts}} micht na be shawn in this leet.',
+'lag-warn-high' => 'Cause o hei database server lag, chynges newer than $1 {{PLURAL:$1|seicont|seiconts}} micht na be shawn in this leet.',
+
+# Watchlist editor
+'watchlistedit-numitems' => 'Yer watchleet contains {{PLURAL:$1|1 title|$1 titles}}, na coontin tauk pages.',
+'watchlistedit-noitems' => 'Yer watchleet contains naw titles.',
+'watchlistedit-normal-title' => 'Eedit watchleet',
+'watchlistedit-normal-legend' => 'Remuiv titles fae watchleet',
+'watchlistedit-normal-explain' => 'Titles oan yer watchleet ar shawn ablo.
+Tae remuiv ae title, check the kist nex til it, n clap "{{int:Watchlistedit-normal-submit}}".
+Ye can [[Special:EditWatchlist/raw|eedit the raw leet]] ava.',
+'watchlistedit-normal-submit' => 'Remuiv titles',
+'watchlistedit-normal-done' => '{{PLURAL:$1|1 title wis|$1 titles were}} remuived fae yer watchleet:',
+'watchlistedit-raw-title' => 'Eedit raw watchleet',
+'watchlistedit-raw-legend' => 'Eedit raw watchleet',
+'watchlistedit-raw-explain' => 'Titles oan yer watchleet ar shawn ablo, n can be eeditit bi addin til n remuivin fae the leet;
+yin title per line.
+Whan dun, clap "{{int:Watchlistedit-raw-submit}}".
+Ye can [[Special:EditWatchlist|uise the staundairt eediter]] ava.',
+'watchlistedit-raw-submit' => 'Update watchleet',
+'watchlistedit-raw-done' => 'Yer watchleet haes been updated.',
+'watchlistedit-raw-added' => '{{PLURAL:$1|1 title wis|$1 titles were}} added:',
+'watchlistedit-raw-removed' => '{{PLURAL:$1|1 title wis|$1 titles were}} remuived:',
 
 # Watchlist editing tools
-'watchlisttools-view' => 'View relevant changes',
+'watchlisttools-view' => 'See reelavant chynges',
 'watchlisttools-edit' => 'See n eedit watchleet',
 'watchlisttools-raw' => 'Eedit raw watchleet',
 
+# Signatures
+'signature' => '[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1|tauk]])',
+
 # Core parser functions
-'duplicate-defaultsort' => '\'\'\'Wairnin:\'\'\' Default sort key "$2" overrides earlier default sort key "$1".',
+'unknown_extension_tag' => 'Onkent extension tag "$1"',
+'duplicate-defaultsort' => '<strong>Warnishment:</strong> Defaut sort key "$2" owerrides earlier defaut sort key "$1".',
 
 # Special:Version
+'version-extensions' => 'Instawed extensions',
+'version-specialpages' => 'Byordinar pages',
+'version-parserhooks' => 'Parser huiks',
+'version-variables' => 'Vareeables',
+'version-other' => 'Ither',
+'version-mediahandlers' => 'Media haunnlers',
+'version-hooks' => 'Huiks',
+'version-parser-function-hooks' => 'Parser function huiks',
+'version-hook-name' => 'Huik name',
+'version-hook-subscribedby' => 'Subscribed bi',
+'version-ext-colheader-description' => 'Descreeption',
+'version-ext-colheader-credits' => 'Writers',
+'version-license-title' => 'License fer $1',
+'version-license-not-found' => 'Naw detailed license information wis foond fer this extension.',
+'version-credits-title' => 'Creedits fer $1',
+'version-credits-not-found' => 'Naw detailed creedits information wis foond fer this extension.',
 'version-poweredby-credits' => 'This wiki is pwred bi <strong>[https://www.mediawiki.org/ MediaWiki]</strong>, copiericht © 2001-$1 $2.',
+'version-poweredby-others' => 'ithers',
+'version-poweredby-translators' => 'translatewiki.net owerseters',
+'version-credits-summary' => "We'd like tae recognize the follaein fawk fer thair contreebution til [[Special:Version|MediaWiki]].",
+'version-license-info' => 'MediaWiki is free saffware; ye can reedistreebute it n/or modifie it unner the terms o the GNU General Public License aes publeesht bi the Free Software Foundation; either version 2 o the License, or (bi yer optie) onie later version.
+
+MediaWiki is distreebuted in the hope that it will be uissfu, bit WIOOT ONIE WARRANTIE; wioot even the implied warrantie o MERCHANTABILITIE or FITNESS FER AE PARTEECULAR PURPYSS. See the GNU General Public License fer mair details.
+
+Ye shid hae receeved [{{SERVER}}{{SCRIPTPATH}}/COPIEIN ae copie o the GNU General Public License] alang wi this program; gif na, write til the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA or [//www.gnu.org/licenses/old-licenses/gpl-2.0.html read it online].',
+'version-software' => 'Instawed saffware',
+'version-entrypoints' => 'Entrie point URLs',
+'version-entrypoints-header-entrypoint' => 'Entrie point',
+
+# Special:Redirect
+'redirect' => 'Reguidal bi file, uiser, page or reveesion ID',
+'redirect-legend' => 'Reguidal til ae file or page',
+'redirect-summary' => 'This byordiair page reguides til ae file (gien the file name), ae page (gien ae reveesion ID or page ID), or ae uiser page (gien ae numereec uiser ID). Uissage: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/page/64308]], [[{{#Special:Redirect}}/reveesion/328429]], or [[{{#Special:Redirect}}/uiser/101]].',
+'redirect-submit' => 'Gang',
+'redirect-lookup' => 'Luikup:',
+'redirect-user' => 'Uiser ID',
+'redirect-revision' => 'Page reveesion',
+'redirect-not-exists' => 'Value na foond',
 
 # Special:FileDuplicateSearch
+'fileduplicatesearch' => 'Rake fer dupleecate files',
+'fileduplicatesearch-summary' => 'Rake fer dupleecate files based oan hash values.',
+'fileduplicatesearch-legend' => 'Rake fer ae dupleecate',
 'fileduplicatesearch-filename' => 'Filename:',
 'fileduplicatesearch-submit' => 'Rake',
+'fileduplicatesearch-result-1' => 'The file "$1" haes naw identeecal dupleecation.',
+'fileduplicatesearch-result-n' => 'The file "$1" haes {{PLURAL:$2|1 identeecal dupleecation|$2 identeecal dupleecations}}.',
+'fileduplicatesearch-noresults' => 'Naw file named "$1" foond.',
 
 # Special:SpecialPages
 'specialpages' => 'Byordinar pages',
+'specialpages-note' => '* Normal byordinair pages.
+* <span class="mw-specialpagerestricted">Restreected byordinair pages.</span>',
+'specialpages-group-other' => 'Ither byordinair pages',
+'specialpages-group-login' => 'Login / cræft accoont',
+'specialpages-group-changes' => 'Recynt chynges n logs',
+'specialpages-group-media' => 'Media reports n uplaids',
 'specialpages-group-users' => 'Uisers n richts',
+'specialpages-group-highuse' => 'Hei uiss pages',
 'specialpages-group-pages' => 'leet o pages',
+'specialpages-group-pagetools' => 'Page tuils',
+'specialpages-group-wiki' => 'Data n tuils',
+'specialpages-group-redirects' => 'Reguidin byordinair pages',
+'specialpages-group-spam' => 'Spam tuils',
+
+# Special:BlankPage
+'intentionallyblankpage' => 'This page is intentionlie left blank.',
 
 # External image whitelist
 'external_image_whitelist' => ' #Lea this line exactlie aes it is<pre>
@@ -3376,15 +3523,177 @@ Please confirm that ye reallie want tae recræft this page.',
 #Put aw regex fragments abuin this line. Lea this line exactlie aes it is</pre>',
 
 # Special:Tags
+'tags' => 'Valit chynge tags',
 'tag-filter' => '[[Special:Tags|Tag]] filter:',
 'tag-filter-submit' => 'Filter',
+'tags-intro' => 'This page leets the tags that the saffware can maurk aen eedit wi, n thair meanin.',
+'tags-display-header' => 'Appearance oan chynge leets',
+'tags-description-header' => 'Ful descreeption o meanin',
+'tags-active-header' => 'Acteeve?',
+'tags-hitcount-header' => 'Tagged chynges',
+'tags-active-yes' => 'Ay',
+'tags-active-no' => 'Naw',
 'tags-edit' => 'eedit',
+'tags-hitcount' => '$1 {{PLURAL:$1|chynge|chynges}}',
+
+# Special:ComparePages
+'compare-rev1' => 'Reveesion 1',
+'compare-rev2' => 'Reveesion 2',
+'compare-invalid-title' => 'The title that ye speceefied is onvalit.',
+'compare-title-not-exists' => 'The title that ye speceefied disna exeest.',
+'compare-revision-not-exists' => 'The reveesion that ye speceefied disna exeest.',
+
+# Database error messages
+'dberr-header' => 'This wiki haes ae proablem',
+'dberr-problems' => 'Sairrie! This site is expereeancin techneecal diffeculties.',
+'dberr-again' => 'Gie it ae few minutes n than relaid.',
+'dberr-info' => '(Canna contact the database server: $1)',
+'dberr-info-hidden' => '(Canna contact the database server)',
+'dberr-usegoogle' => 'Ye can dae ae rake bi wa o Google in the meanwhile.',
+'dberr-outofdate' => 'Mynd that thair indexes o oor content micht be oot o date.',
+'dberr-cachederror' => 'This is ae cached copie o the requested page, n micht na be up til date.',
 
 # HTML forms
 'htmlform-invalid-input' => 'Thau ar proablems wi some o yer input.',
+'htmlform-select-badoption' => 'The value that ye speceefied isna ae valit optie.',
+'htmlform-int-invalid' => 'The value that ye speceefied isna aen integer.',
+'htmlform-float-invalid' => 'The value that ye speceefied isna ae nummer.',
 'htmlform-int-toolow' => 'The value that ye speceefied is ablo the smaaest o $1.',
 'htmlform-int-toohigh' => 'The value that ye speceefied is abuin the mucklest o $1.',
 'htmlform-required' => 'This value is needit.',
+'htmlform-submit' => 'Haun-in',
+'htmlform-reset' => 'Ondae chynges',
 'htmlform-selectorother-other' => 'Ither',
+'htmlform-no' => 'Naw',
+'htmlform-yes' => 'Ay',
+'htmlform-chosen-placeholder' => 'Select aen optie',
+
+# SQLite database support
+'sqlite-has-fts' => '$1 wi ful-tex rake support',
+'sqlite-no-fts' => '$1 wioot ful-tex rake support',
+
+# New logging system
+'logentry-delete-delete' => '$1 {{GENDER:$2|delytit}} page $3',
+'logentry-delete-event' => '$1 {{GENDER:$2|chynged}} veesibeelitie o {{PLURAL:$5|ae log event|$5 log events}} oan $3: $4',
+'logentry-delete-revision' => '$1 {{GENDER:$2|chynged}} veesibeelitie o {{PLURAL:$5|ae reveesion|$5 reveesions}} oan page $3: $4',
+'logentry-delete-event-legacy' => '$1 {{GENDER:$2|chynged}} veesibeelitie o log events oan $3',
+'logentry-delete-revision-legacy' => '$1 {{GENDER:$2|chynged}} veesibeelitie o reveesions oan page $3',
+'logentry-suppress-event' => '$1 hidlinswise {{GENDER:$2|chynged}} veesibeelitie o {{PLURAL:$5|ae log event|$5 log events}} oan $3: $4',
+'logentry-suppress-revision' => '$1 hidlinswise {{GENDER:$2|chynged}} veesibeelity o {{PLURAL:$5|ae reveesion|$5 reveesions}} oan page $3: $4',
+'logentry-suppress-event-legacy' => '$1 hidlinswise {{GENDER:$2|chynged}} veesibeelitie o log events oan $3',
+'logentry-suppress-revision-legacy' => '$1 hidlinswise {{GENDER:$2|chynged}} veesibeelitie o reveesions oan page $3',
+'revdelete-content-hid' => 'content skaukt',
+'revdelete-summary-hid' => 'eedit ootline skaukt',
+'revdelete-uname-hid' => 'uisername skaukt',
+'revdelete-content-unhid' => 'content onskaukt',
+'revdelete-summary-unhid' => 'eedit ootline onskaukt',
+'revdelete-uname-unhid' => 'uisername onskaukt',
+'revdelete-restricted' => 'applied restreections til admeenistraters',
+'revdelete-unrestricted' => 'remuived restreections fer admeenistraters',
+'logentry-move-move' => '$1 {{GENDER:$2|muived}} page $3 til $4',
+'logentry-move-move-noredirect' => '$1 {{GENDER:$2|muived}} page $3 til $4 wioot leain ae reguidal',
+'logentry-move-move_redir' => '$1 {{GENDER:$2|muived}} page $3 til $4 ower reguidal',
+'logentry-move-move_redir-noredirect' => '$1 {{GENDER:$2|muived}} page $3 til $4 ower ae reguidal wioot leain ae reguidal',
+'logentry-patrol-patrol' => '$1 {{GENDER:$2|maurkt}} reveesion $4 o page $3 patrowed',
+'logentry-patrol-patrol-auto' => '$1 autæmateeclie {{GENDER:$2|maurkt}} reveesion $4 o page $3 patrowed',
+'logentry-newusers-newusers' => 'Uiser accoont $1 wis {{GENDER:$2|cræftit}}',
+'logentry-newusers-create' => 'Uiser accoont $1 wis {{GENDER:$2|cræftit}}',
+'logentry-newusers-create2' => 'Uiser accoont $3 wis {{GENDER:$2|cræftit}} bi $1',
+'logentry-newusers-byemail' => 'Uiser accoont $3 wis {{GENDER:$2|cræftit}} bi $1 n passwaird wis sent bi wab-mail',
+'logentry-newusers-autocreate' => 'Uiser accoont $1 wis {{GENDER:$2|cræftit}} autæmateeclie',
+'logentry-rights-rights' => '$1 {{GENDER:$2|chynged}} groop memmership fer $3 fae $4 til $5',
+'logentry-rights-rights-legacy' => '$1 {{GENDER:$2|chynged}} groop memmership fer $3',
+'logentry-rights-autopromote' => '$1 wis autæmateeclie {{GENDER:$2|promoted}} fae $4 til $5',
+'rightsnone' => '(nane)',
+
+# Feedback
+'feedback-bugornote' => 'Gif yer readie tae describe ae techneecal problem in detail please [$1 report ae bug].
+Itherwise, ye can uiss the easie form ablo. Yer comment will be added til the page "[$3 $2]", alang wi yer uisername.',
+'feedback-adding' => 'Addin feedback til page...',
+'feedback-error1' => 'Mistak: Onrecognised ootcome fae API',
+'feedback-error2' => 'Mistak: Eedit failed',
+'feedback-error3' => 'Mistak: Naw response fae API',
+'feedback-thanks' => 'Thanks! Yer feedback haes been posted til the page "[$2 $1]".',
+'feedback-close' => 'Dun',
+'feedback-bugcheck' => "Wunnerfu! Just check that it's na awreadie yin o the [$1 knawn bugs].",
+'feedback-bugnew' => 'Ah checkt. Report ae new bug',
+
+# Search suggestions
+'searchsuggest-search' => 'Rake',
+'searchsuggest-containing' => 'containin...',
+
+# API errors
+'api-error-badaccess-groups' => "Ye'r na permittit tae uplaid files til this wiki.",
+'api-error-copyuploaddisabled' => 'Uplaidin bi URL is disabled oan this server.',
+'api-error-duplicate' => 'Thaur {{PLURAL:$1|is [$2 anither file]|ar [$2 some ither files]}} awreadie oan the site wi the same content.',
+'api-error-duplicate-archive' => 'Thaur {{PLURAL:$1|wis [$2 anither file]|were [$2 some ither files]}} awreadie oan the site wi the same content, but {{PLURAL:$1|it wis|thay were}} delytit.',
+'api-error-duplicate-archive-popup-title' => 'Dupleecate {{PLURAL:$1|file that haes|files that hae}} awreadie been delytit.',
+'api-error-duplicate-popup-title' => 'Dupleecate {{PLURAL:$1|file|files}}.',
+'api-error-empty-file' => 'The file that ye haunnit in wis tuim.',
+'api-error-emptypage' => 'Cræftin new, tuim pages isna permittit.',
+'api-error-fetchfileerror' => 'Internal mistak: Sommit went wrang while fetchin the file.',
+'api-error-fileexists-forbidden' => 'Ae file wi the name "$1" awreadie exeests, n canna be owerwritten.',
+'api-error-fileexists-shared-forbidden' => 'Ae file wi the name "$1" awreadie exeests in the shaired file reposeetair, n canna be owerwritten.',
+'api-error-file-too-large' => 'The file that ye haunnit in wis ower muckle.',
+'api-error-filename-tooshort' => 'The filename is ower short.',
+'api-error-filetype-banned' => 'This type o file is banned.',
+'api-error-filetype-banned-type' => '$1 {{PLURAL:$4|isna ae permittit file type|arna permittit file types}}. Permittit {{PLURAL:$3|file type is|file types ar}} $2.',
+'api-error-filetype-missing' => 'The filename is missin aen extension.',
+'api-error-hookaborted' => 'The modeefication that ye gave makin ae gae wis abortit bi aen extension.',
+'api-error-http' => 'Internal mistak: Onable tae connect til server.',
+'api-error-illegal-filename' => 'The filename isna permitit.',
+'api-error-internal-error' => 'Internal mistak: Sommit went wrang wi processin yer uplaid oan the wiki.',
+'api-error-invalid-file-key' => 'Internal mistak: File wisna foond in temparie storage.',
+'api-error-missingparam' => 'Internal mistak: Missin boonds oan request.',
+'api-error-missingresult' => 'Internal mistak: Coudna determine gif the copie succeeded.',
+'api-error-mustbeloggedin' => 'Ye maun be loggit in tae uplaid files.',
+'api-error-mustbeposted' => 'Internal mistak: Request needs HTTP POST.',
+'api-error-noimageinfo' => 'The uplaid succeeded, bit the server didna gie us onie information aneat the file.',
+'api-error-nomodule' => 'Internal mistak: Naw uplaid module set.',
+'api-error-ok-but-empty' => 'Internal mistak: Naw response fae server.',
+'api-error-overwrite' => 'Owerwritin aen exeestin file isna permitit.',
+'api-error-stashfailed' => 'Internal mistak: Server failed tae store temparie file.',
+'api-error-publishfailed' => 'Internal mistak: Server failed tae publeesh temparie file.',
+'api-error-stasherror' => 'Thaur wis ae mistak while uplaidin the file tae stash.',
+'api-error-timeout' => 'The server didna respond wiin the expectit time.',
+'api-error-unclassified' => 'Aen onkent mistake occurred.',
+'api-error-unknown-error' => 'Internal mistak: Sommit went wrang whan uplaidin yer file.',
+'api-error-uploaddisabled' => 'Uplaidin is disabled oan this wiki.',
+'api-error-verification-error' => 'This file micht be rotten, or hae the wrang extension.',
+
+# Durations
+'duration-seconds' => '$1 {{PLURAL:$1|seicont|seiconts}}',
+'duration-hours' => '$1 {{PLURAL:$1|hoor|hoors}}',
+'duration-centuries' => '$1 {{PLURAL:$1|centuair|centuairs}}',
+
+# Image rotation
+'rotate-comment' => 'Eemage rotated bi $1 {{PLURAL:$1|degree|degrees}} clockwise',
+
+# Limit report
+'limitreport-title' => 'Parser profilin data:',
+'limitreport-cputime' => 'CPU time uissage',
+'limitreport-cputime-value' => '$1 {{PLURAL:$1|seicont|seiconts}}',
+'limitreport-walltime' => 'Real time uissage',
+'limitreport-walltime-value' => '$1 {{PLURAL:$1|seicont|seiconts}}',
+'limitreport-ppvisitednodes' => 'Preprocessor veesitit node coont',
+'limitreport-ppgeneratednodes' => 'Preprocessor generated node coont',
+'limitreport-postexpandincludesize' => 'Post-expand incluid size',
+'limitreport-expansiondepth' => 'Heiest expansion depth',
+'limitreport-expensivefunctioncount' => 'Expensive parser function coont',
+
+# Special:ExpandTemplates
+'expand_templates_intro' => 'This byordiair page taks tex n expauns aw templates in it recurseevelie.
+It foreby expaunds supported parser functions like
+<code><nowiki>{{</nowiki>#language:…}}</code> n vareeables like
+<code><nowiki>{{</nowiki>CURRENTDAY}}</code>.
+In fact, it expauns just aboot awthings in dooble-braces.',
+'expand_templates_title' => 'Contex title, fer {{FULLPAGENAME}}, etc.:',
+'expand_templates_output' => 'Ootcome',
+'expand_templates_xml_output' => 'XML ootpit',
+'expand_templates_html_output' => 'Raw HTML ootpit',
+'expand_templates_remove_nowiki' => 'Suppress <nowiki> tags in ootcome',
+'expand_templates_generate_xml' => 'Shaw XML parse tree',
+'expand_templates_generate_rawhtml' => 'Shaw raw HTML',
+'expand_templates_preview' => 'Luikower',
 
 );
index ee3fd90..8a03222 100644 (file)
@@ -668,8 +668,6 @@ Pamiegīkėt [[Special:Search|ėiškoutė pruojektė]] sosėjosiu naujū poslapi
 'rev-delundel' => 'ruodītė/kavuotė',
 'revisiondelete' => 'Trintė/atkortė versėjės',
 'logdelete-selected' => "{{PLURAL:$2|Pasėrinkts|Pasėrinktė|Pasėrinktė}} '''$1''' istuorėjės {{PLURAL:$2|atėtėkims|atsėtėkimā|atsėtėkimā}}:",
-'revdelete-text' => "'''Ėštrintuos versėjės ėr ivīkē vistėik da bus ruodomė poslapė istuorėjuo ėr specēliūju veiksmū istuorėjuo, no anū torėnė dalīs nabus vėišā pasėikiamos.'''
-Kėtė admėnėstratuorē šėtom pruojekte vėsdar galės pasėiktė pasliepta torėni ėr galės ana atkortė viel par šėta pate sasaja, nabent īr nostatītė papėlduomė aprėbuojėmā.",
 'revdelete-unsuppress' => 'Šalėntė apribuojėmos atkortuos versėjės',
 'revdel-restore' => 'Keistė veizėmuma',
 'revdelete-edit-reasonlist' => 'Keistė trīnėma prīžastis',
index 4a58588..95a618d 100644 (file)
@@ -1150,8 +1150,6 @@ ili ta revizija ne postoji, ili pokušavate sakriti trenutnu reviziju.',
 'revdelete-show-file-submit' => 'Da',
 'revdelete-selected' => "'''{{PLURAL:$2|Odabrana revizija|Odabrane revizije}} od [[:$1]]:'''",
 'logdelete-selected' => "'''{{PLURAL:$1|Označena stavka registra|Označene stavke registra}}:'''",
-'revdelete-text' => "'''Obrisane revizije i događaji će i dalje biti vidljivi u historiji stranice i registrima, ali dijelovi njenog sadržaja neće biti dostupni javnosti.'''
-Drugi administratori projekta {{SITENAME}} će i dalje moći pristupiti sakrivenom sadržaju i mogu ga ponovo vratiti kroz ovaj interfejs, osim ako nisu postavljena dodatna ograničenja.",
 'revdelete-confirm' => 'Molimo potvrdite da namjeravate ovo učiniti, da razumijete posljedice i da to činite u skladu s [[{{MediaWiki:Policy-url}}|pravilima]].',
 'revdelete-suppress-text' => "Ograničenja bi trebala biti korištena '''samo''' u sljedećim slučajevima:
 * Osjetljive korisničke informacije
index 36b883e..52093e7 100644 (file)
@@ -1133,8 +1133,6 @@ $3 විසින් සපයා ඇති හේතුව ''$2'' වේ",
 'revdelete-show-file-submit' => 'ඔව්',
 'revdelete-selected' => "'''[[:$1]] හි {{PLURAL:$2|තෝරාගත් සංශෝධනය|තෝරාගත් සංශෝධනයන්}} :'''",
 'logdelete-selected' => "'''{{PLURAL:$1|තෝරාගත් ලඝු-සිදුවීම|තෝරාගත් ලඝු-සිදුවීම්}}:'''",
-'revdelete-text' => "'''මකාදැමුණු සංශෝධනයන් හා සිද්ධීන් තවදුරටත් පිටු විත්ති හා ලඝු-සටහන් හි දර්ශනය වුවද, ප්‍රජාව ට ප්‍රවිෂ්ඨ විය හැක්කේ ඒවායේ අන්තර්ගතයෙන් කොටසකටය.'''
-අමතර සීමා පණවා නොමැති නම්, සැඟවුනු අන්තර්ගතයට එළඹී, යම් අතුරුමුහුණතක් ඔස්සේ,   එය මකාදැමුම යළි අවලංගු කිරීමට, {{SITENAME}} හි අනෙකුත් පරිපාලකයන්හට තවමත් අවතාශ ඇත්තේය.",
 'revdelete-confirm' => 'කරුණාකර ඔබ මෙය කිරීමට අදහස් කරන බවත්,එහි ප්‍රතිඵලය අවබෝධ කර ගන්නා බවත්,මෙය සිදු කරනුයේ [[{{MediaWiki:Policy-url}}| ප්‍රතිපත්තියට]] අනුකූලව බවත් තහවුරු කරන්න.',
 'revdelete-suppress-text' => "යටපත්කිරීම පහත අවස්ථාවන්හිදී  '''පමණක්''' භාවිතා කල යුතුය:
 * නුසුදුසු පෞද්ගලික තොරතුරු
index d6d1f89..b4bf336 100644 (file)
@@ -822,6 +822,10 @@ Prosím, počkajte $1 predtým, než to skúsite znova.',
 'suspicious-userlogout' => 'Vaša požiadavka odhlásiť sa bola zamietnutá, pretože to vyzerá, že ju poslal pokazený prehliadač alebo proxy server.',
 'createacct-another-realname-tip' => 'Skutočné meno je nepovinné.
 Ak sa rozhodnete ho poskytnúť, použije sa na označenie vašej práce.',
+'pt-login' => 'Prihlásiť sa',
+'pt-login-button' => 'Prihlásiť sa',
+'pt-createaccount' => 'Vytvoriť účet',
+'pt-userlogout' => 'Odhlásiť sa',
 
 # Email sending
 'php-mail-error-unknown' => 'Neznáma chyba vo funkcii PHP mail()',
@@ -830,7 +834,7 @@ Ak sa rozhodnete ho poskytnúť, použije sa na označenie vašej práce.',
 
 # Change password dialog
 'changepassword' => 'Zmeniť heslo',
-'resetpass_announce' => 'Prishlásili ste sa pomocou dočasného emailom zaslaného kódu. Pre dokončenie prihlásenia je potrebné tu nastaviť nové heslo:',
+'resetpass_announce' => 'Pre dokončenie prihlásenia je potrebné nastaviť nové heslo.',
 'resetpass_text' => '<!-- Sem pridajte text -->',
 'resetpass_header' => 'Zmeniť heslo k účtu',
 'oldpassword' => 'Staré heslo:',
@@ -845,6 +849,7 @@ Ak sa rozhodnete ho poskytnúť, použije sa na označenie vašej práce.',
 'resetpass-submit-cancel' => 'Zrušiť',
 'resetpass-wrong-oldpass' => 'Neplatné dočasné alebo aktuálne heslo.
 Je možné, že sa vám už podarilo úspešne zmeniť svoje heslo alebo ste si vyžiadali nové dočasné heslo.',
+'resetpass-recycled' => 'Ako nové heslo si prosím nastavte niečo iné než súčasné heslo.',
 'resetpass-temp-password' => 'Dočasné heslo:',
 'resetpass-abort-generic' => 'Zmena hesla bola zablokovaná rozšírením.',
 
@@ -1232,8 +1237,6 @@ Ako správca si môžete tento rozdiel zobraziť; podrobnosti môžete nájsť v
 'revdelete-show-file-submit' => 'Áno',
 'revdelete-selected' => "'''{{PLURAL:$2|Vybraná jedna revízia|Vybrané $2 revízie|Vybraných $2 revízií}} z [[:$1]]:'''",
 'logdelete-selected' => "'''{{PLURAL:$1|Vybraná udalosť záznamu|Vybrané udalosti záznamu}}:'''",
-'revdelete-text' => "'''Zmazané revízie a udalosti sú stále viditeľné v histórii úprav stránky, ale časti ich obsahu nebudú prístupné verejnosti.'''
-Iní správcovia {{GRAMMAR:genitív|{{SITENAME}}}} budú stále môcť pristupovať k skrytému obsahu a môžu ho znova obnoviť použitím tohto rozhrania v prípade, že nie sú stanovené ďalšie obmedzenia.",
 'revdelete-confirm' => 'Prosím, potvrďte, že to naozaj chcete vykonať, rozumiete následkom a že to robíte v súlade s [[{{MediaWiki:Policy-url}}|politikou]].',
 'revdelete-suppress-text' => "Zatajenie by sa malo používať '''výlučne''' v nasledovných prípadoch:
 * Potenciálne hanlivé informácie
@@ -1686,11 +1689,23 @@ Softvér používa toto nastavenie na správne oslovenie a označenie vás ostat
 'rcnotefrom' => "Nižšie sú zobrazené úpravy od '''$2''' (do '''$1''').",
 'rclistfrom' => 'Zobraziť nové úpravy počnúc od $1',
 'rcshowhideminor' => '$1 drobné úpravy',
+'rcshowhideminor-show' => 'Zobraziť',
+'rcshowhideminor-hide' => 'Skryť',
 'rcshowhidebots' => '$1 botov',
+'rcshowhidebots-show' => 'Zobraziť',
+'rcshowhidebots-hide' => 'Skryť',
 'rcshowhideliu' => '$1 registrovaní užívatelia',
+'rcshowhideliu-show' => 'Zobraziť',
+'rcshowhideliu-hide' => 'Skryť',
 'rcshowhideanons' => '$1 anonymných používateľov',
+'rcshowhideanons-show' => 'Zobraziť',
+'rcshowhideanons-hide' => 'Skryť',
 'rcshowhidepatr' => '$1 úpravy strážených stránok',
+'rcshowhidepatr-show' => 'Zobraziť',
+'rcshowhidepatr-hide' => 'Skryť',
 'rcshowhidemine' => '$1 moje úpravy',
+'rcshowhidemine-show' => 'Zobraziť',
+'rcshowhidemine-hide' => 'Skryť',
 'rclinks' => 'Zobraziť posledných $1 úprav v posledných $2 dňoch<br />$3',
 'diff' => 'rozdiel',
 'hist' => 'história',
@@ -2178,7 +2193,15 @@ Každý riadok obsahuje odkaz na prvé a druhé presmerovanie a tiež prvý riad
 'protectedpages' => 'Zamknuté stránky',
 'protectedpages-indef' => 'Zamknutia iba na neurčito',
 'protectedpages-cascade' => 'Iba kaskádové zamykanie',
+'protectedpages-noredirect' => 'Skryť presmerovania',
 'protectedpagesempty' => 'Momentálne nie sú žiadne stránky s týmito parametrami zamknuté.',
+'protectedpages-timestamp' => 'Časová známka',
+'protectedpages-page' => 'Stránka',
+'protectedpages-expiry' => 'Koniec platnosti',
+'protectedpages-params' => 'Nastavenie zámku',
+'protectedpages-reason' => 'Dôvod',
+'protectedpages-unknown-timestamp' => 'Neznáme',
+'protectedpages-unknown-performer' => 'Neznámy redaktor',
 'protectedtitles' => 'Zamknuté názvy',
 'protectedtitlesempty' => 'Tieto parametre momentálne nezamykajú žiadne názvy stránok.',
 'listusers' => 'Zoznam používateľov',
@@ -3796,6 +3819,10 @@ Prosím, potvrďte, že túto stránku chcete skutočne znovu vytvoriť.",
 'imgmultigo' => 'Vykonať',
 'imgmultigoto' => 'Prejsť na stránku $1',
 
+# Language selector for translatable SVGs
+'img-lang-default' => '(predvolený jazyk)',
+'img-lang-go' => 'Vykonať',
+
 # Table pager
 'ascending_abbrev' => 'vzostupne',
 'descending_abbrev' => 'zostupne',
@@ -3879,7 +3906,13 @@ Tiež môžete [[Special:EditWatchlist|použiť štandardný editor]].',
 'version-hook-subscribedby' => 'Pripojené',
 'version-version' => '(Verzia $1)',
 'version-license' => 'Licencia',
+'version-ext-license' => 'Licencia',
+'version-ext-colheader-name' => 'Rozšírenie',
 'version-ext-colheader-version' => 'Verzia',
+'version-ext-colheader-license' => 'Licencia',
+'version-ext-colheader-description' => 'Popis',
+'version-ext-colheader-credits' => 'Autori',
+'version-license-title' => 'Licencia pre $1',
 'version-poweredby-credits' => "Táto wiki beží na '''[https://www.mediawiki.org/ MediaWiki]''', copyright © 2001-$1 $2.",
 'version-poweredby-others' => 'ďalší',
 'version-poweredby-translators' => 'prekladatelia na translatewiki.net',
index 9d6e7de..c0edded 100644 (file)
@@ -738,6 +738,7 @@ Prosimo, počakajte $1, preden poskusite znova.',
 'createacct-another-realname-tip' => 'Pravo ime ni obvezno.
 Če se ga odločite navesti, bo uporabljeno za priznavanje uporabnikovega dela.',
 'pt-login' => 'Prijava',
+'pt-login-button' => 'Prijava',
 'pt-createaccount' => 'Ustvari račun',
 'pt-userlogout' => 'Odjava',
 
@@ -1160,8 +1161,6 @@ To redakcijo si lahko ogledate; podrobnosti lahko najdete v [{{fullurl:{{#Specia
 'revdelete-show-file-submit' => 'Da',
 'revdelete-selected' => "'''{{PLURAL:$2|Izbrana redakcija|Izbrani redakciji|Izbrane redakcije}} strani [[:$1]]:'''",
 'logdelete-selected' => "'''{{PLURAL:$1|Izbran dnevniški dogodek|Izbrana dnevniška dogodka|Izbrani dnevniški dogodki}}:'''",
-'revdelete-text' => "'''Izbrisane redakcije in dogodki bodo v zgodovini strani in dnevniki še vedno navedene, vendar bo njihova vsebina za javnost nedostopna.'''
-Do skrite vsebine bodo še vedno lahko dostopali drugi administratorji {{GRAMMAR:rodilnik|{{SITENAME}}}} in jo z uporabo istega vmesnika tudi obnovili, razen kjer bodo uveljavljene dodatne omejitve.",
 'revdelete-confirm' => 'Prosim potrdite da nameravate to storiti, da se zavedate posledic in da to počnete v skladu s [[{{MediaWiki:Policy-url}}|politiko]].',
 'revdelete-suppress-text' => "Zadrževanje naj bi bilo uporabljeno '''le''' v sledečih primerih:
 * Morebitni klevetniški podatki
@@ -1298,7 +1297,7 @@ Podrobnosti lahko najdete v [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENA
 'search-file-match' => '(ujema se z vsebino datoteke)',
 'search-suggest' => 'Iščete morda: $1',
 'search-interwiki-caption' => 'Sorodni projekti',
-'search-interwiki-default' => '$1 zadetkov:',
+'search-interwiki-default' => 'Rezultati s strani $1:',
 'search-interwiki-more' => '(več)',
 'search-relatedarticle' => 'Podobno',
 'searcheverything-enable' => 'Iskanje po vseh imenskih prostorih',
index 536882e..5a71bc2 100644 (file)
@@ -484,6 +484,7 @@ Waa iska dhago tiri kartaa fariintaan, hadii akoonkaan oo ku sameysmay qalad.',
 Fadlan waxyar sug intii aadan soo gelin.',
 'login-abort-generic' => 'Ma u soo gali karin gudaha - waa la noqay',
 'loginlanguagelabel' => 'Luqada: $1',
+'pt-userlogout' => 'Ka bax',
 
 # Email sending
 'user-mail-no-addy' => "Isku dayday in aa dirto e-mail ayada oo ciwaan e-mail la'aan ah.",
@@ -789,11 +790,14 @@ sababteeda neh waxaa laga heli kartaa  [{{fullurl:{{#Special:Log}}/delete|page={
 'skin-preview' => 'Horfiirin',
 'datedefault' => "Ma'jiro dooq",
 'prefs-datetime' => 'Taariikhda iyo waqtiga',
+'prefs-personal' => 'Galka isticmaalaha',
 'prefs-rc' => 'Isbedelada dhow',
 'prefs-watchlist' => 'liiska-waardiyaha',
 'prefs-watchlist-days' => 'Tirada maalamaha ay ku jirayaan liiska-waardiyaha:',
 'prefs-email' => 'E-mail aad dooran kartaa',
+'prefs-rendering' => 'Muuqaalka',
 'saveprefs' => 'Kaydi',
+'restoreprefs' => 'Dib u soo celin qaabeynta (dhammaan qaybaha)',
 'prefs-editing' => 'Wax ka bedelka',
 'searchresultshead' => 'Raadi',
 'recentchangesdays' => 'Tirada maalmaha lagu tusaayo isbedelada dhow:',
@@ -1092,8 +1096,8 @@ si aad ugu dirto E-boosto isticmaalayaasha kale.',
 'emailsenttext' => 'Fariintaadii E-mailka aheeyd waa la diray.',
 
 # Watchlist
-'watchlist' => 'Liiskeyga waardiyeynta',
-'mywatchlist' => 'Liiskeyga waardiyeynta',
+'watchlist' => 'Liiska-waardiyaha',
+'mywatchlist' => 'Liiska-waardiyaha',
 'watchlistfor2' => 'Ku socoto $1 $2',
 'nowatchlist' => 'Waxba kuma jiraan liiskaaga waardiyeynta.',
 'watchlistanontext' => 'Fadlan $1 si aad u fiirisid ama wax uga bedeshid qoraalada ku jira liiska waardiyeyska.',
@@ -1379,6 +1383,7 @@ Waxaa fiiri kartaa cadaadkiisa',
 
 # Info page
 'pageinfo-title' => 'Macluumaad ku saabsan "$1"',
+'pageinfo-header-basic' => 'Macaaluumaadka asaasiga ah',
 'pageinfo-toolboxlink' => 'Macluumad ku saabsan',
 
 # Browsing diffs
@@ -1471,6 +1476,7 @@ waxaad awoodaa [[Special:EditWatchlist/raw|Liiska wax ka bedel]].',
 
 # Special:Tags
 'tag-filter' => '[[Special:Tags|Filtaraha]] tag:',
+'tags-display-header' => 'Muuqaalka liiska bedelka',
 
 # Database error messages
 'dberr-usegoogle' => 'Waxaa baroobeen kartaa in aad ka raadiso google',
index 9a20472..4de5936 100644 (file)
@@ -1088,7 +1088,6 @@ Ju mund ta shikoni këtë ndryshim; detajet mund të gjenden te [{{fullurl:{{#Sp
 'revdelete-show-file-submit' => 'Po',
 'revdelete-selected' => "'''{{PLURAL:$2|Versioni i zgjedhur i|Versionet e zgjedhura të}} [[:$1]]:'''",
 'logdelete-selected' => "'''{{PLURAL:$1|Veprimi i zgjedhur në regjistër|Veprimet e zgjedhura në regjistër}}:'''",
-'revdelete-text' => "'''Përmbajtja dhe pjesët e tjera nuk janë të dukshme për të gjithë, por figurojnë në historikun e versioneve.''' Administratorët munden përmbajtjen e larguar ta shikojnë dhe restaurojnë, përveç në rastet kur një gjë e tillë është ndaluar ekstra.",
 'revdelete-confirm' => 'Ju lutem konfirmoni që keni ndër mënd ta bëni këtë, që i kuptoni pasojat, dhe që ju po veproni në përputhje me [[{{MediaWiki:Policy-url}}|politiken]].',
 'revdelete-suppress-text' => "Shuarje duhet'''vetëm'''të përdoret për rastet e mëposhtme: 
  * Potencialisht e informacionit shpifës 
index 132c506..3f9d59f 100644 (file)
@@ -940,6 +940,7 @@ $2',
 'createacct-another-realname-tip' => 'Право име није обавезно.
 Ако изаберете да га унесете, оно ће бити коришћено за приписивање вашег рада.',
 'pt-login' => 'Пријави ме',
+'pt-login-button' => 'Пријави ме',
 'pt-createaccount' => 'Отвори налог',
 'pt-userlogout' => 'Одјави ме',
 
@@ -976,6 +977,7 @@ $2',
 # Special:PasswordReset
 'passwordreset' => 'Обнављање лозинке',
 'passwordreset-text-one' => 'Попуните овај образац да бисте ресетовали лозинку.',
+'passwordreset-text-many' => '{{PLURAL:$1|Испуните једно од поља како би сте добили привремену лозинку на е-пошту.}}',
 'passwordreset-legend' => 'Поништи лозинку',
 'passwordreset-disabled' => 'Обнављање лозинке је онемогућено на овом викију.',
 'passwordreset-emaildisabled' => 'Е-пошта је онемогућена на овом викију.',
@@ -1347,8 +1349,6 @@ $2
 'revdelete-show-file-submit' => 'Да',
 'revdelete-selected' => "'''{{PLURAL:$2|Изабрана измена|Изабране измене}} странице [[:$1]]'''",
 'logdelete-selected' => "'''{{PLURAL:$1|Изабрана ставка у историји|Изабране ставке у историји}}:'''",
-'revdelete-text' => "'''Обрисане измене ће и даље бити приказане у историји страница и записима, али делови њиховог садржаја неће бити доступни јавности.'''
-Други администратори на овом викију ће и даље имати приступ сакривеном садржају, а они ће тај садржај моћи да врате путем овог сучеља, осим ако нису постављена додатна ограничења.",
 'revdelete-confirm' => 'Потврдите да намеравате ово урадити, да разумете последице и да то чините у складу с [[{{MediaWiki:Policy-url}}|правилима]].',
 'revdelete-suppress-text' => "Сакривање измена би требало користити '''само''' у следећим случајевима:
 * Злонамерни или погрдни подаци
@@ -2314,20 +2314,32 @@ $1',
 'mostrevisions' => 'Странице с највише измена',
 'prefixindex' => 'Све странице с префиксом',
 'prefixindex-namespace' => 'Све странице с предметком (именски простор $1)',
+'prefixindex-strip' => 'Сакриј префикс у списку',
 'shortpages' => 'Кратке странице',
 'longpages' => 'Дугачке странице',
 'deadendpages' => 'Странице без унутрашњих веза',
 'deadendpagestext' => 'Следеће странице немају везе до других страница на овом викију.',
 'protectedpages' => 'Заштићене странице',
 'protectedpages-indef' => 'само неограничене заштите',
+'protectedpages-summary' => 'На овој страници се налази списак тренутно заштићених страница. За списак заштићених наслова види [[{{#special:ProtectedTitles}}]].',
 'protectedpages-cascade' => 'само преносиве заштите',
 'protectedpages-noredirect' => 'сакриј преусмерења',
 'protectedpagesempty' => 'Нема заштићених страница с овим параметрима.',
+'protectedpages-timestamp' => 'Време и датум',
+'protectedpages-page' => 'Страница',
+'protectedpages-expiry' => 'Истиче',
+'protectedpages-performer' => 'Заштитио',
+'protectedpages-params' => 'Ниво заштите',
+'protectedpages-reason' => 'Разлог',
+'protectedpages-unknown-timestamp' => 'нема',
+'protectedpages-unknown-performer' => 'нема',
 'protectedtitles' => 'Заштићени наслови',
+'protectedtitles-summary' => 'На овој страници се налази списак тренутно заштићених наслова. За списак тренутно заштићених страница види [[{{#special:ProtectedPages}}]].',
 'protectedtitlesempty' => 'Нема заштићених наслова с овим параметрима.',
 'listusers' => 'Списак корисника',
 'listusers-editsonly' => 'прикажи само кориснике који су уређивали',
 'listusers-creationsort' => 'поређај по датуму стварања',
+'listusers-desc' => 'сортирај у опадајућем редоследу',
 'usereditcount' => '$1 {{PLURAL:$1|измена|измене|измена}}',
 'usercreated' => '{{GENDER:$3|је направио|је направила|је направио}} дана $1 у $2',
 'newpages' => 'Нове странице',
@@ -4215,6 +4227,12 @@ $5
 'version-version' => '(издање $1)',
 'version-svn-revision' => '(изм. $2)',
 'version-license' => 'Лиценца',
+'version-ext-license' => 'Лиценца',
+'version-ext-colheader-name' => 'Екстензија',
+'version-ext-colheader-version' => 'Верзија',
+'version-ext-colheader-license' => 'Лиценца',
+'version-ext-colheader-description' => 'Опис',
+'version-ext-colheader-credits' => 'Аутори',
 'version-poweredby-credits' => "Овај вики покреће '''[https://www.mediawiki.org/ Медијавики]''', ауторска права © 2001-$1 $2.",
 'version-poweredby-others' => 'остали',
 'version-poweredby-translators' => 'translatewiki.net преводиоци',
index 29339f6..20cbfe8 100644 (file)
@@ -855,6 +855,7 @@ Možda ste već promenili lozinku ili ste zatražili novu privremenu lozinku.',
 # Special:PasswordReset
 'passwordreset' => 'Obnavljanje lozinke',
 'passwordreset-text-one' => 'Popunite ovaj obrazac da biste resetovali lozinku.',
+'passwordreset-text-many' => '{{PLURAL:$1|Ispunite jedno od polja kako bi ste dobili privremenu lozinku na e-poštu.}}',
 'passwordreset-legend' => 'Poništi lozinku',
 'passwordreset-disabled' => 'Obnavljanje lozinke je onemogućeno na ovom vikiju.',
 'passwordreset-username' => 'Korisničko ime:',
@@ -1223,8 +1224,6 @@ Ipak možete da vidite ovu razliku; više detalja možete naći u [{{fullurl:{{#
 'revdelete-show-file-submit' => 'Da',
 'revdelete-selected' => "'''{{PLURAL:$2|Izabrana izmena|Izabrane izmene}} stranice [[:$1]]'''",
 'logdelete-selected' => "'''{{PLURAL:$1|Izabrana stavka u istoriji|Izabrane stavke u istoriji}}:'''",
-'revdelete-text' => "'''Obrisane izmene će i dalje biti prikazane u istoriji stranica i zapisima, ali delovi njihovog sadržaja neće biti dostupni javnosti.'''
-Drugi administratori na ovom vikiju će i dalje imati pristup sakrivenom sadržaju, a oni će taj sadržaj moći da vrate putem ovog sučelja, osim ako nisu postavljena dodatna ograničenja.",
 'revdelete-confirm' => 'Potvrdite da nameravate ovo uraditi, da razumete posledice i da to činite u skladu s [[{{MediaWiki:Policy-url}}|pravilima]].',
 'revdelete-suppress-text' => "Sakrivanje izmena bi trebalo koristiti '''samo''' u sledećim slučajevima:
 * Zlonamerni ili pogrdni podaci
@@ -2169,11 +2168,20 @@ Sada je preusmerenje na [[$2]].',
 'protectedpages-cascade' => 'samo prenosive zaštite',
 'protectedpages-noredirect' => 'sakrij preusmerenja',
 'protectedpagesempty' => 'Nema zaštićenih stranica s ovim parametrima.',
+'protectedpages-timestamp' => 'Vreme i datum',
+'protectedpages-page' => 'Stranica',
+'protectedpages-expiry' => 'Ističe',
+'protectedpages-performer' => 'Zaštitio',
+'protectedpages-params' => 'Nivo zaštite',
+'protectedpages-reason' => 'Razlog',
+'protectedpages-unknown-timestamp' => 'nema',
+'protectedpages-unknown-performer' => 'nema',
 'protectedtitles' => 'Zaštićeni naslovi',
 'protectedtitlesempty' => 'Nema zaštićenih naslova s ovim parametrima.',
 'listusers' => 'Spisak korisnika',
 'listusers-editsonly' => 'prikaži samo korisnike koji su uređivali',
 'listusers-creationsort' => 'poređaj po datumu stvaranja',
+'listusers-desc' => 'sortiraj u opadajućem redosledu',
 'usereditcount' => '$1 {{PLURAL:$1|izmena|izmene|izmena}}',
 'usercreated' => '{{GENDER:$3|je napravio|je napravila|je napravio}} dana $1 u $2',
 'newpages' => 'Nove stranice',
index 90f54a7..222dae8 100644 (file)
@@ -832,8 +832,6 @@ Du koast dissen Versionsunnerskeed bekiekje, wan du wolt. Details fiende sik in
 'revdelete-show-file-submit' => 'Jee',
 'revdelete-selected' => "'''{{PLURAL:$2|Uutwäälde Version|Uutwäälde Versione}} fon [[:$1]]:'''",
 'logdelete-selected' => "'''{{PLURAL:$1|Uutwäälden Logboukiendraach|Uutwäälde Logboukiendraage}}:'''",
-'revdelete-text' => "'''Läskede Versione un Aktione ferblieuwe in ju Versionsgeskichte un do Logbouke, man Deele deerfon sunt nit eepentelk ientoukiekjen.'''
-Uur Administratore ap {{SITENAME}} hääbe Tougriep ap dän ferstatte Inhoold un konnen him mäd ju glieke Siede wier moakje, insowied uurhoop neen Ientuunengen bestounde.",
 'revdelete-confirm' => 'Bestäätigje, dät du dit wuddelk dwo wolt, dät du do Konsequenze ferstoanst un dät in Uureenstimmenge mäd do [[{{MediaWiki:Policy-url}}|Gjuchtlienjen]] dääst.',
 'revdelete-suppress-text' => "Unnerdrukkengen skuulen '''bloot''' in do foulgjende Fälle foarnuumen waide:
 * Uunpaasende persöönelke Informatione
index 8c8326c..d44340f 100644 (file)
@@ -903,8 +903,6 @@ Salaku kuncen, mun perlu, anjeun bisa kénéh [$1 nempo bédana].",
 'revdelete-show-file-submit' => 'Enya',
 'revdelete-selected' => "'''{{PLURAL:$2|Révisi pilihan|Révisi pilihan}} pikeun '''$1''''''",
 'logdelete-selected' => "'''{{PLURAL:$1|pilihan keur log|pilihan keur log}}:'''",
-'revdelete-text' => "'''Revisi sarta tindakan anu geus dihapus baris tetep mecenghul di kaca vérsi tiheula, tapi teks eusi henteu bisa diakses ku publik.'''
-Kuncén séjén bakalan bisa ngakses eusi nu nyumput sarta bisa ngabolaykeun hapusan ngaliwatan antarmuka anu sarua, kajaba lamun aya pangbates séjén anu dijieun ku operator loka",
 'revdelete-confirm' => 'Mangga geura konfirmasi yen Anjeun gaduh maksad pikeun ngalakukeun hal ieu, paham kana konsekwensina, tur nu dilakukeun ieu teh luyu sareng [[{{MediaWiki:Policy-url}}|kawijakanana]]',
 'revdelete-suppress-text' => "Nyumputkeun revisi '''ukur''' bisa digunakeun keur kasus-kasus di handap ieu:
 * Informasi nu boga potensi mitenah
index 65951d1..d545fad 100644 (file)
@@ -864,6 +864,7 @@ Vänta $1 innan du försöker igen.',
 'createacct-another-realname-tip' => 'Riktiga namnet är valfritt.
 Om du väljer att ange det, kommer det användas för att tillskriva användaren för sitt arbete.',
 'pt-login' => 'Logga in',
+'pt-login-button' => 'Logga in',
 'pt-createaccount' => 'Skapa konto',
 'pt-userlogout' => 'Logga ut',
 
@@ -1285,8 +1286,10 @@ eller så försöker du gömma den senaste versionen av sidan.',
 'revdelete-show-file-submit' => 'Ja',
 'revdelete-selected' => "'''{{PLURAL:$2|Vald version|Valda versioner}} av [[:$1]]:'''",
 'logdelete-selected' => "'''{{PLURAL:$1|Vald loggåtgärd|Valda loggåtgärder}}:'''",
-'revdelete-text' => "'''Borttagna versioner och åtgärder kommer fortfarande att synas i historiken och i loggar, men deras innehåll kommer ej att vara tillgängligt för allmänheten.'''
-Andra administratörer på {{SITENAME}} kommer fortfarande att kunna läsa det dolda innehållet och kan återställa sidan genom samma gränssnitt, om inte ytterligare begränsningar finns.",
+'revdelete-text-text' => 'Raderade sidversioner kommer fortfarande synas i sidans historik, men delar av innehållet kommer inte att bli tillgängligt offentligt.',
+'revdelete-text-file' => 'Raderade filversioner kommer fortfarande synas i filens historik, men delar av innehållet kommer inte att bli tillgängligt offentligt.',
+'logdelete-text' => 'Raderade logghändelser kommer fortfarande synas i loggarna, men delar av innehållet kommer inte att bli tillgängligt offentligt.',
+'revdelete-text-others' => 'Andra administratörer på {{SITENAME}} kommer fortfarande att kunna komma åt det dolda innehållet och återställa det igen genom samma gränssnitt om inte tilläggande begränsningar används.',
 'revdelete-confirm' => 'Var god bekräfta att du vill göra detta, och att du förstår konsekvenserna, och att du gör så i enlighet med [[{{MediaWiki:Policy-url}}|policyn]].',
 'revdelete-suppress-text' => "Undanhållande ska '''bara''' användas i följande fall:
 * Eventuell förolämpande information
@@ -1422,7 +1425,7 @@ Detaljer kan hittas i [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}
 'search-file-match' => '(överensstämmer filens innehåll)',
 'search-suggest' => 'Menade du: $1',
 'search-interwiki-caption' => 'Systerprojekt',
-'search-interwiki-default' => 'Resultat i $1:',
+'search-interwiki-default' => 'Resultat från $1:',
 'search-interwiki-more' => '(mer)',
 'search-relatedarticle' => 'Relaterad',
 'searcheverything-enable' => 'Sök i alla namnrymder',
@@ -2725,6 +2728,7 @@ Orsaken till senaste blockeringen kan ses nedan:',
 'sp-contributions-blocked-notice-anon' => 'Denna IP-adress är för närvarande blockerad.
 Den senaste posten i blockeringsloggen visas nedan som referens:',
 'sp-contributions-search' => 'Sök efter användarbidrag',
+'sp-contributions-suppresslog' => 'undanhållna användarbidrag',
 'sp-contributions-username' => 'IP-adress eller användarnamn:',
 'sp-contributions-toponly' => 'Visa endast aktuella sidversioner',
 'sp-contributions-newonly' => 'Visa endast redigeringar där sidor skapas',
index 2f3ca8b..1c6d68a 100644 (file)
@@ -977,8 +977,6 @@ Unaweza masasisho; maelezo mengine yapo kwenye [{{fullurl:{{#Special:Log}}/delet
 'revdelete-show-file-submit' => 'Ndiyo',
 'revdelete-selected' => "'''{{PLURAL:$2|Pitio lililoteuliwa|Mapitio yaliyoteuliwa}} ya [[:$1]]:'''",
 'logdelete-selected' => "'''{{PLURAL:$1|Tukio la kumbukumbu lililoteuliwa|Matukio ya kumbukumbu yaliyoteuliwa}}:'''",
-'revdelete-text' => "'''Mapitio bado yataonekana kwenye ukurasa wa historia na matukio bado yataonekana kwenye kumbukumbu, lakini baadhi ya yaliyomo haitaonekana mbele ya watu wote.'''
-Wakabidhi wengine wa {{SITENAME}} bado wataweza kuliona lile lililofichwa pamoja na kulirudisha kwa kuutumia ukurasa maalum huu huu, isipowekewa vizuio vingine.",
 'revdelete-confirm' => 'Tafadhali uthibitishe kwamba unataka kufanya hivyo, pamoja na kwamba unaelewa matokeo yake, na unafanya hivyo kutokana na [[{{MediaWiki:Policy-url}}|sera yetu]].',
 'revdelete-suppress-text' => "Kuficha kunaruhisiwa '''tu''' wakati hizo:
 * Taarifa zinazowezekana kwamba ni za kukashifu
index d1e150d..6eb719e 100644 (file)
@@ -885,9 +885,6 @@ Powody wyćepańo idźe znejść we [{{fullurl:{{#Special:Log}}/suppress|page={{
 'revdelete-show-file-submit' => 'Ja',
 'revdelete-selected' => "'''{{PLURAL:$2|Wybrano wersyjo|Wybrane wersyje}} zajty [[:$1]]:'''",
 'logdelete-selected' => "'''{{PLURAL:$1|Wybrane zdarzyńy ze rejeru|Wybrane zdarzyńa ze rejeru}}:'''",
-'revdelete-text' => "'''Wyćepane wersyje bydům dali widoczne w historyji zajty, nale jejich treść ńy bydźe publiczńy dostympna.'''
-
-Inkśi admińistratorzi {{GRAMMAR:D.lp|{{SITENAME}}}} dali bydům mjeć dostymp do schrůńůnych wersyji a bydům můgli je wćepać nazod, chyba aże uoperator serwisu nouożůł dodatkowe uograńiczyńo.",
 'revdelete-legend' => 'Naštaluj uograńičyńo lo wersyji:',
 'revdelete-hide-text' => 'Schrůń tekst wersyji',
 'revdelete-hide-image' => 'Schrůń zawartość plika',
index b4d1470..93ae352 100644 (file)
@@ -976,9 +976,6 @@ $1 எனும் பயனரையோ வேறு [[{{MediaWiki:Grouppage-sy
 'revdelete-show-file-submit' => 'ஆம்',
 'revdelete-selected' => "'''[[:$1]] பக்கத்தின் தெரிவுச் செய்யப்பட்ட {{PLURAL:$2|திருத்தம்|திருத்தங்கள்}}:'''",
 'logdelete-selected' => "'''தெரிவு செய்யப்பட்ட பதிகை {{PLURAL:$1|நிகழ்வு|நிகழ்வுகள்}}:'''",
-'revdelete-text' => "'''நீக்கப்பட்ட நிகழ்வுகள் மற்றும் திருத்தங்கள், வரலாற்றுப் பக்கத்திலும் குறிப்புகளிலும் தெரியும். ஆனால் அவற்றின் உள்ளடக்கத்தை எல்லோரும் பார்க்கமுடியாது.'''
-
-மேலதிக கட்டுப்பாடுகளை விதிக்காமல் இருந்தால்,  {{SITENAME}} இத்தளத்தில் உள்ள மற்ற நிர்வாகிகள், இந்த இணைப்பின் மூலம்,  மறைந்துள்ள பகுதிகளை அணுகவும் மீட்டெடுக்கவும் முடியும்.",
 'revdelete-confirm' => 'நீங்கள் கண்டிப்பாக இதைச் செய்ய விரும்புகிறீர்கள் என்பதையும்,  இதன் விளைவுகளை புரிந்துகொண்டிருக்கின்றீர்கள் என்பதையும், மேலும் நீங்கள் [[{{MediaWiki:Policy-url}}|செயல் திட்டம்]] படி செய்கிறீர்கள் என்பதையும் உறுதிசெயுங்கள்.',
 'revdelete-suppress-text' => "ஒடுக்கப்படுவது கீழ்காணும் '''காரணங்களுக்காக''' மட்டுமே செய்யப்படும்.
 *அவதூறான தீங்கு விளைவிக்கக்கூடிய தகவல்
index 79faa58..9f3e7df 100644 (file)
@@ -313,7 +313,7 @@ $messages = array(
 'vector-view-viewsource' => 'మూలాన్ని చూపించు',
 'actions' => 'పనులు',
 'namespaces' => 'పేరుబరులు',
-'variants' => 'à°°à°\95à°°à°\95ాలు',
+'variants' => 'వివిధ à°°à±\82à°ªాలు',
 
 'navigation-heading' => 'మార్గదర్శకపు మెనూ',
 'errorpagetitle' => 'లోపం',
@@ -690,6 +690,7 @@ $2',
 'createacct-another-realname-tip' => 'అసలు పేరు ఐచ్ఛికం.
 మీరు దాన్ని ఇస్తే, వాడుకరి పనుల శ్రేయస్సు ఆ పేరుకు ఆపాదించబడుతుంది.',
 'pt-login' => 'లాగినవండి',
+'pt-login-button' => 'లాగినవండి',
 'pt-createaccount' => 'ఖాతా సృష్టించు',
 'pt-userlogout' => 'లాగౌటవండి',
 
@@ -1099,8 +1100,6 @@ $3 ఇచ్చిన కారణం: ''$2''",
 'revdelete-show-file-submit' => 'అవును',
 'revdelete-selected' => '<strong>[[:$1]] యొక్క {{PLURAL:$2|ఎంచుకున్న కూర్పు|ఎంచుకున్న కూర్పులు}}:</strong>',
 'logdelete-selected' => '<strong>{{PLURAL:$1|ఎంచుకున్న చిట్టా ఘటన|ఎంచుకున్న చిట్టా ఘటనలు}}:</strong>',
-'revdelete-text' => '<strong>తొలగించిన కూర్పులు, ఘటనలూ పేజీ చరితం లోనూ, చిట్టాలలోనూ కనిపిస్తాయి, కానీ వాటిలో కొన్ని భాగాలు సార్వజనికంగా అందుబాటులో ఉండవు.</strong>
-{{SITENAME}} లోని ఇతర నిర్వాహకులు ఆ దాచిన భాగాలను చూడగలరు మరియు (ఇతర నియంత్రణలేమీ లేకపోతే) అదే అంతరవర్తి ద్వారా వాటిని పునస్థాపించగలరు.',
 'revdelete-confirm' => 'మీరు దీన్ని చేయగోరుతున్నారనీ, దీని పర్యవసానాలు మీకు తెలుసుననీ, దీన్ని సంబంధిత [[{{MediaWiki:Policy-url}}|విధానం]] ప్రకారమే చేస్తున్నారనీ నిర్ధారించండి.',
 'revdelete-suppress-text' => 'అణచివేతను కింది సందర్భాలలో <strong>మాత్రమే</strong> వాడాలి:
 * బురదజల్లే ధోరణిలో ఉన్న సమాచారం
@@ -1234,7 +1233,7 @@ $1",
 'search-file-match' => '(ఫైలు విషయంతో సరిపోలుతోంది)',
 'search-suggest' => 'మీరు అంటున్నది ఇదా: $1',
 'search-interwiki-caption' => 'సోదర ప్రాజెక్టులు',
-'search-interwiki-default' => '$1 ఫలితాలు:',
+'search-interwiki-default' => '$1 à°¨à±\81à°\82à°¡à°¿ à°«à°²à°¿à°¤à°¾à°²à±\81:',
 'search-interwiki-more' => '(మరిన్ని)',
 'search-relatedarticle' => 'సంబంధించినవి',
 'searcheverything-enable' => 'అన్ని పేరుబరుల్లో వెతుకు',
@@ -1735,7 +1734,8 @@ $1',
 'upload-file-error' => 'అంతర్గత లోపం',
 'upload-file-error-text' => 'సర్వరులో తాత్కాలిక ఫైలును సృష్టించబోగా ఏదో అంతర్గత లోపం తలెత్తింది. ఎవరైనా [[Special:ListUsers/sysop|నిర్వాహకుడిని]] సంప్రదించండి.',
 'upload-misc-error' => 'తెలియని ఎక్కింపు లోపం',
-'upload-misc-error-text' => 'ఎక్కిస్తూండగా ఏదో తెలియని లోపం తలెత్తింది. URL సరైనదేనని, అది అందుబాటులోనే ఉందని నిర్ధారించుకుని మళ్ళీ ప్రయత్నించండి. సమస్య అలాగే ఉంటే, సిస్టము నిర్వాహకుని సంప్రదించండి.',
+'upload-misc-error-text' => 'ఎక్కిస్తూండగా ఏదో తెలియని లోపం తలెత్తింది. 
+URL సరైనదేనని, అది అందుబాటులోనే ఉందని నిర్ధారించుకుని మళ్ళీ ప్రయత్నించండి. సమస్య అలాగే ఉంటే, [[Special:ListUsers/sysop|నిర్వాహకులు]] ఎవరినైనా సంప్రదించండి.',
 'upload-too-many-redirects' => 'ఆ URLలో చాలా దారిమార్పులు ఉన్నాయి',
 'upload-unknown-size' => 'సైజు తెలియదు',
 'upload-http-error' => 'ఒక HTTP పొరపాటు జరిగింది: $1',
@@ -2198,23 +2198,23 @@ https://www.mediawiki.org/wiki/Manual:Image_Authorization చూడండి.',
 'mailnologintext' => 'ఇతరులకు ఈ-మెయిలు పంపించాలంటే, మీరు [[Special:UserLogin|లాగిన్‌]] అయి ఉండాలి, మరియు మీ [[Special:Preferences|అభిరుచుల]]లో సరైన ఈ-మెయిలు చిరునామా ఇచ్చి ఉండాలి.',
 'emailuser' => 'ఈ వాడుకరికి ఈ-మెయిలుని పంపించండి',
 'emailuser-title-target' => 'ఈ {{GENDER:$1|వాడుకరికి}} ఈమెయిలు పంపించండి',
-'emailuser-title-notarget' => 'à°\88-à°®à±\86యిలà±\81 à°µà°¾à°¡à±\81à°\95à°°ి',
+'emailuser-title-notarget' => 'వాడà±\81à°\95à°°à°¿à°\95à°¿ à°\88à°®à±\86యిలà±\81 à°ªà°\82పిà°\82à°\9aà°\82à°¡ి',
 'emailpage' => 'వాడుకరికి ఈ-మెయిలుని పంపించు',
 'emailpagetext' => 'ఈ {{GENDER:$1|వాడుకరికి}} ఈమెయిలు సందేశము పంపించుటకు క్రింది ఫారంను ఉపయోగించవచ్చు. [[Special:Preferences|మీ వాడుకరి అభిరుచుల]]లో మీరిచ్చిన ఈ-మెయిలు చిరునామా "నుండి" ఆ సందేశం వచ్చినట్లుగా ఉంటుంది, కనుక వేగుని అందుకునేవారు నేరుగా మీకు జవాబివ్వగలుగుతారు.',
 'usermailererror' => 'మెయిలు ఆబ్జెక్టు ఈ లోపాన్ని చూపింది:',
 'defemailsubject' => 'వాడుకరి "$1" నుండి {{SITENAME}} ఈ-మెయిలు',
-'usermaildisabled' => 'వాడుకరి ఈ-మెయిళ్ళు అచేతనం చేసారు',
+'usermaildisabled' => 'వాడుకరి ఈమెయిలు అచేతనం చెయ్యబడింది',
 'usermaildisabledtext' => 'ఈ వికీలో మీరు ఇతర వాడుకరులకి ఈ-మెయిళ్ళని పంపించలేరు',
 'noemailtitle' => 'ఈ-మెయిలు చిరునామా లేదు',
 'noemailtext' => 'ఈ వాడుకరి సరైన ఈ-మెయిలు చిరునామాని ఇవ్వలేదు.',
-'nowikiemailtitle' => 'ఈ-మెయిళ్ళను అనుమతించరు',
+'nowikiemailtitle' => 'ఈమెయిలుకు అనుమతి లేదు',
 'nowikiemailtext' => 'ఇతర వాడుకరుల నుండి ఈ-మెయిళ్ళను అందుకోడానికి ఈ వాడుకరి సుముఖంగా లేరు.',
 'emailnotarget' => 'గ్రహీతగా ఇచ్చిన వాడుకరిపేరు తప్పైనా కావచ్చు, లేదా అసలే ఉండి ఉండకపోవచ్చు',
 'emailtarget' => 'అందుకొనేవారి వాడుకరిపేరు ఇవ్వండి',
 'emailusername' => 'వాడుకరి పేరు:',
-'emailusernamesubmit' => 'దాà°\96à°²à±\81à°\9aà±\86à°¯à±\8dయి',
+'emailusernamesubmit' => 'à°ªà°\82పిà°\82à°\9aà±\81',
 'email-legend' => 'మరో {{SITENAME}} వాడుకరికి వేగు పంపించండి',
-'emailfrom' => 'à°\8eవరà±\81:',
+'emailfrom' => 'à°\8eవరి à°¨à±\81à°\82à°¡à°¿:',
 'emailto' => 'ఎవరికి:',
 'emailsubject' => 'విషయం:',
 'emailmessage' => 'సందేశం:',
@@ -2256,12 +2256,12 @@ https://www.mediawiki.org/wiki/Manual:Image_Authorization చూడండి.',
 'watchlistcontains' => 'మీ వీక్షణ జాబితాలో {{PLURAL:$1|ఒక పేజీ ఉంది|$1 పేజీలు ఉన్నాయి}}.',
 'iteminvalidname' => "'$1' తో ఇబ్బంది, సరైన పేరు కాదు...",
 'wlnote2' => '$2, $3 సమయానికి, గత {{PLURAL:$1|గంటలో|<strong>$1</strong> గంటల్లో}}, జరిగిన మార్పులు కింద ఇవ్వబడ్డాయి.',
-'wlshowlast' => 'గత $1 గంటలు $2 రోజులు $3 చూపించు',
+'wlshowlast' => 'గత $1 గంటల $2 రోజుల $3 చూపించు',
 'watchlist-options' => 'వీక్షణ జాబితా ఎంపికలు',
 
 # Displayed when you click the "watch" button and it is in the process of watching
-'watching' => 'à°\97మనిసà±\8dà°¤à±\81à°¨à±\8dనాà°\82...',
-'unwatching' => 'à°µà±\80à°\95à±\8dà°·à°£ à°¨à±\81à°\82à°¡à°¿ à°¤à±\8aà°²à°\97à°¿à°¸à±\8dà°¤à±\81à°¨à±\8dనా...',
+'watching' => 'à°\97మనిసà±\8dà°¤à±\81à°¨à±\8dనారà±\81...',
+'unwatching' => 'à°\97మనిà°\82à°\9aà°¡à°\82 à°²à±\87à°¦à±\81...',
 'watcherrortext' => '"$1" కు మీ సెట్టింగులను మార్చేటపుడు ఏదో లోపం దొర్లింది.',
 
 'enotif_mailer' => '{{SITENAME}} ప్రకటన మెయిలు పంపునది',
@@ -2312,7 +2312,7 @@ $UNWATCHURL
 # Delete
 'deletepage' => 'పేజీని తొలగించు',
 'confirm' => 'ధృవీకరించు',
-'excontent' => "à°\87దివరà°\95à±\81 విషయ సంగ్రహం: '$1'",
+'excontent' => "à°\89à°¨à±\8dà°¨ విషయ సంగ్రహం: '$1'",
 'excontentauthor' => 'ఉన్న విషయ సంగ్రహం: "$1" (మరియు దీని ఒకే ఒక్క రచయిత "[[Special:Contributions/$2|$2]]")',
 'exbeforeblank' => "ఖాళీ చెయ్యకముందు పేజీలో ఉన్న విషయ సంగ్రహం: '$1'",
 'exblank' => 'పేజీ ఖాళీగా ఉంది',
@@ -2339,7 +2339,7 @@ $UNWATCHURL
 'delete-edit-reasonlist' => 'తొలగింపు కారణాలని మార్చండి',
 'delete-toobig' => 'ఈ పేజీకి $1 {{PLURAL:$1|కూర్పుకు|కూర్పులకు}} మించిన, చాలా పెద్ద దిద్దుబాటు చరితం ఉంది. {{SITENAME}}కు అడ్డంకులు కలగడాన్ని నివారించేందుకు గాను, అలాంటి పెద్ద పేజీల తొలగింపును నియంత్రించాం.',
 'delete-warning-toobig' => 'ఈ పేజీకి $1 {{PLURAL:$1|కూర్పుకు|కూర్పులకు}} మించిన, చాలా పెద్ద దిద్దుబాటు చరితం ఉంది. దాన్ని తొలగిస్తే {{SITENAME}}కి చెందిన డేటాబేసు కార్యాలకు ఆటంకం కలగొచ్చు; అప్రమత్తతో ముందుకుసాగండి.',
-'deleting-backlinks-warning' => "'''హెచ్చరిక:''' మీరు తొలగించబోతున్న పేజీకి ఇతర పేజీల నుండి లింకులు ఉన్నాయి లేదా ఇక్కడ నుండి ట్రాన్స్‍క్లూడు అవుతున్నాయి.",
+'deleting-backlinks-warning' => "'''హెచ్చరిక:''' మీరు తొలగించబోతున్న పేజీకి [[Special:WhatLinksHere/{{FULLPAGENAME}}|ఇతర పేజీల]] నుండి లింకులు ఉన్నాయి లేదా ఇక్కడ నుండి ట్రాన్స్‍క్లూడు అవుతున్నాయి.",
 
 # Rollback
 'rollback' => 'దిద్దుబాట్లను రద్దుచేయి',
@@ -2563,7 +2563,7 @@ $1',
 'ipbenableautoblock' => 'ఈ వాడుకరి వాడిన చివరి ఐపీ అడ్రసును, అలాగే ఆ తరువాత వాడే అడ్రసులను కూడా ఆటోమాటిగ్గా నిరోధించు',
 'ipbsubmit' => 'ఈ సభ్యుని నిరోధించు',
 'ipbother' => 'వేరే గడువు',
-'ipboptions' => '2 గంటలు:2 hours,1 రోజు:1 day,3 రోజులు:3 days,1 వారం:1 week,2 వారాలు:2 weeks,1 నెల:1 month,3 నెలలు:3 months,6 నెలలు:6 months,1 సంవత్సరం:1 year,ఎప్పటికీ:infinite',
+'ipboptions' => '2 గంటలు:2 hours,ఒక రోజు:1 day,3 రోజులు:3 days,ఒక వారం:1 week,2 వారాలు:2 weeks,ఒక నెల:1 month,3 నెలలు:3 months,6 నెలలు:6 months,ఒక సంవత్సరం:1 year,ఎప్పటికీ:infinite',
 'ipbhidename' => 'మార్పులు మరియు జాబితాల నుండి ఈ వాడుకరిపేరుని దాచు',
 'ipbwatchuser' => 'ఈ సభ్యుని సభ్యుని పేజీ, చర్చాపేజీలను వీక్షణలో ఉంచు',
 'ipb-disableusertalk' => 'నిరోధంలో ఉండగా ఈ వాడుకరి తన స్వంత చర్చ పేజీలో మార్పుచేర్పులు చెయ్యకుండా నిరోధించు',
@@ -2624,7 +2624,7 @@ $1 ను నిరోధించడానికి కారణం: "$2"',
 మీ సమాచారం కోసం నిరోధపు చిట్టాని క్రింద ఇచ్చాం:',
 'blocklog-showsuppresslog' => 'ఈ వాడుకరిని గతంలో నిరోధించి, దాచి ఉంచారు.
 వివరాల కోసం అణచివేత చిట్టా కింద చూపబడింది:',
-'blocklogentry' => '"[[$1]]" పై నిరోధం అమలయింది. నిరోధ కాలం $2 $3',
+'blocklogentry' => '"[[$1]]" పై నిరోధం అమలయింది. నిరోధ కాలం $2. $3',
 'reblock-logentry' => '[[$1]] కై నిరోధపు అమరికలను $2 $3 గడువుతో మార్చారు',
 'blocklogtext' => 'వాడుకరుల నిరోధాలు, పునస్థాపనల చిట్టా ఇది. 
 ఆటోమాటిక్‌గా నిరోధానికి గురైన ఐ.పి. చిరునామాలు ఈ జాబితాలో ఉండవు. 
@@ -2948,7 +2948,7 @@ $2',
 'tooltip-preview' => 'మీ మార్పులను మునుజూడండి, భద్రపరిచేముందు ఇది వాడండి!',
 'tooltip-diff' => 'పాఠానికి మీరు ఏ మార్పులు చేసారో చూపిస్తుంది',
 'tooltip-compareselectedversions' => 'ఈ పేజీలో ఎంచుకున్న రెండు కూర్పులకు మధ్య తేడాలను చూడండి',
-'tooltip-watch' => 'à°\88 à°ªà±\87à°\9cà±\80ని à°®à±\80 à°µà°¿à°\95à±\8dషణా జాబితాకు చేర్చండి',
+'tooltip-watch' => 'à°\88 à°ªà±\87à°\9cà±\80ని à°®à±\80 à°µà±\80à°\95à±\8dà°·à°£ జాబితాకు చేర్చండి',
 'tooltip-watchlistedit-normal-submit' => 'శీర్షికలను తీసివెయ్యి',
 'tooltip-watchlistedit-raw-submit' => 'వీక్షణ జాబితాను తాజాకరించు',
 'tooltip-recreate' => 'పేజీ తుడిచివేయబడ్డాకానీ మళ్ళీ సృష్టించు',
index 70773de..0b4c1a4 100644 (file)
@@ -757,9 +757,6 @@ $1',
 'revdelete-nooldid-text' => 'Шумо ин ё он нусхаи(ҳои) мақсадро барои иҷрои ин амал мушаххас накардаед, нусхаи мушаххасшуда вуҷуд надорад, ё  шумо дар ҳоли кӯшиши пинҳон кардани нусхаи кунуниаш ҳастед.',
 'revdelete-selected' => "'''{{PLURAL:$2|Нусхаи интихобшуда|Нусхаҳои интихобшуда}} аз [[:$1]]:'''",
 'logdelete-selected' => "'''{{PLURAL:$1|Гузориши маврид интихобшуда|Гузориши мавориди интихобшуда}}:'''",
-'revdelete-text' => "'''Нусхаҳои ва мавориди ҳазфшуда камокам дар таърих ва гузоришҳои саҳифа қобили мушоҳида ҳастанд, аммо бахшҳои аз мӯҳтавои он ба умум қобили мушоҳида нахоҳанд буд.'''
-
-Дигар мудирон дар {{SITENAME}} ҳанӯз метавонанд ба ин мӯҳтавои пинҳонро дастрасӣ кунанд ва ҳатто мавориди ҳазфшударо эҳё кунанд, магар он ки маҳдудиятҳои дигаре амалӣ гардад.",
 'revdelete-legend' => 'Танзими маҳдудиятҳои падидорӣ',
 'revdelete-hide-text' => 'Пинҳон кардани нусхаи матн',
 'revdelete-hide-image' => 'Пинҳон кардани мӯҳтавиёти парванда',
index 41f498e..f75d5b8 100644 (file)
@@ -1127,8 +1127,6 @@ $2
 'revdelete-show-file-submit' => 'ใช่',
 'revdelete-selected' => "'''{{PLURAL:$2|รุ่นการปรับปรุงที่ถูกเลือก|รุ่นการปรับปรุงที่ถูกเลือก}}ของ [[:$1]] :'''",
 'logdelete-selected' => "'''{{PLURAL:$1|เหตุการณ์ปูมที่เลือก|เหตุการณ์ปูมที่เลือก}} :'''",
-'revdelete-text' => "'''รุ่นการปรับปรุงและเหตุการณ์ที่ถูกลบยังปรากฏในประวัติและปูมของหน้า แต่สาธารณะไม่สามารถเข้าถึงเนื้อหาบางส่วนได้'''
-ผู้ดูแลระบบคนอื่นบน {{SITENAME}} ยังสามารถเข้าถึงเนื้อหาที่ถูกซ่อน และสามารถกู้คืนอีกครั้งในลักษณะเดิมเช่นนี้ เว้นแต่จะมีการกำหนดการจำกัดเพิ่มเติม",
 'revdelete-confirm' => 'กรุณายืนยันว่าคุณมีเจตนาลบจริง และเข้าใจผลลัพธ์ และกระทำภายใต้[[{{MediaWiki:Policy-url}}|นโยบาย]]',
 'revdelete-suppress-text' => "การระงับควรใช้'''เฉพาะ'''กรณีต่อไปนี้:
 * ข้อมูลที่อาจหมิ่นประมาท
index d626133..67b3ed4 100644 (file)
@@ -820,8 +820,6 @@ Administrator hökmünde bu aratapawudy görüp bilersiňiz; [{{fullurl:{{#Speci
 'revdelete-show-file-submit' => 'Hawa',
 'revdelete-selected' => "'''[[:$1]] sahypasynyň {{PLURAL:$2|saýlanylan wersiýasy|saýlanylan wersiýalary}}:'''",
 'logdelete-selected' => "'''{{PLURAL:$1|Saýlanylan gündelik wakasy|Saýlanylan gündelik wakalary}}:'''",
-'revdelete-text' => "'''Öçürilen wersiýalar we wakalar sahypa geçmişlerinde we gündeliklerde ýene-de görkeziljekdir, emma olaryň mazmunynyň käbir bölekleri jemgyýetçilige açyk boljak däldir.'''
-{{SITENAME}} saýtyndaky başga administratorlar gizlin mazmuny ýene-de görüp hem-de goşmaça çäklendirme goýulmadyk ýagdaýynda şol bir interfeýsiň üsti bilen ony yzyna dikeldip bilýärler.",
 'revdelete-confirm' => 'Şu işi anyk isleýändigiňizi, ýagny onuň netijelerine düşünýändiňizi we [[{{MediaWiki:Policy-url}}|kadalar boýunça]] amala aşyrýandygyňyzy tassyklamagyňyzy haýyş edýäris.',
 'revdelete-suppress-text' => "Gizlemeklik '''diňe''' aşakdaky ýagdaýlarda ulanylmalydyr:
 * Potensial taýdan töhmetçilikli maglumat
index 356993e..710b60e 100644 (file)
@@ -1073,8 +1073,6 @@ Makikita mo ang pagkakaibang ito; matatagpuan ang mga detalye sa [{{fullurl:{{#S
 'revdelete-show-file-submit' => 'Oo',
 'revdelete-selected' => "{{PLURAL:$2|Piniling|Mga piniling}} pagbabago ng '''$1:'''",
 'logdelete-selected' => '{{PLURAL:$1|Piniling tala ng pangyayari|Piniling tala ng mga pangyayari}}:',
-'revdelete-text' => "'''Makikita pa rin ang mga binurang pagbabago at mga kaganapan sa pahina ng kasaysayan at mga talaan, ngunit hindi mapupuntahan ng madla ang mga bahagi ng kanilang nilalaman.
-Makikita pa rin ng iba pang mga tagapangasiwang nasa {{SITENAME}} ang mga tinagong nilalaman at maaaring ibalik ito mula sa pagkakabura sa pamamagitan ng kaparehong ugnayang-hangganan, maliban na lamang kung may itinakdang karagdagang mga restriksyon.",
 'revdelete-confirm' => 'Pakitiyak po na nais mo itong gawin, na nauunawaan mo ang mga kahihinatnan, at na ginagawa mo ito alinsunod sa [[{{MediaWiki:Policy-url}}|patakaran]].',
 'revdelete-suppress-text' => "Ang paglilingid ay dapat na gamitin '''lamang''' para sa sumusunod na mga pagkakataon:
 * Hindi naaangkop na kabatirang pansarili
index 0214a8a..d416678 100644 (file)
@@ -1307,8 +1307,6 @@ Bir hizmetli olarak bu değişikliği görebilirsiniz; [{{fullurl:{{#Special:Log
 'revdelete-show-file-submit' => 'Evet',
 'revdelete-selected' => "'''[[:$1]] sayfasının {{PLURAL:$2|seçili değişikliği|seçili değişiklikleri}}:'''",
 'logdelete-selected' => "'''{{PLURAL:$1|Seçili kayıt olayı|Seçili kayıt olayları}}:'''",
-'revdelete-text' => "'''Silinen revizyonlar ve olaylar hala sayfa geçmişinde ve günlüklerde görünecektir, fakat içeriğin parçaları umumi olarak erişilemeyecektir.'''
-{{SITENAME}} sitesindeki diğer hizmetliler gizli içeriğe erişebilir ve ilave kısıtlamalar ayarlanmadıysa bu arayüz ile geri getirebilir.",
 'revdelete-confirm' => 'Lütfen, bunu yapmak istediğinizi , sonuçlarını anladığınızı, ve bunu [[{{MediaWiki:Policy-url}}|ilkelere]] göre yapıyor olduğunuzu onaylayın.',
 'revdelete-suppress-text' => "Saklama '''sadece''' aşağıdaki durumlarda kullanılmalıdır:
 * Muhtemel iftira niteliğindeki bilgi
index dd664f6..7fa59dd 100644 (file)
@@ -633,8 +633,8 @@ $2',
 'userlogin-noaccount' => 'Аккаунт юкмы?',
 'userlogin-joinproject' => 'Проектка керү',
 'nologin' => "Кулланучы исемең юкмы? '''$1'''",
-'nologinlink' => 'Хисап язмасы төзегез',
-'createaccount' => 'Яңа кулланучы теркәү',
+'nologinlink' => 'Хисап язмасы төзү',
+'createaccount' => 'Яңа кулланучыны теркәү',
 'gotaccount' => "Сез инде теркәлдегезме? '''$1'''.",
 'gotaccountlink' => 'Керү',
 'userlogin-resetlink' => 'Серсүзегезне оныттыгызмы?',
@@ -696,6 +696,7 @@ $2',
 'loginlanguagelabel' => 'Тел: $1',
 'suspicious-userlogout' => 'Сезнең эшчәнлекне бетерү соравыгыз кире кагылды, чөнки ул ялгыш браузер яисә кэшлаучы прокси аша җибәрелергэ мөмкин.',
 'pt-login' => 'Керү',
+'pt-createaccount' => 'Яңа кулланучыны теркәү',
 'pt-userlogout' => 'Чыгу',
 
 # Email sending
@@ -1341,7 +1342,7 @@ $1",
 'recentchanges-legend' => 'Соңгы үзгәртүләр көйләүләре',
 'recentchanges-summary' => 'Бу биттә {{grammar:genitive|{{SITENAME}}}} проектының соңгы үзгәртүләре күрсәтелә.',
 'recentchanges-feed-description' => 'Бу агымда соңгы үзгәртүләрне күзәтү.',
-'recentchanges-label-newpage' => 'Ð\91Ñ\83 Ò¯Ð·Ð³Ó\99Ñ\80Ñ\82Ò¯ Ð±ÐµÐ»Ó\99н Ñ\8fңа Ð±Ð¸Ñ\82 Ñ\82өзелде',
+'recentchanges-label-newpage' => 'Ð\91Ñ\83 Ò¯Ð·Ð³Ó\99Ñ\80Ñ\82Ò¯ Ð±ÐµÐ»Ó\99н Ñ\8fңа Ð±Ð¸Ñ\82 Ñ\82өзелгÓ\99н',
 'recentchanges-label-minor' => 'Бу кече үзгәртү',
 'recentchanges-label-bot' => 'Бу үзгәртү бот белән эшләнгән',
 'recentchanges-label-unpatrolled' => 'Үзгәртүне әлегә тикшермәгәннәр',
@@ -1350,22 +1351,22 @@ $1",
 'rcnotefrom' => "Астарак '''$2''' башлап ('''$1''' кадәр) үзгәртүләр күрсәтелгән.",
 'rclistfrom' => '$1 башлап яңа үзгәртүләрне күрсәт',
 'rcshowhideminor' => 'кече үзгәртүләрне $1',
-'rcshowhideminor-show' => 'Ð\9aÒ¯Ñ\80Ñ\81Ó\99Ñ\82еÑ\80гÓ\99',
-'rcshowhideminor-hide' => 'Яшерергә',
+'rcshowhideminor-show' => 'күÑ\80Ñ\81Ó\99Ñ\82',
+'rcshowhideminor-hide' => 'яшер',
 'rcshowhidebots' => 'ботларны $1',
-'rcshowhidebots-show' => 'Ð\9aÒ¯Ñ\80Ñ\81Ó\99Ñ\82еÑ\80гÓ\99',
-'rcshowhidebots-hide' => 'Яшерергә',
-'rcshowhideliu' => '$1 теркәлгән кулланучыларны яшерергә',
-'rcshowhideliu-show' => 'Ð\9aÒ¯Ñ\80Ñ\81Ó\99Ñ\82еÑ\80гÓ\99',
-'rcshowhideliu-hide' => 'Яшерергә',
+'rcshowhidebots-show' => 'күÑ\80Ñ\81Ó\99Ñ\82',
+'rcshowhidebots-hide' => 'яшер',
+'rcshowhideliu' => 'Теркәлгән кулланучыларны $1',
+'rcshowhideliu-show' => 'күÑ\80Ñ\81Ó\99Ñ\82',
+'rcshowhideliu-hide' => 'яшер',
 'rcshowhideanons' => 'кермәгән кулланучыларны $1',
-'rcshowhideanons-show' => 'Ð\9aÒ¯Ñ\80Ñ\81Ó\99Ñ\82еÑ\80гÓ\99',
-'rcshowhideanons-hide' => 'Яшерергә',
+'rcshowhideanons-show' => 'күÑ\80Ñ\81Ó\99Ñ\82',
+'rcshowhideanons-hide' => 'яшер',
 'rcshowhidepatr' => 'тикшерелгән үзгәртүләрне $1',
-'rcshowhidepatr-hide' => 'Яшерергә',
+'rcshowhidepatr-hide' => 'яшер',
 'rcshowhidemine' => 'минем үзгәртүләремне $1',
-'rcshowhidemine-show' => 'Ð\9aÒ¯Ñ\80Ñ\81Ó\99Ñ\82еÑ\80гÓ\99',
-'rcshowhidemine-hide' => 'Яшерергә',
+'rcshowhidemine-show' => 'күÑ\80Ñ\81Ó\99Ñ\82',
+'rcshowhidemine-hide' => 'яшер',
 'rclinks' => 'Соңгы $2 көн эчендә соңгы $1 үзгәртүне күрсәт<br />$3',
 'diff' => 'аерма',
 'hist' => 'тарих',
index 2cff208..85fd619 100644 (file)
@@ -1048,8 +1048,6 @@ $3 تەمىنلىگەن چەكلەش سەۋەبى ''$2''",
 'revdelete-show-file-submit' => 'ھەئە',
 'revdelete-selected' => "'''[[:$1]] نىڭ {{PLURAL:$2|تاللانغان تۈزىتىش نەشرى|تاللانغان تۈزىتىش نەشرى}}:'''",
 'logdelete-selected' => "'''{{PLURAL:$1|تاللانغان خاتىرە تۈرى|تاللانغان خاتىرە تۈرى}}:'''",
-'revdelete-text' => "'''ئۆچۈرۈلگەن تۈزىتىلگەن نەشرى ۋە ھادىسە بەت تارىخىدا كۆرۈنىدۇ ئەمما ئۇنىڭ مەزمۇنىنى كۆپچىلىك زىيارەت قىلالمايدۇ.'''
-{{SITENAME}}  دىكى باشقا باشقۇرغۇچىلار يوشۇرۇلغان مەزمۇننى يەنىلا كۆرەلەيدۇ ھەمدە بېكەت خىزمەتچىلىرى قوشۇمچە چەكلىمە ئېلىپ بارمىغانلا بولسا ئوخشاش ئارايۈزدە ئۆچۈرۈلگەننى ئەسلىگە كەلتۈرەلەيدۇ،",
 'revdelete-confirm' => 'بۇ مەشغۇلاتنى ئىجرا قىلسىڭىز ئاقىۋىتىنى چۈشىنىدىغانلىقىڭىزنى ھەمدە بۇ پروگراممىنىڭ [[{{MediaWiki:Policy-url}}|سىياسەت]]كە ئۇيغۇن كېلىدىغانلىقىنى جەزملەڭ.',
 'revdelete-suppress-text' => "'''پەقەت''' تۆۋەندىكى ئەھۋاللار يۈز بەرگەندىلا زىيارەت چەكلىنىدۇ:
 * نامۇۋاپىق شەخسىي ئۇچۇر
index f639c31..30beb36 100644 (file)
@@ -915,6 +915,7 @@ $1',
 'createacct-another-realname-tip' => "Справжнє ім'я є необов'язковим.
 Якщо ви вирішите надати його, то воно буде використовуватися для присвоєння користувачу авторства до його роботи.",
 'pt-login' => 'Увійти',
+'pt-login-button' => 'Вхід',
 'pt-createaccount' => 'Створити обліковий запис',
 'pt-userlogout' => 'Вийти',
 
@@ -1340,9 +1341,6 @@ $3 зазначив таку причину: ''$2''",
 'revdelete-show-file-submit' => 'Так',
 'revdelete-selected' => "'''{{PLURAL:$2|1=Обрана версія|Обрані версії}} сторінки [[:$1]]:'''",
 'logdelete-selected' => "'''{{PLURAL:$1|1=Обраний запис|Обрані записи}} журналу:'''",
-'revdelete-text' => "'''Вилучені версії сторінок і подій будуть відображатися в історії сторінки та журналах, але частина їх вмісту не буде доступною звичайним користувачам.'''
-Доступ до прихованого змісту матимуть адміністратори проекту {{SITENAME}}, які зможуть відновити його за допомогою цього ж інтерфейсу,
-крім випадків, коли були встановлені додаткові обмеження власниками сайту.",
 'revdelete-confirm' => 'Будь ласка, підтвердить, що ви справді бажаєте це здійснити, усвідомлюєте наслідки та робите це згідно з [[{{MediaWiki:Policy-url}}|правилами]].',
 'revdelete-suppress-text' => "Приховування може відбуватися '''лише''' в таких випадках:
 * Потенційно наклепницькі відомості
@@ -1478,7 +1476,7 @@ $1",
 'search-file-match' => '(збігається із вмістом файлу)',
 'search-suggest' => 'Можливо, ви мали на увазі: $1',
 'search-interwiki-caption' => 'Братні проекти',
-'search-interwiki-default' => '$1 результати:',
+'search-interwiki-default' => 'Результати із $1:',
 'search-interwiki-more' => '(більше)',
 'search-relatedarticle' => "Пов'язаний",
 'searcheverything-enable' => 'Пошук у всіх просторах назв',
@@ -2625,7 +2623,7 @@ $UNWATCHURL
 'delete-warning-toobig' => 'У цієї сторінки дуже довга історія редагувань, більше $1 {{PLURAL:$1|версії|версій|версій}}.
 Її вилучення може призвести до порушень у роботі бази даних сайту {{SITENAME}};
 дійте обережно.',
-'deleting-backlinks-warning' => "'''Попередження:''' інші сторінки посилаються або містять сторінку, яку ви маєте намір видалити.",
+'deleting-backlinks-warning' => "'''Попередження:'''  [[Special:WhatLinksHere/{{FULLPAGENAME}}|інші сторінки]] посилаються або містять сторінку, яку ви маєте намір видалити.",
 
 # Rollback
 'rollback' => 'Відкинути редагування',
index 4861e7c..91a4e63 100644 (file)
@@ -985,7 +985,7 @@ Agar keltirsangiz, undan sahifa kim tomonidan tahrirlanganini koʻrsatish uchun
 'recentchanges-label-minor' => 'Bu tahrir kichik deb belgilangan',
 'recentchanges-label-bot' => 'Bu tahrirni bot bajargan',
 'recentchanges-label-unpatrolled' => 'Bu tahrir hali tekshirilmagan',
-'recentchanges-label-plusminus' => 'vazni qanchaga oʻzgargani (bayt)',
+'recentchanges-label-plusminus' => 'Sahifa vazni qanchaga oʻzgargani (bayt)',
 'recentchanges-legend-heading' => "'''Izoh:'''",
 'recentchanges-legend-newpage' => '([[Special:NewPages|alohida roʻyxat]])',
 'rcnotefrom' => 'Quyida <strong>$2</strong>dan boshlab boʻlgan oʻzgarishlar keltirilgan (<strong>$1</strong>dan koʻp boʻlmaganlari koʻrsatildi).',
@@ -1157,13 +1157,13 @@ Uning [$2 fayl tavsifi sahifasidan] olingan tavsifi quyida keltirilgan.',
 
 # Special:Log
 'specialloguserlabel' => 'Ijrochi:',
-'speciallogtitlelabel' => 'Moʻljal (foydalanuvchi yoki sahifa nomi):',
+'speciallogtitlelabel' => 'Moʻljal:',
 'log' => 'Qaydlar',
 'all-logs-page' => 'Barcha ochiq qaydlar',
-'alllogstext' => "{{SITENAME}}dagi barcha jurnallar roʻyxati.
+'alllogstext' => '{{SITENAME}}dagi barcha jurnallar roʻyxati.
 Natijalarni jurnal nomi, foydalanuvchi nomi (harflar katta-kichikligi inobatga olinadi) yoki sahifa nomi boʻyicha saralashingiz mumkin.
-* Biror foydalanuvchi ''amalga oshirgan qaydni'', uning foydalanuvchi nomini \"Ijrochi\" oynasiga kiritib qidirish mumkin.
-* Biror foydalanuvchi yoki sahifaga ''nisbatan'' amalga oshirilgan qaydni, ularning nomini \"Moʻljal\" oynasiga kiritib qidirish mumkin.",
+* Biror foydalanuvchi amalga oshirgan qaydni topish uchun uning foydalanuvchi nomini „Ijrochi“ oynasiga kiriting.
+* Biror foydalanuvchi yoki sahifaga nisbatan amalga oshirilgan qaydni topish uchun ulardan birining nomini „Moʻljal“ oynasiga kiriting.',
 'logempty' => 'Talabga mos yozuvlar mavjud emas.',
 'log-title-wildcard' => 'Shu matndan boshlanuvchi sarlavhalarni izlash',
 
index b6dd205..13a1ac9 100644 (file)
@@ -1056,8 +1056,6 @@ Te połi uncora vixuałixare sto confronto; controłare el [{{fullurl:{{#Special
 'revdelete-show-file-submit' => 'Sì',
 'revdelete-selected' => "'''{{PLURAL:$2|Version selezionà|Versioni selezionà}} de [[:$1]]:'''",
 'logdelete-selected' => "'''{{PLURAL:$1|Evento del registro selezionà|Eventi del registro selezionè}}:'''",
-'revdelete-text' => "'''Le revision e le azion scancelàe le restarà visibili ne la cronologia de la pagina, ma parte del testo contegnùo no'l sarà visìbile al publico.'''
-I altri aministradori de {{SITENAME}} i podarà vardar istesso i contenuti sconti e ripristinarli atraverso questa stessa interfacia, se no xe stà inpostà altre limitazion.",
 'revdelete-confirm' => 'Par piaser, conferma che vol far sta azion, che te capissi le so conseguense, e che te sì drio operar secondo le [[{{MediaWiki:Policy-url}}|linee guida]].',
 'revdelete-suppress-text' => "La sopression la se dovarìa doparar '''solo''' in sti casi qua:
 
index a5a3236..1d2cd7a 100644 (file)
@@ -866,8 +866,6 @@ Detalid voidas olda [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}}
 'revdelete-show-file-submit' => 'Ka',
 'revdelete-selected' => "'''{{PLURAL:$2|Valitud versii|Valitud versijad}} lehtpolišpäi [[:$1]]:'''",
 'logdelete-selected' => "'''{{PLURAL:$1|Valitud kirjutez aigkirjas|Valitud kirjutesed aigkirjas}}:'''",
-'revdelete-text' => "'''Čutud versijad ozutadas lehtpolen istorijas da aigkirjoiš, no järgeližed lugijad ei voiškakoi nähta niiden südäimišton erasid paloid.'''
-Administratorad voiškatas lugeda peittud südäimištod da endištada sidä necen interfeisan kal't siloi, konz ei ole ližakaidendusid.",
 'revdelete-legend' => 'Säta kaidendused',
 'revdelete-hide-text' => 'Redakcijan tekst',
 'revdelete-hide-image' => 'Peitta failan südäiolend',
index 6bc0430..faa6f8f 100644 (file)
@@ -1283,8 +1283,6 @@ hoặc bạn đang tìm cách ẩn phiên bản hiện tại.',
 'revdelete-show-file-submit' => 'Có',
 'revdelete-selected' => "'''{{PLURAL:$2|Phiên bản|Các phiên bản}} được chọn của [[:$1]]:'''",
 'logdelete-selected' => "'''{{PLURAL:$1|Nhật trình đã chọn|Các nhật trình đã chọn}}:'''",
-'revdelete-text' => "'''Các phiên bản và sự kiện bị xóa sẽ vẫn xuất hiện trong lịch sử trang và nhật trình, nhưng mọi người sẽ không xem được một số phần của các nội dung đó.'''
-Các quản lý khác ở {{SITENAME}} vẫn có thể truy nhập vào nội dung ẩn và phục hồi lại bằng cách dùng giao diện này, trừ trường hợp thiết lập thêm một số hạn chế.",
 'revdelete-confirm' => 'Xin hãy xác nhận rằng bạn có ý định xóa, nhận biết tầm quan trọng của việc này, và việc xóa tuân theo [[{{MediaWiki:Policy-url}}|quy định]].',
 'revdelete-suppress-text' => "Việc ẩn giấu '''chỉ''' nên dùng trong các trường hợp sau:
 * Thông tin có thể phỉ báng
index 1b16414..65c3f86 100644 (file)
@@ -860,8 +860,6 @@ Kanol logön oni; pats ba binons in [{{fullurl:{{#Special:Log}}/delete|page={{FU
 'revdelete-show-file-submit' => 'Si',
 'revdelete-selected' => "'''{{PLURAL:$2|Fomam|Fomams}} pevalöl pada: [[:$1]]:'''",
 'logdelete-selected' => "'''{{PLURAL:$1|Lisedajenot|Lisedajenots}} pevälöl:'''",
-'revdelete-text' => "'''Revids pemoüköl nog opubons in padajenotem, ab ninäd (vödem) onsik no gebidons publüge.'''
-Ninäd peklänedöl at binon ye nog lügolovik guvanes votik vüka: {{SITENAME}}, kels kanons nog votükön ninädi peklänedöl u geükön padi medü fometem at (üf miedöfükams u neletians votik no lonöfons).",
 'revdelete-legend' => 'Levälön miedükamis logova:',
 'revdelete-hide-text' => 'Klänedön vödemi revida',
 'revdelete-hide-image' => 'Klänedön ragivaninädi',
index e69d6a2..edd5295 100644 (file)
@@ -741,7 +741,6 @@ Lisateedüst või ollaq [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAME
 'revdelete-nooldid-text' => 'Sa olõ-i valinuq kujjo vai kujjõ.',
 'revdelete-selected' => "'''{{PLURAL:$2|Valit kujo|Validuq kujoq}} lehele [[:$1]]'''",
 'logdelete-selected' => "'''{{PLURAL:$1|Valit muutminõ|Validuq muutmisõq}}:'''",
-'revdelete-text' => "'''Kistudõduq kujoq ommaq olõman lehe aoluun, a näide sissu saa-i avaligult nätäq.''' Seo viki tõõsõq kõrraldajaq saavaq taad käkitüt teksti lukõq ja taa tagasi avaligult nättäväs tetäq, ku olõ-i säet muid piirdmiisi.",
 'revdelete-legend' => 'Nättävüse piirdmiseq',
 'revdelete-hide-text' => 'Käkiq kujo sisu',
 'revdelete-hide-image' => 'Käkiq teedüstü sissu',
index 143db5e..d5b55c4 100644 (file)
@@ -744,9 +744,6 @@ Vos l' poloz co vey; i gn a des detays sol [{{fullurl:{{#Special:Log}}/suppress|
 'revdelete-show-file-submit' => 'Oyi',
 'revdelete-selected' => "'''{{PLURAL:$2|Tchoezeye modêye|Tchoezeyès modêyes}} di [[:$1]]:'''",
 'logdelete-selected' => "'''{{PLURAL:$1|Evenmint tchoezi|Evenmints tchoezis}} ezès djournås:'''",
-'revdelete-text' => "'''Les disfacés avenmints et modêyes vont continouwer d' aparexhe dins l' pådje di l' istwere, mins leu contnou n' serè nén veyåve do publik.'''
-
-Les ôtes manaedjeus so {{SITENAME}} pôront todi vey li contnou catchî eyet l' rapexhî åd triviè di cisse minme eterface ci, a moens k' ene restriccion di pus ni soeye metowe en alaedje pås mwaisses-manaedjeus del waibe.",
 'revdelete-legend' => 'Defini des restriccions sol voeyaedje',
 'revdelete-hide-text' => "Catchî l' tecse del modêye",
 'revdelete-hide-comment' => "Catchî l' comintaire di candjmint",
index f1bdc20..36187cc 100644 (file)
@@ -757,8 +757,6 @@ Li nga doon yorkat tax na ba-tay nga man a [$1 gis gii wuute] su la neexee.",
 'revdelete-show-file-submit' => 'Waaw',
 'revdelete-selected' => "'''{{PLURAL:$2|Sumbum '''$1''' mi falu|Sumbi '''$1''' yi falu}} :'''",
 'logdelete-selected' => "'''{{PLURAL:$1|Xew-xewu yéenekaay bi falu|Xew-xewi yéenekaay yi falu}}:'''",
-'revdelete-text' => "'''Sumb yi nga far dañuy wéy di feeñ ci jaar-jaaru xët wi, waaye mbind yi ñu ëmb ñépp duñ leen man a gis.'''
-Yeneen yorkat yu {{SITENAME}} di nañ man a gis ëmbit yu laqu yi te loppanti leen ci benn jokkalekaay bi, su fekkee defuñu fi ay digal yu leen koy tere man a def.",
 'revdelete-legend' => 'Taxawal ay digal ci sumb yi ñu far:',
 'revdelete-hide-text' => 'Nëbb mbindum sumb bi',
 'revdelete-hide-image' => 'Nëbb ëmbiitu dencukaay bi',
index 37f6029..e5b514b 100644 (file)
@@ -826,8 +826,6 @@ $3封禁个原因是''$2''",
 'revdelete-show-file-submit' => '是',
 'revdelete-selected' => "'''选取'''[[:$1]]'''个$2趟修订:'''",
 'logdelete-selected' => "'''选取'''$1'''个日志事件:'''",
-'revdelete-text' => "'''删脱个修订仍然将显示拉页面历史里向,不过渠拉个文本内容公众已经弗好访问。'''
-垃拉{{SITENAME}}个其他管理员将仍旧好访问隐藏个内容并通过与此相同个界面恢复删除,除非站点工作者添加了附加限制。",
 'revdelete-confirm' => '假使侬想箇能介做个闲话,请确认侬已经清爽箇能介做个后果,外加箇个程序符合[[{{MediaWiki:Policy-url}}|政策]]。',
 'revdelete-suppress-text' => "'''只有'''出现下头眼情况再应阻止访问:
 * 弗适合个个人信息
index 1068623..0ca8696 100644 (file)
@@ -748,6 +748,7 @@ $2',
 'createacct-another-realname-tip' => 'עכטער נאמען איז אפציאנאל.
 אויב איר וויילט אויס צוצושטעלן אים, וועט דאס גענוצט ווערן צו געבן אטריבוציע פאר זייער ארבעט.',
 'pt-login' => 'אַרײַנלאגירן',
+'pt-login-button' => 'אַרײַנלאָגירן',
 'pt-createaccount' => 'שאַפֿן אַ קאנטע',
 'pt-userlogout' => 'אַרויסלאגירן',
 
@@ -1166,8 +1167,6 @@ $2
 'revdelete-show-file-submit' => 'יא',
 'revdelete-selected' => "'''{{PLURAL:$2|אויסדערוויילטע ווערסיע| אויסדערוויילטע ווערסיעס}} פון [[:$1]]:'''",
 'logdelete-selected' => "'''{{PLURAL:$1| אויסדערוויילטע לאג אקציע|אויסדערוויילטע לאג אקציעס}}:'''",
-'revdelete-text' => "'''אויסגעמעקטע רעוויזיעס און געשעענישן וועלן בלייבן אין דער בלאט היסטאריע און די לאגביכער, אבער טיילן פון זייער אינהאלט וועט ווערן אומגרייכלעך צום קהל. '''
-אנדערע סיסאפן אויף {{SITENAME}} וועלן נאך האבן צוטריט צום באהאלטענעם אינהאלט און קענען אים צוריקשטעלן דורך דעם זעלבן אייבערפלאך,  אחוץ ווען מען שטעלט נאך באגרענעצונגען.",
 'revdelete-confirm' => 'זייט אזוי גוט און באשטעטיקט אז דאס איז טאקע אייער כוונה, אז איר פארשטייט די קאנסעקווענצן, און אז איר טוט דאס לויט  [[{{MediaWiki:Policy-url}}|דער פאליסי]].',
 'revdelete-suppress-text' => "אונטערדרוקן זאל בלויז גענוצט ווערן '''נאר''' אין די פאלגנדע פעלער:
 * אינפארמאציע וואס קען זיין מוציא שם רע
@@ -1303,7 +1302,7 @@ $1",
 'search-file-match' => '(פאסט צו טעקע אינהאלט)',
 'search-suggest' => 'צי האט איר געמיינט: $1',
 'search-interwiki-caption' => 'שוועסטער פראיעקטן',
-'search-interwiki-default' => '$1 רעזולטאטן:',
+'search-interwiki-default' => 'רעזולטאטן פון $1:',
 'search-interwiki-more' => '(נאך)',
 'search-relatedarticle' => 'פארבינדן',
 'searcheverything-enable' => 'זוכן אין אלע נאמענטיילן',
index 64fd383..ce49390 100644 (file)
@@ -987,8 +987,6 @@ Tó bá jẹ́ pé ẹ ti wọlé, ẹ lè dẹ́kun ìkìlọ̀ yìí nínù ab
 'revdelete-show-file-submit' => 'Bẹ́ẹ̀ni',
 'revdelete-selected' => "'''{{PLURAL:$2|Àtúnyẹ̀wò síṣàyàn|Àwọn àtúnyẹ̀wò síṣàyàn}} fún [[:$1]]:'''",
 'logdelete-selected' => "'''{{PLURAL:$1|Àkọọ́lẹ̀ ìṣẹ̀lẹ̀ síṣàyàn|Àwọn àkọọ́lẹ̀ ìṣẹ̀lẹ̀ síṣàyàn}}:'''",
-'revdelete-text' => "'''Àwọn àtúnyẹ̀wò onípíparẹ́ àti ìṣẹ̀lẹ̀ yíò sì tún hàn nínú ojúewé ìtàn àti àkọọ́lẹ̀, sùgbọ́n àwọn apá àkóónú wọn kò ní hàn jáde sí ìgboro'''
-Àwọn olùmójútó míràn lórí {{SITENAME}} yíò sí tún le wo àkóónú àbòmọ́lẹ̀ náà bẹ́ẹ̀sìni wọ́n le mú ìparẹ́ kúrò lórí ìfojúkojú yìí, àyàfi tí àwọn ìdíwọ́ míràn bá jẹ́ títòsílẹ̀.",
 'revdelete-confirm' => 'Ẹ jọ̀wọ́ ẹ rídájú pé ohun tí ẹ fẹ́ ṣe nìyí, pé ohun tí yíò ṣẹlẹ̀ yé yín, bẹ́ẹ̀sìni pé ẹ̀ únṣe é lọ́nà tó bá  [[{{MediaWiki:Policy-url}}|àdéhùn]] mu.',
 'revdelete-suppress-text' => "Ìrẹ̀mọ́lẹ̀ gbọ́dọ̀ jẹ́ lílò fún àwọn ìṣẹ̀lẹ̀ ìsàlẹ̀ wọ̀nyí '''nìkan''':
 *Ọ̀rọ̀ tó le fa ẹjọ́ wá
index dac35e8..6911b16 100644 (file)
@@ -1015,8 +1015,6 @@ $1',
 'revdelete-show-file-submit' => '係',
 'revdelete-selected' => "'''揀[[:$1]]嘅$2次修訂:'''",
 'logdelete-selected' => "'''揀[[:$1]]嘅日誌事件:'''",
-'revdelete-text' => "'''刪除咗嘅修訂係會仍然出現喺個頁面歷史以及日誌度,但係佢哋嘅文字內容係唔可以供公眾瀏覽。'''
-其他喺{{SITENAME}}嘅管理員仍然可以睇已經隱藏咗嘅內容,同埋可以透過同一個介面去反刪除佢,除非已經設定咗附加嘅限制。",
 'revdelete-confirm' => '請確認你肯定去做嘅話,你就要明白到後果,同埋呢個程序符合[[{{MediaWiki:Policy-url}}|政策]]。',
 'revdelete-suppress-text' => "壓制'''只'''應該響下面嘅情況之下進行:
 * 唔合適嘅個人資料
index dd0183b..9863403 100644 (file)
@@ -908,6 +908,7 @@ $2',
 'createacct-another-realname-tip' => '真实姓名是选填项目。
 如果你选择提供它,它将会用于贡献署名。',
 'pt-login' => '登录',
+'pt-login-button' => '登录',
 'pt-createaccount' => '创建账户',
 'pt-userlogout' => '退出',
 
@@ -1272,8 +1273,10 @@ $3给出的原因是“$2”。",
 'revdelete-show-file-submit' => '是',
 'revdelete-selected' => "'''选取'''[[:$1]]'''的$2次修订:'''",
 'logdelete-selected' => "'''{{PLURAL:$1|选取的日志项目}}:'''",
-'revdelete-text' => "'''删除的版本仍将显示在页面历史及日志中,但公众已不能访问其文本内容。'''
-在{{SITENAME}}的其他管理员将仍能访问隐藏的内容并通过该界面恢复删除的版本,除非进行了额外限制。",
+'revdelete-text-text' => '已删除修订仍将在页面历史中显示,但涉及部分的内容将对公众不可见。',
+'revdelete-text-file' => '已删除文件版本仍将在文件历史中显示,但涉及部分的内容将对公众不可见。',
+'logdelete-text' => '已删除日志事件仍将在日志中显示,但涉及部分的内容将对公众不可见。',
+'revdelete-text-others' => '在{{SITENAME}}的其他管理员仍将可以访问隐藏内容,并在一定条件下能够通过相同界面取消删除,除非附加条件被设定。',
 'revdelete-confirm' => '请确认该操作,明白其后果,并确保该操作符合[[{{MediaWiki:Policy-url}}|方针]]。',
 'revdelete-suppress-text' => "阻止应'''仅'''用于以下情况:
 * 潜在的诽谤信息
@@ -1402,7 +1405,7 @@ $1",
 'search-file-match' => '(匹配文件内容)',
 'search-suggest' => '您是不是要找:$1',
 'search-interwiki-caption' => '姊妹项目',
-'search-interwiki-default' => '$1项结果:',
+'search-interwiki-default' => '来自$1的结果:',
 'search-interwiki-more' => '(更多)',
 'search-relatedarticle' => '相关',
 'searcheverything-enable' => '在所有名字空间中搜索',
@@ -1719,7 +1722,7 @@ $1",
 'recentchanges-label-unpatrolled' => '该编辑尚未巡查',
 'recentchanges-label-plusminus' => '该页面字节数的前后变化',
 'recentchanges-legend-heading' => "'''说明:'''",
-'recentchanges-legend-newpage' => '(见[[Special:NewPages|新页面列表]])',
+'recentchanges-legend-newpage' => '(见[[Special:NewPages|新页面列表]])',
 'recentchanges-legend-plusminus' => "(''±123'')",
 'rcnotefrom' => '下面是<strong>$2</strong>之后的更改(最多显示<strong>$1</strong>个)。',
 'rclistfrom' => '显示$1之后的新更改',
@@ -1857,7 +1860,7 @@ $1",
 'uploaddisabledtext' => '文件上传已停用。',
 'php-uploaddisabledtext' => 'PHP文件上传停用。请检查file_uploads设置。',
 'uploadscripted' => '该文件包含可能被网络浏览器错误解释的 HTML 或脚本代码。',
-'uploadscriptednamespace' => "此SVG文件包含非法名字空间'$1'",
+'uploadscriptednamespace' => '此SVG文件包含非法名字空间“$1”',
 'uploadinvalidxml' => '上传文件中的XML无法解析。',
 'uploadvirus' => '该文件包含病毒!
 详情:$1',
index 17123d0..64471a7 100644 (file)
@@ -806,6 +806,7 @@ $2',
 'createacct-another-realname-tip' => '真實姓名為選填。
 如果您選擇提供,它將用於貢獻署名。',
 'pt-login' => '登入',
+'pt-login-button' => '登入',
 'pt-createaccount' => '建立帳戶',
 'pt-userlogout' => '登出',
 
@@ -1201,8 +1202,10 @@ $3所述禁止原因為“$2”。",
 'revdelete-show-file-submit' => '是',
 'revdelete-selected' => "'''選取[[:$1]]的$2次修訂:'''",
 'logdelete-selected' => "'''{{PLURAL:$1|選取的日誌項目}}:'''",
-'revdelete-text' => "'''刪除的修訂仍將顯示在頁面歷史中, 但它們的文字內容已不能被公眾訪問。'''
-在{{SITENAME}}的其他管理員將仍能訪問隱藏的內容並透過與此相同的介面恢復刪除,除非網站工作者進行了一些附加的限制。",
+'revdelete-text-text' => '已刪除修訂版本仍將出現於頁面歷史中,唯將不公開內容訪問。',
+'revdelete-text-file' => '已刪除檔案版本仍將出現於檔案歷史中,唯將不公開內容訪問。',
+'logdelete-text' => '已刪除日誌活動仍將出現於日誌中,唯將不公開內容訪問。',
+'revdelete-text-others' => '於{{SITENAME}}之其他管理員仍有權限訪問隱藏內容,亦可於同一界面恢復刪除,除非設定額外條件。',
 'revdelete-confirm' => '請確認您肯定去做的話,您就要明白到後果,以及這個程序符合[[{{MediaWiki:Policy-url}}|政策]]。',
 'revdelete-suppress-text' => "禁制應'''僅'''於下述情形之一時使用:
 * 潛在誹謗性資訊
@@ -1332,7 +1335,7 @@ $1",
 'search-file-match' => '(匹配檔案內容)',
 'search-suggest' => '{{GENDER:|你|妳|你}}是不是要找:$1',
 'search-interwiki-caption' => '姊妹計劃',
-'search-interwiki-default' => '$1 項結果:',
+'search-interwiki-default' => '來自$1之結果:',
 'search-interwiki-more' => '(更多)',
 'search-relatedarticle' => '相關',
 'searcheverything-enable' => '在所有名字空間中搜尋',
@@ -1654,7 +1657,7 @@ $1",
 'recentchanges-label-unpatrolled' => '這次編輯尚未巡查過',
 'recentchanges-label-plusminus' => '更改前後頁面位元組大小的變化',
 'recentchanges-legend-heading' => "'''說明:'''",
-'recentchanges-legend-newpage' => '(見[[Special:NewPages|新頁面列表]])',
+'recentchanges-legend-newpage' => '(見[[Special:NewPages|新頁面列表]])',
 'recentchanges-legend-plusminus' => "(''±123'')",
 'rcnotefrom' => '下面是自<strong>$2</strong>起之更改(至多顯示<strong>$1</strong>個)。',
 'rclistfrom' => '顯示自 $1 以來的新變更',
@@ -1795,7 +1798,7 @@ $1",
 'uploaddisabledtext' => '檔案上傳不可用。',
 'php-uploaddisabledtext' => 'PHP 檔案上載已經停用。請檢查 file_uploads 設定。',
 'uploadscripted' => '該檔案包含可能被網路瀏覽器錯誤解釋的 HTML 或腳本代碼。',
-'uploadscriptednamespace' => "此SVG檔案中包含非法命名空間'$1'",
+'uploadscriptednamespace' => '此SVG檔案中包含非法命名空間「$1」',
 'uploadinvalidxml' => '上載檔案中的XML無法解析。',
 'uploadvirus' => '該檔案包含有病毒!
 詳情:$1',
index bd21b18..76b5e3c 100644 (file)
@@ -63,7 +63,6 @@ class bench_strtr_str_replace extends Benchmarker {
                str_replace( "_", " ", "[[MediaWiki:Some_random_test_page]]");
        }
 
-
        function benchstrtr_indirect() {
                bfNormalizeTitleStrTr( "[[MediaWiki:Some_random_test_page]]" );
        }
index 9c8354c..fd56361 100644 (file)
@@ -65,7 +65,7 @@ class GenerateJsonI18n extends Maintenance {
                        $extensionStyle = false;
                        $langcode = $this->getOption( 'langcode' );
                        $messages = array( $langcode => $messages );
-               } else if ( $this->hasOption( 'langcode' ) ) {
+               } elseif ( $this->hasOption( 'langcode' ) ) {
                        $this->output( "Warning: --langcode option set but will not be used.\n" );
                }
 
index 60cc3a8..d4fdfee 100644 (file)
@@ -558,6 +558,7 @@ $wgMessageStructure = array(
                'suspicious-userlogout',
                'createacct-another-realname-tip',
                'pt-login',
+               'pt-login-button',
                'pt-createaccount',
                'pt-userlogout',
        ),
@@ -869,7 +870,10 @@ $wgMessageStructure = array(
                'revdelete-show-file-submit',
                'revdelete-selected',
                'logdelete-selected',
-               'revdelete-text',
+               'revdelete-text-text',
+               'revdelete-text-file',
+               'logdelete-text',
+               'revdelete-text-others',
                'revdelete-confirm',
                'revdelete-suppress-text',
                'revdelete-legend',
index 2f89520..85a125f 100644 (file)
@@ -51,7 +51,9 @@ class PurgeList extends Maintenance {
                $this->output( "Done!\n" );
        }
 
-       /** Purge URL coming from stdin */
+       /**
+        * Purge URL coming from stdin
+        */
        private function doPurge() {
                $stdin = $this->getStdin();
                $urls = array();
@@ -78,7 +80,9 @@ class PurgeList extends Maintenance {
                $this->sendPurgeRequest( $urls );
        }
 
-       /** Purge a namespace or all pages */
+       /**
+        * Purge a namespace or all pages
+        */
        private function purgeNamespace( $namespace = false ) {
                $dbr = wfGetDB( DB_SLAVE );
                $startId = 0;
index f0be709..aade17e 100644 (file)
@@ -221,6 +221,9 @@ class SyncFileBackend extends Maintenance {
                        return $status;
                }
 
+               $src->preloadFileStat( array( 'srcs' => $sPaths, 'latest' => 1 ) );
+               $dst->preloadFileStat( array( 'srcs' => $dPaths, 'latest' => 1 ) );
+
                $ops = array();
                $fsFiles = array();
                foreach ( $sPaths as $i => $sPath ) {
index 57eda3d..026052c 100644 (file)
                 * @return {boolean} return.done.isCategory Whether the category exists.
                 */
                isCategory: function ( title, ok, err ) {
-                       var d = $.Deferred(),
-                               apiPromise;
+                       var apiPromise = this.get( {
+                               prop: 'categoryinfo',
+                               titles: String( title )
+                       } );
 
                        // Backwards compatibility (< MW 1.20)
                        if ( ok || err ) {
                                mw.track( 'mw.deprecate', 'api.cbParam' );
                                mw.log.warn( msg );
-                               d.done( ok ).fail( err );
                        }
 
-                       apiPromise = this.get( {
-                                       prop: 'categoryinfo',
-                                       titles: title.toString()
-                               } )
-                               .done( function ( data ) {
+                       return apiPromise
+                               .then( function ( data ) {
                                        var exists = false;
                                        if ( data.query && data.query.pages ) {
                                                $.each( data.query.pages, function ( id, page ) {
                                                        }
                                                } );
                                        }
-                                       d.resolve( exists );
+                                       return exists;
                                } )
-                               .fail( d.reject );
-
-                       return d.promise( { abort: apiPromise.abort } );
+                               .done( ok )
+                               .fail( err )
+                               .promise( { abort: apiPromise.abort } );
                },
 
                /**
                 * Get a list of categories that match a certain prefix.
-                *   e.g. given "Foo", return "Food", "Foolish people", "Foosball tables" ...
+                *
+                * E.g. given "Foo", return "Food", "Foolish people", "Foosball tables" ...
+                *
                 * @param {string} prefix Prefix to match.
                 * @param {Function} [ok] Success callback (deprecated)
                 * @param {Function} [err] Error callback (deprecated)
                 * @return {jQuery.Promise}
                 * @return {Function} return.done
-                * @return {String[]} return.done.categories Matched categories
+                * @return {string[]} return.done.categories Matched categories
                 */
                getCategoriesByPrefix: function ( prefix, ok, err ) {
-                       var d = $.Deferred(),
-                               apiPromise;
+                       // Fetch with allpages to only get categories that have a corresponding description page.
+                       var apiPromise = this.get( {
+                               list: 'allpages',
+                               apprefix: prefix,
+                               apnamespace: mw.config.get( 'wgNamespaceIds' ).category
+                       } );
 
                        // Backwards compatibility (< MW 1.20)
                        if ( ok || err ) {
                                mw.track( 'mw.deprecate', 'api.cbParam' );
                                mw.log.warn( msg );
-                               d.done( ok ).fail( err );
                        }
 
-                       // Fetch with allpages to only get categories that have a corresponding description page.
-                       apiPromise = this.get( {
-                                       list: 'allpages',
-                                       apprefix: prefix,
-                                       apnamespace: mw.config.get( 'wgNamespaceIds' ).category
-                               } )
-                               .done( function ( data ) {
+                       return apiPromise
+                               .then( function ( data ) {
                                        var texts = [];
                                        if ( data.query && data.query.allpages ) {
                                                $.each( data.query.allpages, function ( i, category ) {
                                                        texts.push( new mw.Title( category.title ).getNameText() );
                                                } );
                                        }
-                                       d.resolve( texts );
+                                       return texts;
                                } )
-                               .fail( d.reject );
-
-                       return d.promise( { abort: apiPromise.abort } );
+                               .done( ok )
+                               .fail( err )
+                               .promise( { abort: apiPromise.abort } );
                },
 
 
                 *  if title was not found.
                 */
                getCategories: function ( title, ok, err, async ) {
-                       var d = $.Deferred(),
-                               apiPromise;
+                       var apiPromise = this.get( {
+                               prop: 'categories',
+                               titles: String( title )
+                       }, {
+                               async: async === undefined ? true : async
+                       } );
 
                        // Backwards compatibility (< MW 1.20)
                        if ( ok || err ) {
                                mw.track( 'mw.deprecate', 'api.cbParam' );
                                mw.log.warn( msg );
-                               d.done( ok ).fail( err );
                        }
 
-                       apiPromise = this.get( {
-                                       prop: 'categories',
-                                       titles: title.toString()
-                               }, {
-                                       async: async === undefined ? true : async
-                               } )
-                               .done( function ( data ) {
-                                       var ret = false;
+                       return apiPromise
+                               .then( function ( data ) {
+                                       var titles = false;
                                        if ( data.query && data.query.pages ) {
                                                $.each( data.query.pages, function ( id, page ) {
                                                        if ( page.categories ) {
-                                                               if ( typeof ret !== 'object' ) {
-                                                                       ret = [];
+                                                               if ( titles === false ) {
+                                                                       titles = [];
                                                                }
                                                                $.each( page.categories, function ( i, cat ) {
-                                                                       ret.push( new mw.Title( cat.title ) );
+                                                                       titles.push( new mw.Title( cat.title ) );
                                                                } );
                                                        }
                                                } );
                                        }
-                                       d.resolve( ret );
+                                       return titles;
                                } )
-                               .fail( d.reject );
-
-                       return d.promise( { abort: apiPromise.abort } );
+                               .done( ok )
+                               .fail( err )
+                               .promise( { abort: apiPromise.abort } );
                }
 
        } );
index 91d9b8f..edfb34a 100644 (file)
@@ -60,7 +60,7 @@
                                action: 'edit',
                                section: 'new',
                                format: 'json',
-                               title: title.toString(),
+                               title: String( title ),
                                summary: header,
                                text: message
                        } ).done( ok ).fail( err );
index 7490862..914f3ec 100644 (file)
@@ -49,7 +49,7 @@
                        options = {};
                }
 
-               // Force toString if we got a mw.Uri object
+               // Force a string if we got a mw.Uri object
                if ( options.ajax && options.ajax.url !== undefined ) {
                        options.ajax.url = String( options.ajax.url );
                }
index 1c04b17..952dea4 100644 (file)
                 * @return {string} return.done.data Parsed HTML of `wikitext`.
                 */
                parse: function ( wikitext, ok, err ) {
-                       var d = $.Deferred(),
-                               apiPromise;
+                       var apiPromise = this.get( {
+                               action: 'parse',
+                               contentmodel: 'wikitext',
+                               text: wikitext
+                       } );
 
                        // Backwards compatibility (< MW 1.20)
                        if ( ok || err ) {
                                mw.track( 'mw.deprecate', 'api.cbParam' );
                                mw.log.warn( 'Use of mediawiki.api callback params is deprecated. Use the Promise instead.' );
-                               d.done( ok ).fail( err );
                        }
 
-                       apiPromise = this.get( {
-                                       action: 'parse',
-                                       contentmodel: 'wikitext',
-                                       text: wikitext
+                       return apiPromise
+                               .then( function ( data ) {
+                                       return data.parse.text['*'];
                                } )
-                               .done( function ( data ) {
-                                       if ( data.parse && data.parse.text && data.parse.text['*'] ) {
-                                               d.resolve( data.parse.text['*'] );
-                                       }
-                               } )
-                               .fail( d.reject );
-
-                       return d.promise( { abort: apiPromise.abort } );
+                               .done( ok )
+                               .fail( err )
+                               .promise( { abort: apiPromise.abort } );
                }
        } );
 
index 653c90a..9d65e1f 100644 (file)
@@ -6,6 +6,7 @@
 
        /**
         * @private
+        * @static
         * @context mw.Api
         *
         * @param {string|mw.Title|string[]|mw.Title[]} pages Full page name or instance of mw.Title, or an
        function doWatchInternal( pages, ok, err, addParams ) {
                // XXX: Parameter addParams is undocumented because we inherit this
                // documentation in the public method..
-               var params, apiPromise,
-                       d = $.Deferred();
+               var apiPromise = this.post(
+                       $.extend(
+                               {
+                                       action: 'watch',
+                                       titles: $.isArray( pages ) ? pages.join( '|' ) : String( pages ),
+                                       token: mw.user.tokens.get( 'watchToken' ),
+                                       uselang: mw.config.get( 'wgUserLanguage' )
+                               },
+                               addParams
+                       )
+               );
 
                // Backwards compatibility (< MW 1.20)
                if ( ok || err ) {
                        mw.track( 'mw.deprecate', 'api.cbParam' );
                        mw.log.warn( 'Use of mediawiki.api callback params is deprecated. Use the Promise instead.' );
-                       d.done( ok ).fail( err );
                }
 
-               params = {
-                       action: 'watch',
-                       token: mw.user.tokens.get( 'watchToken' ),
-                       uselang: mw.config.get( 'wgUserLanguage' ),
-                       titles: $.isArray( pages ) ? pages.join( '|' ) : String( pages )
-               };
-
-               if ( addParams ) {
-                       $.extend( params, addParams );
-               }
-
-               apiPromise = this.post( params )
-                       .done( function ( data ) {
+               return apiPromise
+                       .then( function ( data ) {
                                // If a single page was given (not an array) respond with a single item as well.
-                               d.resolve( $.isArray( pages ) ? data.watch : data.watch[0] );
+                               return $.isArray( pages ) ? data.watch : data.watch[0];
                        } )
-                       .fail( d.reject );
-
-               return d.promise( { abort: apiPromise.abort } );
+                       .done( ok )
+                       .fail( err )
+                       .promise( { abort: apiPromise.abort } );
        }
 
        $.extend( mw.Api.prototype, {
index 1e145ea..ff14ff3 100644 (file)
@@ -8,5 +8,6 @@
     "ooui-dialog-action-close": "ДӀачӀагӀа",
     "ooui-outline-control-move-down": "Лаха яккха элемент",
     "ooui-outline-control-move-up": "Лаккха яккха элемент",
+    "ooui-outline-control-remove": "ДӀадаха меттиг",
     "ooui-toolbar-more": "Кхин тӀе"
 }
\ No newline at end of file
index 9661ec6..670073f 100644 (file)
@@ -16,5 +16,6 @@
     "ooui-dialog-action-close": "Zavřít",
     "ooui-outline-control-move-down": "Přesunout položku dolů",
     "ooui-outline-control-move-up": "Přesunout položku nahoru",
+    "ooui-outline-control-remove": "Odstranit položku",
     "ooui-toolbar-more": "Další"
 }
\ No newline at end of file
index 5d0928f..a029456 100644 (file)
@@ -9,5 +9,6 @@
     "ooui-dialog-action-close": "Pechar",
     "ooui-outline-control-move-down": "Mover o elemento abaixo",
     "ooui-outline-control-move-up": "Mover o elemento arriba",
+    "ooui-outline-control-remove": "Eliminar o elemento",
     "ooui-toolbar-more": "Máis"
 }
\ No newline at end of file
index 9f7b435..b2cf2c0 100644 (file)
@@ -4,11 +4,13 @@
             "Dj",
             "Einstein2",
             "Misibacsi",
-            "ViDam"
+            "ViDam",
+            "Tacsipacsi"
         ]
     },
     "ooui-dialog-action-close": "Bezár",
     "ooui-outline-control-move-down": "Elem mozgatása lefelé",
     "ooui-outline-control-move-up": "Elem mozgatása felfelé",
+    "ooui-outline-control-remove": "Elem eltávolítása",
     "ooui-toolbar-more": "Tovább..."
 }
\ No newline at end of file
index 15f42e5..838face 100644 (file)
@@ -7,5 +7,6 @@
     "ooui-dialog-action-close": "Irekep",
     "ooui-outline-control-move-down": "Ipababa ti banag",
     "ooui-outline-control-move-up": "Ipangato ti banag",
+    "ooui-outline-control-remove": "Ikkaten ti banag",
     "ooui-toolbar-more": "Adu pay"
 }
\ No newline at end of file
index a4dba27..53b5280 100644 (file)
@@ -9,11 +9,13 @@
             "Jaideraf",
             "Jdforrester",
             "Luckas",
-            "Vitorvicentevalente"
+            "Vitorvicentevalente",
+            "SandroHc"
         ]
     },
     "ooui-dialog-action-close": "Fechar",
     "ooui-outline-control-move-down": "Mover item para baixo",
     "ooui-outline-control-move-up": "Mover item para cima",
+    "ooui-outline-control-remove": "Remover elemento",
     "ooui-toolbar-more": "Mais"
 }
\ No newline at end of file
index 1f13047..a27c53e 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOjs UI v0.1.0-pre (efc7297353)
+ * OOjs UI v0.1.0-pre (ac0cc69508)
  * https://www.mediawiki.org/wiki/OOjs_UI
  *
  * Copyright 2011–2014 OOjs Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: Fri Mar 07 2014 17:36:48 GMT-0800 (PST)
+ * Date: Thu Mar 13 2014 17:11:12 GMT-0700 (PDT)
  */
 ( function () {
 
@@ -2459,6 +2459,7 @@ OO.ui.IndicatedElement.prototype.getIndicatorTitle = function () {
  * @param {jQuery} $label Label node, assigned to #$label
  * @param {Object} [config] Configuration options
  * @cfg {jQuery|string|Function} [label] Label nodes, text or a function that returns nodes or text
+ * @cfg {boolean} [autoFitLabel=true] Whether to fit the label or not.
  */
 OO.ui.LabeledElement = function OoUiLabeledElement( $label, config ) {
        // Config intialization
@@ -2471,6 +2472,7 @@ OO.ui.LabeledElement = function OoUiLabeledElement( $label, config ) {
        // Initialization
        this.$label.addClass( 'oo-ui-labeledElement-label' );
        this.setLabel( config.label || this.constructor.static.label );
+       this.autoFitLabel = config.autoFitLabel === undefined || !!config.autoFitLabel;
 };
 
 /* Static Properties */
@@ -2541,7 +2543,7 @@ OO.ui.LabeledElement.prototype.getLabel = function () {
  * @chainable
  */
 OO.ui.LabeledElement.prototype.fitLabel = function () {
-       if ( this.$label.autoEllipsis ) {
+       if ( this.$label.autoEllipsis && this.autoFitLabel ) {
                this.$label.autoEllipsis( { 'hasSpan': false, 'tooltip': true } );
        }
        return this;
index daf6f35..2a6fab2 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOjs UI v0.1.0-pre (efc7297353)
+ * OOjs UI v0.1.0-pre (ac0cc69508)
  * https://www.mediawiki.org/wiki/OOjs_UI
  *
  * Copyright 2011–2014 OOjs Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: Fri Mar 07 2014 17:36:48 GMT-0800 (PST)
+ * Date: Thu Mar 13 2014 17:11:12 GMT-0700 (PDT)
  */
 
 /* Textures */
 
 .oo-ui-dialog-small .oo-ui-window-frame {
   width: 400px;
-  max-height: 200px;
+  max-height: 230px;
 }
 
 .oo-ui-dialog-medium .oo-ui-window-frame {
   width: 600px;
-  max-height: 400px;
+  max-height: 460px;
 }
 
 .oo-ui-dialog-large .oo-ui-window-frame {
   width: 800px;
-  max-height: 600px;
+  max-height: 690px;
 }
 
 .oo-ui-dialog .oo-ui-frame {
index bb0f013..2bab6ad 100644 (file)
@@ -167,6 +167,7 @@ class VectorTemplate extends BaseTemplate {
                                $this->data['pageLanguage'] = $this->getSkin()->getTitle()->getPageViewLanguage()->getHtmlCode();
                                $this->text( 'pageLanguage' );
                        ?>"><span dir="auto"><?php $this->html( 'title' ) ?></span></h1>
+                       <?php $this->html( 'prebodyhtml' ) ?>
                        <div id="bodyContent">
                                <?php if ( $this->data['isarticle'] ) { ?>
                                <div id="siteSub"><?php $this->msg( 'tagline' ) ?></div>
diff --git a/skins/vector/components/animations.less b/skins/vector/components/animations.less
new file mode 100644 (file)
index 0000000..9163779
--- /dev/null
@@ -0,0 +1,28 @@
+/* Animate between standard and high definition layouts */
+body.vector-animateLayout {
+       div#content,
+       div#footer,
+       #left-navigation {
+               .transition(margin-left 250ms, padding 250ms;);
+       }
+
+       #p-logo {
+               .transition(left 250ms);
+       }
+
+       #mw-panel {
+               .transition(padding-right 250ms);
+       }
+
+       #p-search {
+               .transition(margin-right 250ms);
+       }
+
+       #p-personal {
+               .transition(right 250ms);
+       }
+
+       #mw-head-base {
+               .transition(margin-left 250ms);
+       }
+}
index cb89a7b..8e7fc4d 100644 (file)
@@ -87,32 +87,3 @@ pre, .mw-code {
 .tipsy {
        font-size: 0.8em;
 }
-
-/* Animate between standard and high definition layouts */
-body.vector-animateLayout {
-       div#content,
-       div#footer,
-       #left-navigation {
-               .transition(margin-left 250ms, padding 250ms;);
-       }
-
-       #p-logo {
-               .transition(left 250ms);
-       }
-
-       #mw-panel {
-               .transition(padding-right 250ms);
-       }
-
-       #p-search {
-               .transition(margin-right 250ms);
-       }
-
-       #p-personal {
-               .transition(right 250ms);
-       }
-
-       #mw-head-base {
-               .transition(margin-left 250ms);
-       }
-}
index 8d5423a..819286e 100644 (file)
@@ -2,6 +2,7 @@
 
 @media screen {
        @import "components/common.less";
+       @import "components/animations.less";
        @import "components/navigation.less";
        @import "components/footer.less";
        @import 'components/notifications.less';
index d9ad773..7b0fc44 100644 (file)
@@ -35,7 +35,10 @@ class ParserTestResult {
                $this->description = $description;
        }
 
-       /** Whether the test passed */
+       /**
+        * Whether the test passed
+        * @return bool
+        */
        public function isSuccess() {
                return $this->expected === $this->actual;
        }
index 55e93e2..95b9d05 100644 (file)
@@ -387,7 +387,7 @@ class ParserTest {
 
                foreach ( $filenames as $filename ) {
                        $contents = file_get_contents( $filename );
-                       preg_match_all( '/!!\s*input\n(.*?)\n!!\s*result/s', $contents, $matches );
+                       preg_match_all( '/!!\s*(input|wikitext)\n(.*?)\n!!\s*(result|html|html\/\*|html\/php)/s', $contents, $matches );
 
                        foreach ( $matches[1] as $match ) {
                                $dict .= $match . "\n";
index bbfea6a..9cea156 100644 (file)
@@ -157,23 +157,23 @@ Template:OpenTable
 ###
 !! test
 Blank input
-!! input
-!! result
+!! wikitext
+!! html
 !! end
 
 
 !! test
 Simple paragraph
-!! input
+!! wikitext
 This is a simple paragraph.
-!! result
+!! html
 <p>This is a simple paragraph.
 </p>
 !! end
 
 !! test
 Paragraphs with extra newline spacing
-!! input
+!! wikitext
 foo
 
 bar
@@ -184,7 +184,7 @@ baz
 
 
 booz
-!! result
+!! html
 <p>foo
 </p><p>bar
 </p><p><br />
@@ -196,7 +196,7 @@ baz
 
 !! test
 Paragraphs with newline spacing with comment lines in between
-!! input
+!! wikitext
 ----
 a
 <!--foo-->
@@ -232,7 +232,7 @@ a
 <!--foo-->
 b
 ----
-!! result
+!! html
 <hr />
 <p>a
 b
@@ -269,7 +269,7 @@ b
 
 !! test
 Paragraphs with newline spacing with non-empty white-space lines in between
-!! input
+!! wikitext
 ----
 a
  
@@ -280,7 +280,7 @@ a
  
 b
 ----
-!! result
+!! html
 <hr />
 <p>a
 </p><p>b
@@ -296,7 +296,7 @@ b
 
 !! test
 Paragraphs with newline spacing with non-empty mixed comment and white-space lines in between
-!! input
+!! wikitext
 ----
 a
  <!--foo-->
@@ -319,7 +319,7 @@ a
  
 b
 ----
-!! result
+!! html
 <hr />
 <p>a
 b
@@ -343,13 +343,13 @@ b
 
 !! test
 Extra newlines: More paragraphs with indented comment
-!! input
+!! wikitext
 a
 
    <!--boo-->
 
 b
-!!result
+!! html
 <p>a
 </p><p><br />
 b
@@ -358,7 +358,7 @@ b
 
 !! test
 Extra newlines followed by heading
-!! input
+!! wikitext
 a
 
 
@@ -368,7 +368,7 @@ a
 
 
 =b=
-!! result
+!! html
 <p>a
 </p><p><br />
 </p>
@@ -382,13 +382,13 @@ a
 
 !! test
 Extra newlines between heading and content are swallowed
-!! input
+!! wikitext
 =b=
 
 
 
 [[a]]
-!! result
+!! html
 <h1><span class="mw-headline" id="b">b</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=1" title="Edit section: b">edit</a><span class="mw-editsection-bracket">]</span></span></h1>
 <p><a href="/index.php?title=A&amp;action=edit&amp;redlink=1" class="new" title="A (page does not exist)">a</a>
 </p>
@@ -396,20 +396,20 @@ Extra newlines between heading and content are swallowed
 
 !! test
 Parsing an URL
-!! input
+!! wikitext
 http://fr.wikipedia.org/wiki/🍺
 <!-- EasterEgg we love beer, better be able be able to link to it -->
-!! result
+!! html
 <p><a rel="nofollow" class="external free" href="http://fr.wikipedia.org/wiki/🍺">http://fr.wikipedia.org/wiki/🍺</a>
 </p>
 !! end
 
 !! test
 Simple list
-!! input
+!! wikitext
 * Item 1
 * Item 2
-!! result
+!! html
 <ul>
 <li> Item 1
 </li>
@@ -421,7 +421,7 @@ Simple list
 
 !! test
 Italics and bold
-!! input
+!! wikitext
 * plain
 * plain''italic''plain
 * plain''italic''plain''italic''plain
@@ -437,7 +437,7 @@ Italics and bold
 * plain'''bold''bold-italic'''''plain
 * plain l'''italic''plain
 * plain l''''bold''' plain
-!! result
+!! html
 <ul>
 <li> plain
 </li>
@@ -476,9 +476,9 @@ Italics and bold
 # this example taken from the [[simple:Moon]] article (bug 47326)
 !! test
 Italics and possessives (1)
-!! input
+!! wikitext
 obtained by ''[[Lunar Prospector]]'''s gamma-ray spectrometer
-!! result
+!! html
 <p>obtained by <i><a href="/index.php?title=Lunar_Prospector&amp;action=edit&amp;redlink=1" class="new" title="Lunar Prospector (page does not exist)">Lunar Prospector</a>'</i>s gamma-ray spectrometer
 </p>
 !! end
@@ -486,9 +486,9 @@ obtained by ''[[Lunar Prospector]]'''s gamma-ray spectrometer
 # this example taken from [[en:Flaming Pie]] (bug 49926)
 !! test
 Italics and possessives (2)
-!! input
+!! wikitext
 '''''Flaming Pie''''' is ... released in 1997. In ''Flaming Pie'''s liner notes
-!! result
+!! html
 <p><i><b>Flaming Pie</b></i> is ... released in 1997. In <i>Flaming Pie'</i>s liner notes
 </p>
 !! end
@@ -496,9 +496,9 @@ Italics and possessives (2)
 # this example taken from [[en:Dictionary]] (bug 49926)
 !! test
 Italics and possessives (3)
-!! input
+!! wikitext
 The first monolingual dictionary written in a Romance language was ''Sebastián Covarrubias''' ''Tesoro de la lengua castellana o española'', published in 1611 in Madrid. In 1612 the first edition of the ''Vocabolario dell'[[Accademia della Crusca]]'', for Italian, was published. In 1690 in Rotterdam was published, posthumously, the ''Dictionnaire Universel''.
-!! result
+!! html
 <p>The first monolingual dictionary written in a Romance language was <i>Sebastián Covarrubias'</i> <i>Tesoro de la lengua castellana o española</i>, published in 1611 in Madrid. In 1612 the first edition of the <i>Vocabolario dell'<a href="/index.php?title=Accademia_della_Crusca&amp;action=edit&amp;redlink=1" class="new" title="Accademia della Crusca (page does not exist)">Accademia della Crusca</a></i>, for Italian, was published. In 1690 in Rotterdam was published, posthumously, the <i>Dictionnaire Universel</i>.
 </p>
 !! end
@@ -509,9 +509,9 @@ The first monolingual dictionary written in a Romance language was ''Sebastián
 ###
 !! test
 Italics and bold: 2-quote opening sequence: (2,2)
-!! input
+!! wikitext
 ''foo''
-!! result
+!! html
 <p><i>foo</i>
 </p>
 !!end
@@ -519,9 +519,9 @@ Italics and bold: 2-quote opening sequence: (2,2)
 
 !! test
 Italics and bold: 2-quote opening sequence: (2,3)
-!! input
+!! wikitext
 ''foo'''
-!! result
+!! html
 <p><i>foo'</i>
 </p>
 !!end
@@ -529,32 +529,23 @@ Italics and bold: 2-quote opening sequence: (2,3)
 
 !! test
 Italics and bold: 2-quote opening sequence: (2,4)
-!! input
+!! wikitext
 ''foo''''
-!! result
+!! html
 <p><i>foo''</i>
 </p>
 !!end
 
 
+# The PHP parser strips the empty tags out for giggles; parsoid doesn't.
 !! test
-Italics and bold: 2-quote opening sequence: (2,5) (php)
-!! options
-php
-!! input
+Italics and bold: 2-quote opening sequence: (2,5)
+!! wikitext
 ''foo'''''
-!! result
+!! html/php
 <p><i>foo</i>
 </p>
-!!end
-# The PHP parser strips the empty tags out for giggles; parsoid doesn't.
-!! test
-Italics and bold: 2-quote opening sequence: (2,5) (parsoid)
-!! options
-parsoid
-!! input
-''foo'''''
-!! result
+!! html/parsoid
 <p><i>foo</i><b></b>
 </p>
 !!end
@@ -566,9 +557,9 @@ parsoid
 
 !! test
 Italics and bold: 3-quote opening sequence: (3,2)
-!! input
+!! wikitext
 '''foo''
-!! result
+!! html
 <p>'<i>foo</i>
 </p>
 !!end
@@ -576,9 +567,9 @@ Italics and bold: 3-quote opening sequence: (3,2)
 
 !! test
 Italics and bold: 3-quote opening sequence: (3,3)
-!! input
+!! wikitext
 '''foo'''
-!! result
+!! html
 <p><b>foo</b>
 </p>
 !!end
@@ -586,32 +577,23 @@ Italics and bold: 3-quote opening sequence: (3,3)
 
 !! test
 Italics and bold: 3-quote opening sequence: (3,4)
-!! input
+!! wikitext
 '''foo''''
-!! result
+!! html
 <p><b>foo'</b>
 </p>
 !!end
 
 
+# The PHP parser strips the empty tags out for giggles; parsoid doesn't.
 !! test
-Italics and bold: 3-quote opening sequence: (3,5) (php)
-!! options
-php
-!! input
+Italics and bold: 3-quote opening sequence: (3,5)
+!! wikitext
 '''foo'''''
-!! result
+!! html/php
 <p><b>foo</b>
 </p>
-!!end
-# The PHP parser strips the empty tags out for giggles; parsoid doesn't.
-!! test
-Italics and bold: 3-quote opening sequence: (3,5) (parsoid)
-!! options
-parsoid
-!! input
-'''foo'''''
-!! result
+!! html/parsoid
 <p><b>foo</b><i></i>
 </p>
 !!end
@@ -623,9 +605,9 @@ parsoid
 
 !! test
 Italics and bold: 4-quote opening sequence: (4,2)
-!! input
+!! wikitext
 ''''foo''
-!! result
+!! html
 <p>''<i>foo</i>
 </p>
 !!end
@@ -633,9 +615,9 @@ Italics and bold: 4-quote opening sequence: (4,2)
 
 !! test
 Italics and bold: 4-quote opening sequence: (4,3)
-!! input
+!! wikitext
 ''''foo'''
-!! result
+!! html
 <p>'<b>foo</b>
 </p>
 !!end
@@ -643,32 +625,23 @@ Italics and bold: 4-quote opening sequence: (4,3)
 
 !! test
 Italics and bold: 4-quote opening sequence: (4,4)
-!! input
+!! wikitext
 ''''foo''''
-!! result
+!! html
 <p>'<b>foo'</b>
 </p>
 !!end
 
 
+# The PHP parser strips the empty tags out for giggles; parsoid doesn't.
 !! test
-Italics and bold: 4-quote opening sequence: (4,5) (php)
-!! options
-php
-!! input
+Italics and bold: 4-quote opening sequence: (4,5)
+!! wikitext
 ''''foo'''''
-!! result
+!! html/php
 <p>'<b>foo</b>
 </p>
-!!end
-# The PHP parser strips the empty tags out for giggles; parsoid doesn't.
-!! test
-Italics and bold: 4-quote opening sequence: (4,5) (parsoid)
-!! options
-parsoid
-!! input
-''''foo'''''
-!! result
+!! html/parsoid
 <p>'<b>foo</b><i></i>
 </p>
 !!end
@@ -681,9 +654,9 @@ parsoid
 !! test
 Italics and bold: 5-quote opening sequence: (5,2)
 !! options
-!! input
+!! wikitext
 '''''foo''
-!! result
+!! html
 <p><b><i>foo</i></b>
 </p>
 !!end
@@ -691,9 +664,9 @@ Italics and bold: 5-quote opening sequence: (5,2)
 
 !! test
 Italics and bold: 5-quote opening sequence: (5,3)
-!! input
+!! wikitext
 '''''foo'''
-!! result
+!! html
 <p><i><b>foo</b></i>
 </p>
 !!end
@@ -701,9 +674,9 @@ Italics and bold: 5-quote opening sequence: (5,3)
 
 !! test
 Italics and bold: 5-quote opening sequence: (5,4)
-!! input
+!! wikitext
 '''''foo''''
-!! result
+!! html
 <p><i><b>foo'</b></i>
 </p>
 !!end
@@ -711,9 +684,9 @@ Italics and bold: 5-quote opening sequence: (5,4)
 
 !! test
 Italics and bold: 5-quote opening sequence: (5,5)
-!! input
+!! wikitext
 '''''foo'''''
-!! result
+!! html
 <p><i><b>foo</b></i>
 </p>
 !!end
@@ -723,9 +696,9 @@ Italics and bold: 5-quote opening sequence: (5,5)
 ###
 !! test
 Italics and bold: multiple quote sequences: (2,4,2)
-!! input
+!! wikitext
 ''foo''''bar''
-!! result
+!! html
 <p><i>foo'<b>bar</b></i>
 </p>
 !!end
@@ -733,9 +706,9 @@ Italics and bold: multiple quote sequences: (2,4,2)
 
 !! test
 Italics and bold: multiple quote sequences: (2,4,3)
-!! input
+!! wikitext
 ''foo''''bar'''
-!! result
+!! html
 <p><i>foo'<b>bar</b></i>
 </p>
 !!end
@@ -743,55 +716,37 @@ Italics and bold: multiple quote sequences: (2,4,3)
 
 !! test
 Italics and bold: multiple quote sequences: (2,4,4)
-!! input
+!! wikitext
 ''foo''''bar''''
-!! result
+!! html
 <p><i>foo'<b>bar'</b></i>
 </p>
 !!end
 
 
+# The PHP parser strips the empty tags out for giggles; parsoid doesn't.
 !! test
-Italics and bold: multiple quote sequences: (3,4,2) (php)
-!! options
-php
-!! input
+Italics and bold: multiple quote sequences: (3,4,2)
+!! wikitext
 '''foo''''bar''
-!! result
+!! html/php
 <p><b>foo'</b>bar
 </p>
-!!end
-# The PHP parser strips the empty tags out for giggles; parsoid doesn't.
-!! test
-Italics and bold: multiple quote sequences: (3,4,2) (parsoid)
-!! options
-parsoid
-!! input
-'''foo''''bar''
-!! result
+!! html/parsoid
 <p><b>foo'</b>bar<i></i>
 </p>
 !!end
 
 
+# The PHP parser strips the empty tags out for giggles; parsoid doesn't.
 !! test
-Italics and bold: multiple quote sequences: (3,4,3) (php)
-!! options
-php
-!! input
+Italics and bold: multiple quote sequences: (3,4,3)
+!! wikitext
 '''foo''''bar'''
-!! result
+!! html/php
 <p><b>foo'</b>bar
 </p>
-!!end
-# The PHP parser strips the empty tags out for giggles; parsoid doesn't.
-!! test
-Italics and bold: multiple quote sequences: (3,4,3) (parsoid)
-!! options
-parsoid
-!! input
-'''foo''''bar'''
-!! result
+!! html/parsoid
 <p><b>foo'</b>bar<b></b>
 </p>
 !!end
@@ -801,9 +756,9 @@ parsoid
 ###
 !! test
 Italics and bold: other quote tests: (2,3,5)
-!! input
+!! wikitext
 ''this is about '''foo's family'''''
-!! result
+!! html
 <p><i>this is about <b>foo's family</b></i>
 </p>
 !!end
@@ -811,9 +766,9 @@ Italics and bold: other quote tests: (2,3,5)
 
 !! test
 Italics and bold: other quote tests: (2,(3,3),2)
-!! input
+!! wikitext
 ''this is about '''foo's''' family''
-!! result
+!! html
 <p><i>this is about <b>foo's</b> family</i>
 </p>
 !!end
@@ -821,9 +776,9 @@ Italics and bold: other quote tests: (2,(3,3),2)
 
 !! test
 Italics and bold: other quote tests: (3,2,3,2)
-!! input
+!! wikitext
 '''this is about ''foo'''s family''
-!! result
+!! html
 <p><b>this is about <i>foo</i></b><i>s family</i>
 </p>
 !!end
@@ -832,9 +787,9 @@ Italics and bold: other quote tests: (3,2,3,2)
 !! test
 Italics and bold: other quote tests: (3,2,3,3)
 !! options
-!! input
+!! wikitext
 '''this is about ''foo'''s family'''
-!! result
+!! html
 <p>'<i>this is about </i>foo<b>s family</b>
 </p>
 !!end
@@ -842,9 +797,9 @@ Italics and bold: other quote tests: (3,2,3,3)
 
 !! test
 Italics and bold: other quote tests: (3,(2,2),3)
-!! input
+!! wikitext
 '''this is about ''foo's'' family'''
-!! result
+!! html
 <p><b>this is about <i>foo's</i> family</b>
 </p>
 !!end
@@ -852,9 +807,9 @@ Italics and bold: other quote tests: (3,(2,2),3)
 
 !! test
 Italicized possessive
-!! input
+!! wikitext
 The ''[[Main Page]]'''s talk page.
-!! result
+!! html
 <p>The <i><a href="/wiki/Main_Page" title="Main Page">Main Page</a>'</i>s talk page.
 </p>
 !! end
@@ -864,12 +819,12 @@ Parsoid only: Quote balancing context should be restricted to td/th cells on the
 (Requires tidy for PHP parser output to be fixed up)
 !! options
 parsoid=wt2html,wt2wt
-!! input
+!! wikitext
 {|
 !''a!!''b
 |''a||''b
 |}
-!! result
+!! html
 <table>
 <tbody><tr><th><i>a</i></th><th><i>b</i></th>
 <td><i>a</i></td><td><i>b</i></td></tr>
@@ -882,13 +837,13 @@ parsoid=wt2html,wt2wt
 
 !! test
 Non-html5 tags should be accepted
-!! input
+!! wikitext
 <center>''foo''</center>
 <big>''foo''</big>
 <font>''foo''</font>
 <strike>''foo''</strike>
 <tt>''foo''</tt>
-!! result
+!! html
 <center><i>foo</i></center>
 <p><big><i>foo</i></big>
 <font><i>foo</i></font>
@@ -899,9 +854,9 @@ Non-html5 tags should be accepted
 
 !! test
 <wbr> is valid wikitext (bug 52468)
-!! input
+!! wikitext
 <wbr>
-!! result
+!! html
 <p><wbr />
 </p>
 !! end
@@ -909,11 +864,11 @@ Non-html5 tags should be accepted
 # <strike> is HTML4, <s> is HTML4/5.
 !! test
 <s> or <strike> for strikethrough
-!! input
+!! wikitext
 <strike>strike</strike>
 
 <s>s</s>
-!! result
+!! html
 <p><strike>strike</strike>
 </p><p><s>s</s>
 </p>
@@ -921,7 +876,7 @@ Non-html5 tags should be accepted
 
 !! test
 Non-word characters don't terminate tag names (bug 17663, 40670, 52022)
-!! input
+!! wikitext
 <b→> doesn't work! </b→>
 
 <bä> doesn't work! </bä>
@@ -931,7 +886,7 @@ Non-word characters don't terminate tag names (bug 17663, 40670, 52022)
 <s.foo>s.foo</s.foo>
 
 <sub-ID#1>
-!! result
+!! html
 <p>&lt;b→&gt; doesn't work! &lt;/b→&gt;
 </p><p>&lt;bä&gt; doesn't work! &lt;/bä&gt;
 </p><p>&lt;boo&gt; works fine &lt;/boo&gt;
@@ -942,11 +897,11 @@ Non-word characters don't terminate tag names (bug 17663, 40670, 52022)
 
 !! test
 Isolated close tags should be treated as literal text (bug 52760)
-!! input
+!! wikitext
 </b>
 
 <s.foo>s</s>
-!! result
+!! html
 <p>&lt;/b&gt;
 </p><p>&lt;s.foo&gt;s&lt;/s&gt;
 </p>
@@ -958,18 +913,18 @@ Isolated close tags should be treated as literal text (bug 52760)
 
 !! test
 Bare pipe character (bug 52363)
-!! input
+!! wikitext
 |
-!! result
+!! html
 <p>|
 </p>
 !! end
 
 !! test
 Bare pipe character from a template (bug 52363)
-!! input
+!! wikitext
 {{pipe}}
-!! result
+!! html
 <p>|
 </p>
 !! end
@@ -980,16 +935,16 @@ Bare pipe character from a template (bug 52363)
 
 !! test
 <nowiki> unordered list
-!! input
+!! wikitext
 <nowiki>* This is not an unordered list item.</nowiki>
-!! result
+!! html
 <p>* This is not an unordered list item.
 </p>
 !! end
 
 !! test
 <nowiki> spacing
-!! input
+!! wikitext
 <nowiki>Lorem ipsum dolor
 
 sed abit.
@@ -997,7 +952,7 @@ sed abit.
 
 :and a colon
 </nowiki>
-!! result
+!! html
 <p>Lorem ipsum dolor
 
 sed abit.
@@ -1010,7 +965,7 @@ sed abit.
 
 !! test
 nowiki 3
-!! input
+!! wikitext
 :There is not nowiki.
 :There is <nowiki>nowiki</nowiki>.
 
@@ -1019,7 +974,7 @@ nowiki 3
 
 *There is not nowiki.
 *There is <nowiki>nowiki</nowiki>.
-!! result
+!! html
 <dl>
 <dd>There is not nowiki.
 </dd>
@@ -1043,9 +998,9 @@ nowiki 3
 
 !! test
 Entities inside <nowiki>
-!! input
+!! wikitext
 <nowiki>&lt;</nowiki>
-!! result
+!! html
 <p>&lt;
 </p>
 !! end
@@ -1054,9 +1009,9 @@ Entities inside <nowiki>
 Entities inside template parameters
 !! options
 parsoid
-!! input
+!! wikitext
 {{echo|&ndash;}}
-!! result
+!! html
 <p><span typeof="mw:Transclusion mw:Entity" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"&amp;ndash;"}},"i":0}}]}'>&ndash;</span>
 </p>
 !! end
@@ -1066,7 +1021,7 @@ parsoid
 ###
 !! test
 Comments and Indent-Pre
-!! input
+!! wikitext
 <!-- comment 1 --> asdf
 
 <!-- comment 1 --> asdf
@@ -1077,7 +1032,7 @@ Comments and Indent-Pre
 
 <!-- comment 1 --> asdf
 <!-- comment 2 --> xyz
-!! result
+!! html
 <pre>asdf
 </pre>
 <pre>asdf
@@ -1093,11 +1048,11 @@ xyz
 
 !! test
 Comment test 2a
-!! input
+!! wikitext
 asdf
 <!-- comment 1 -->
 jkl
-!! result
+!! html
 <p>asdf
 jkl
 </p>
@@ -1105,12 +1060,12 @@ jkl
 
 !! test
 Comment test 2b
-!! input
+!! wikitext
 asdf
 <!-- comment 1 -->
 
 jkl
-!! result
+!! html
 <p>asdf
 </p><p>jkl
 </p>
@@ -1118,12 +1073,12 @@ jkl
 
 !! test
 Comment test 3
-!! input
+!! wikitext
 asdf
 <!-- comment 1 -->
 <!-- comment 2 -->
 jkl
-!! result
+!! html
 <p>asdf
 jkl
 </p>
@@ -1131,20 +1086,20 @@ jkl
 
 !! test
 Comment test 4
-!! input
+!! wikitext
 asdf<!-- comment 1 -->jkl
-!! result
+!! html
 <p>asdfjkl
 </p>
 !! end
 
 !! test
 Comment spacing
-!! input
+!! wikitext
 a
  <!-- foo --> b <!-- bar -->
 c
-!! result
+!! html
 <p>a
 </p>
 <pre> b 
 
 !! test
 Comment whitespace
-!! input
+!! wikitext
 <!-- returns a single newline, not nothing, since the newline after > is not stripped -->
-!! result
+!! html
 
 !! end
 
 !! test
 Comment semantics and delimiters
-!! input
+!! wikitext
 <!-- --><!----><!-----><!------>
-!! result
+!! html
 
 !! end
 
 !! test
 Comment semantics and delimiters, redux
-!! input
+!! wikitext
 <!-- In SGML every "foo" here would actually show up in the text -- foo -- bar
 -- foo -- funky huh? ... -->
-!! result
+!! html
 
 !! end
 
 !! test
 Comment semantics and delimiters: directors cut
-!! input
+!! wikitext
 <!-- ... However we like to keep things simple and somewhat XML-ish so we eat
 everything starting with < followed by !-- until the first -- and > we see,
 that wouldn't be valid XML however, since in XML -- has to terminate a comment
 -->-->
-!! result
+!! html
 <p>--&gt;
 </p>
 !! end
 
 !! test
 Comment semantics: nesting
-!! input
+!! wikitext
 <!--<!-- no, we're not going to do anything fancy here -->-->
-!! result
+!! html
 <p>--&gt;
 </p>
 !! end
 
 !! test
 Comment semantics: unclosed comment at end
-!! input
+!! wikitext
 <!--This comment will run out to the end of the document
-!! result
+!! html
 
 !! end
 
 !! test
 Comment in template title
-!! input
+!! wikitext
 {{f<!---->oo}}
-!! result
+!! html
 <p>FOO
 </p>
 !! end
 
 !! test
 Comment on its own line post-expand
-!! input
+!! wikitext
 a
 {{blank}}<!---->
 b
-!! result
+!! html
 <p>a
 </p><p>b
 </p>
 
 !! test
 Comment on its own line post-expand with non-significant whitespace
-!! input
+!! wikitext
 a
  {{blank}} <!----> 
 b
-!! result
+!! html
 <p>a
 </p><p>b
 </p>
 ###
 !! test
 No block tags
-!! input
+!! wikitext
 a
 
 b
-!! result
+!! html
 <p>a
 </p><p>b
 </p>
 
 !! test
 Block tag on one line (<div>)
-!! input
+!! wikitext
 a <div>foo</div>
 
 b
-!! result
+!! html
 a <div>foo</div>
 <p>b
 </p>
@@ -1269,11 +1224,11 @@ a <div>foo</div>
 
 !! test
 Block tag on one line (<blockquote>)
-!! input
+!! wikitext
 a <blockquote>foo</blockquote>
 
 b
-!! result
+!! html
 a <blockquote>foo</blockquote>
 <p>b
 </p>
@@ -1281,11 +1236,11 @@ a <blockquote>foo</blockquote>
 
 !! test
 Block tag on both lines (<div>)
-!! input
+!! wikitext
 a <div>foo</div>
 
 b <div>foo</div>
-!! result
+!! html
 a <div>foo</div>
 b <div>foo</div>
 
@@ -1293,11 +1248,11 @@ b <div>foo</div>
 
 !! test
 Block tag on both lines (<blockquote>)
-!! input
+!! wikitext
 a <blockquote>foo</blockquote>
 
 b <blockquote>foo</blockquote>
-!! result
+!! html
 a <blockquote>foo</blockquote>
 b <blockquote>foo</blockquote>
 
@@ -1305,13 +1260,13 @@ b <blockquote>foo</blockquote>
 
 !! test
 Multiple lines without block tags
-!! input
+!! wikitext
 <div>foo</div> a
 b
 c
 d<!--foo--> e
 x <div>foo</div> z
-!! result
+!! html
 <div>foo</div> a
 <p>b
 c
@@ -1323,7 +1278,7 @@ x <div>foo</div> z
 
 !! test
 Empty lines between lines with block tags
-!! input
+!! wikitext
 <div></div>
 
 
@@ -1336,7 +1291,7 @@ b
 
 
 <div>e</div>
-!! result
+!! html
 <div></div>
 <p><br />
 </p>
 ## PHP parser emits output which is broken
 !! test
 Unclosed HTML p-tags should be handled properly
-!! options
-parsoid
-!! input
+!! wikitext
 <div><p>foo</div>
 a
 
 b
-!! result
+!! html/parsoid
 <div data-parsoid='{"stx":"html"}'><p data-parsoid='{"stx":"html", "autoInsertedEnd":true}'>foo</p></div>
 <p>a</p>
 <p>b</p>
 ###
 !! test
 Preformatted text
-!! input
+!! wikitext
  This is some
  Preformatted text
  With ''italic''
  And '''bold'''
  And a [[Main Page|link]]
-!! result
+!! html
 <pre>This is some
 Preformatted text
 With <i>italic</i>
@@ -1389,12 +1342,12 @@ And a <a href="/wiki/Main_Page" title="Main Page">link</a>
 
 !! test
 Tabs don't trigger preformatted text
-!! input
+!! wikitext
        This is not
         preformatted text.
  This is preformatted text.
        So is this.
-!! result
+!! html
 <p>    This is not
         preformatted text.
 </p>
@@ -1405,10 +1358,10 @@ Tabs don't trigger preformatted text
 
 !! test
 Ident preformatting with inline content
-!! input
+!! wikitext
  a
  ''b''
-!! result
+!! html
 <pre>a
 <i>b</i>
 </pre>
@@ -1416,13 +1369,13 @@ Ident preformatting with inline content
 
 !! test
 <pre> with <nowiki> inside (compatibility with 1.6 and earlier)
-!! input
+!! wikitext
 <pre><nowiki>
 <b>
 <cite>
 <em>
 </nowiki></pre>
-!! result
+!! html
 <pre>
 &lt;b&gt;
 &lt;cite&gt;
@@ -1433,11 +1386,11 @@ Ident preformatting with inline content
 
 !! test
 Regression with preformatted in <center>
-!! input
+!! wikitext
 <center>
  Blah
 </center>
-!! result
+!! html
 <center>
 <pre>Blah
 </pre>
@@ -1447,7 +1400,7 @@ Regression with preformatted in <center>
 
 !! test
 Bug 52763: Preformatted in <blockquote>
-!! input
+!! wikitext
 <blockquote>
  Blah
 {|
@@ -1455,7 +1408,7 @@ Bug 52763: Preformatted in <blockquote>
  indented cell (no pre-wrapping!)
 |}
 </blockquote>
-!! result
+!! html
 <blockquote>
 <p> Blah
 </p>
@@ -1471,13 +1424,13 @@ Bug 52763: Preformatted in <blockquote>
 
 !! test
 Bug 51086: Double newlines in blockquotes should be turned into paragraphs
-!! input
+!! wikitext
 <blockquote>
 Foo
 
 Bar
 </blockquote>
-!! result
+!! html
 <blockquote>
 <p>Foo
 </p><p>Bar
@@ -1488,11 +1441,11 @@ Bar
 
 !! test
 Bug 15491: <ins>/<del> in blockquote
-!! input
+!! wikitext
 <blockquote>
 Foo <del>bar</del> <ins>baz</ins> quux
 </blockquote>
-!! result
+!! html
 <blockquote>
 <p>Foo <del>bar</del> <ins>baz</ins> quux
 </p>
@@ -1505,10 +1458,10 @@ Foo <del>bar</del> <ins>baz</ins> quux
 # below in a <p> tag. (see comment 23-25 of bug #6200)
 !! test
 Bug 15491: <ins>/<del> in blockquote (2)
-!! input
+!! wikitext
 <blockquote>Foo <del>bar</del> <ins>baz</ins> quux
 </blockquote>
-!! result
+!! html
 <blockquote>Foo <del>bar</del> <ins>baz</ins> quux
 </blockquote>
 
@@ -1516,52 +1469,52 @@ Bug 15491: <ins>/<del> in blockquote (2)
 
 !! test
 <pre> with attributes (bug 3202)
-!! input
+!! wikitext
 <pre style="background: blue; color:white">Bluescreen of WikiDeath</pre>
-!! result
+!! html
 <pre style="background: blue; color:white">Bluescreen of WikiDeath</pre>
 
 !! end
 
 !! test
 <pre> with width attribute (bug 3202)
-!! input
+!! wikitext
 <pre width="8">Narrow screen goodies</pre>
-!! result
+!! html
 <pre width="8">Narrow screen goodies</pre>
 
 !! end
 
 !! test
 <pre> with forbidden attribute (bug 3202)
-!! input
+!! wikitext
 <pre width="8" onmouseover="alert(document.cookie)">Narrow screen goodies</pre>
-!! result
+!! html
 <pre width="8">Narrow screen goodies</pre>
 
 !! end
 
 !! test
 Entities inside <pre>
-!! input
+!! wikitext
 <pre>&lt;</pre>
-!! result
+!! html
 <pre>&lt;</pre>
 
 !! end
 
 !! test
 <pre> with forbidden attribute values (bug 3202)
-!! input
+!! wikitext
 <pre width="8" style="border-width: expression(alert(document.cookie))">Narrow screen goodies</pre>
-!! result
+!! html
 <pre width="8" style="/* insecure input */">Narrow screen goodies</pre>
 
 !! end
 
 !! test
 <nowiki> inside <pre> (bug 13238)
-!! input
+!! wikitext
 <pre>
 <nowiki>
 </pre>
@@ -1569,7 +1522,7 @@ Entities inside <pre>
 <nowiki></nowiki>
 </pre>
 <pre><nowiki><nowiki></nowiki>Foo<nowiki></nowiki></nowiki></pre>
-!! result
+!! html
 <pre>
 &lt;nowiki&gt;
 </pre>
@@ -1582,7 +1535,7 @@ Entities inside <pre>
 
 !! test
 <nowiki> and <pre> preference (first one wins)
-!! input
+!! wikitext
 <pre>
 <nowiki>
 </pre>
@@ -1596,7 +1549,7 @@ Entities inside <pre>
 </nowiki>
 </pre>
 
-!! result
+!! html
 <pre>
 &lt;nowiki&gt;
 </pre>
@@ -1613,23 +1566,23 @@ Entities inside <pre>
 
 !! test
 </pre> inside nowiki
-!! input
+!! wikitext
 <nowiki></pre></nowiki>
-!! result
+!! html
 <p>&lt;/pre&gt;
 </p>
 !! end
 
 !! test
 Empty pre; pre inside other HTML tags (bug 54946)
-!! input
+!! wikitext
 a
 
 <div><pre>
 foo
 </pre></div>
 <pre></pre>
-!! result
+!! html
 <p>a
 </p>
 <div><pre>
@@ -1641,10 +1594,10 @@ foo
 
 !! test
 HTML pre followed by indent-pre
-!! input
+!! wikitext
 <pre>foo</pre>
  bar
-!! result
+!! html
 <pre>foo</pre>
 <pre>bar
 </pre>
@@ -1654,36 +1607,36 @@ HTML pre followed by indent-pre
 Block tag pre
 !!options
 parsoid
-!!input
+!! wikitext
 <p><pre>foo</pre></p>
-!!result
+!! html
 <p data-parsoid='{"stx":"html","autoInsertedEnd":true}'></p><pre data-parsoid='{"stx":"html"}'>foo</pre><p data-parsoid='{"autoInsertedStart":true,"stx":"html"}'></p>
 !!end
 
 !!test
 Templates: Indent-Pre: 1a. Templates that break a line should suppress <pre>
-!!input
+!! wikitext
  {{echo|}}
-!!result
+!! html
 
 !!end
 
 !!test
 Templates: Indent-Pre: 1b. Templates that break a line should suppress <pre>
-!!input
+!! wikitext
  {{echo|
 foo}}
-!!result
+!! html
 <p>foo
 </p>
 !!end
 
 !! test
 Templates: Indent-Pre: 1c: Wrapping should be based on expanded content
-!! input
+!! wikitext
  {{echo|a
 b}}
-!!result
+!! html
 <pre>a
 </pre>
 <p>b
@@ -1692,14 +1645,14 @@ b}}
 
 !! test
 Templates: Indent-Pre: 1d: Wrapping should be based on expanded content
-!! input
+!! wikitext
  {{echo|a
 b
 c
  d
 e
 }}
-!!result
+!! html
 <pre>a
 </pre>
 <p>b
@@ -1713,7 +1666,7 @@ c
 
 !!test
 Templates: Indent-Pre: 1e. Wrapping should be based on expanded content
-!!input
+!! wikitext
 {{echo| foo}}
 
 {{echo| foo}}{{echo| bar}}
@@ -1726,7 +1679,7 @@ Templates: Indent-Pre: 1e. Wrapping should be based on expanded content
 <!--cmt-->{{echo| foo}}
 
 {{echo|{{echo| }}bar}}
-!!result
+!! html
 <pre>foo
 </pre>
 <pre>foo bar
@@ -1744,7 +1697,7 @@ bar
 
 !! test
 Templates: Indent-Pre: 1f: Wrapping should be based on expanded content
-!! input
+!! wikitext
 {{echo| }}a
 
 {{echo|
@@ -1758,7 +1711,7 @@ Templates: Indent-Pre: 1f: Wrapping should be based on expanded content
 
 {{echo|a
 }} b
-!!result
+!! html
 <pre>a
 </pre>
 <p><br />
@@ -1781,9 +1734,9 @@ Templates: Indent-Pre: 1f: Wrapping should be based on expanded content
 
 !! test
 Things that look like <pre> tags aren't treated as such
-!! input
+!! wikitext
 Barack Obama <President> of the United States
-!! result
+!! html
 <p>Barack Obama &lt;President&gt; of the United States
 </p>
 !! end
@@ -1792,9 +1745,9 @@ Barack Obama <President> of the United States
 Parsoid: handle pre with space after attribute
 !! options
 parsoid=wt2html
-!! input
+!! wikitext
 <pre style="width:50%;" >{{echo|foo}}</pre>
-!! result
+!! html
 <pre style="width:50%;">{{echo|foo}}</pre>
 !! end
 
@@ -1803,7 +1756,7 @@ parsoid=wt2html
 Parsoid: Don't paragraph-wrap fosterable content
 !! options
 parsoid=wt2html
-!! input
+!! wikitext
 {|
 <td></td>
 <td></td>
@@ -1811,7 +1764,7 @@ parsoid=wt2html
 
 
 |}
-!! result
+!! html
 <table>
 
 <tbody>
@@ -1829,7 +1782,7 @@ parsoid=wt2html
 Parsoid: Don't paragraph-wrap fosterable content even if table syntax is unbalanced
 !! options
 parsoid=wt2html
-!! input
+!! wikitext
 {|
 <td>
 <td>
@@ -1838,7 +1791,7 @@ parsoid=wt2html
 
 
 |}
-!! result
+!! html
 <table>
 
 <tbody>
@@ -1860,7 +1813,7 @@ parsoid=wt2html
 #--------------------------------------------------------------------
 !! test
 Templates: Strip leading and trailing whitespace from named-param values
-!! input
+!! wikitext
 {{echo|1= a }}
 
 {{echo|1= {{echo|b}} }}
@@ -1871,7 +1824,7 @@ Templates: Strip leading and trailing whitespace from named-param values
 {{echo| 1 =
 * d
 }}
-!! result
+!! html
 <p>a
 </p><p>b
 </p><p>c
@@ -1885,7 +1838,7 @@ Templates: Strip leading and trailing whitespace from named-param values
 
 !! test
 Templates: Don't strip whitespace from positional-param values
-!! input
+!! wikitext
 {{echo|a }}
 
 {{echo|{{echo|b}} }}
@@ -1904,7 +1857,7 @@ Templates: Don't strip whitespace from positional-param values
 
 {{echo|
  }}g
-!! result
+!! html
 <p>a 
 </p><p>b 
 </p>
@@ -1932,12 +1885,12 @@ Templates: Don't strip whitespace from positional-param values
 
 !! test
 Templates: Handle empty comment-and-ws-only lines correctly
-!! input
+!! wikitext
 {{echo|foo
 <!--should be ignored-->
  <!--should be ignored as well-->
 bar}}
-!! result
+!! html
 <p>foo
 bar
 </p>
@@ -1950,9 +1903,9 @@ bar
 Templates: Parsoid parameter escaping test 1
 !! options
 parsoid
-!! input
+!! wikitext
 {{echo|[foo]|{{echo|[bar]}}}}
-!! result
+!! html
 <p about="#mwt1" typeof="mw:Transclusion"
 data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"[foo]"},"2":{"wt":"{{echo|[bar]}}"}},"i":0}}]}'>[foo]</p>
 !! end
@@ -1961,9 +1914,9 @@ data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},
 Parsoid: Pipes in external links in template parameter
 !! options
 parsoid
-!! input
+!! wikitext
 {{echo|[{{echo|http://example.com}} link]}}
-!! result
+!! html
 <p><a rel="mw:ExtLink" href="http://example.com" about="#mwt31" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"[{{echo|http://example.com}} link]"}},"i":0}}]}'>link</a></p>
 !! end
 
@@ -1971,9 +1924,9 @@ parsoid
 Parsoid: pipe in transclusion parameter
 !! options
 parsoid
-!! input
+!! wikitext
 {{echo|http://foo.com/a&#124;b}}
-!! result
+!! html
 <p><a rel="mw:ExtLink" href="http://foo.com/a|b" about="#mwt1"
 typeof="mw:Transclusion"
 data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"http://foo.com/a&amp;#124;b"}},"i":0}}]}'>http://foo.com/a|b</a></p>
@@ -1983,9 +1936,9 @@ data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},
 Parsoid: Pipe in external link target and content in template parameter
 !! options
 parsoid=html2wt,wt2wt
-!! input
+!! wikitext
 {{echo|[http://foo.com/a&#124;b a&#124;b]}}
-!! result
+!! html
 <p><a rel="mw:ExtLink" href="http://foo.com/a|b" about="#mwt1"
 typeof="mw:Transclusion"
 data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},
@@ -1996,11 +1949,11 @@ data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},
 Templates: Don't escape already nowiki-escaped text in template parameters
 !! options
 parsoid=html2wt,wt2wt
-!! input
+!! wikitext
 {{echo|foo<nowiki>|</nowiki>bar}}
 {{echo|<nowiki>&lt;div&gt;</nowiki>}}
 {{echo|<nowiki></nowiki>}}
-!! result
+!! html
 <p><span about="#mwt1" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"foo<nowiki>|</nowiki>bar"}},"i":0}}]}'}'>foo</span><span typeof="mw:Nowiki" about="#mwt1">|</span><span about="#mwt1">bar</span>
 <span typeof="mw:Transclusion mw:Nowiki" about="#mwt2" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"<nowiki>&amp;lt;div&amp;gt;</nowiki>"}},"i":0}}]}'><span typeof="mw:Entity">&lt;</span>div<span typeof="mw:Entity">&gt;</span></span>
 <span typeof="mw:Transclusion mw:Nowiki" about="#mwt3" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"<nowiki></nowiki>"}},"i":0}}]}'></span>
@@ -2012,9 +1965,9 @@ parsoid=html2wt,wt2wt
 Templates: '=' char in nested transclusions should not trigger nowiki escapes or conversion to named param
 !! options
 parsoid=html2wt,wt2wt
-!! input
+!! wikitext
 {{echo|{{echo|1=bar}}}}
-!! result
+!! html
 <p about="#mwt1" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"{{echo|1=bar}}"}},"i":0}}]}'>bar</p>
 !! end
 
@@ -2023,9 +1976,9 @@ parsoid=html2wt,wt2wt
 Templates parameters with special tokenizing behavior dont get modified because of arg escaping
 !! options
 parsoid
-!! input
+!! wikitext
 {{echo|a : b}}
-!! result
+!! html
 <p about="#mwt1" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"a : b"}},"i":0}}]}'>a<span typeof="mw:Placeholder" data-parsoid='{"isDisplayHack":true}'> </span>: b</p>
 !! end
 
@@ -2035,11 +1988,11 @@ parsoid
 
 !!test
 1a. Indent-Pre and Comments
-!!input
+!! wikitext
  a
 <!--a-->
 c
-!!result
+!! html
 <pre>a
 </pre>
 <p>c
 
 !!test
 1b. Indent-Pre and Comments
-!!input
+!! wikitext
  a
  <!--a-->
 c
-!!result
+!! html
 <pre>a
 </pre>
 <p>c
 
 !!test
 1c. Indent-Pre and Comments
-!!input
+!! wikitext
 <!--a-->  a
 
  <!--a--> a
-!!result
+!! html
 <pre> a
 </pre>
 <pre> a
 !!test
 1d. Indent-Pre and Comments
 (Pre-handler currently cannot distinguish between comment/ws order and normalizes them to [comment,ws] order)
-!!input
+!! wikitext
 <!--a--> a
 
  <!--b-->b
-!!result
+!! html
 <pre>a
 </pre>
 <pre>b
 
 !!test
 2a. Indent-Pre and tables
-!!input
+!! wikitext
  {|
  |-
  !h1!!h2
  |foo||bar
  |}
-!!result
+!! html
 <table>
 
 <tr>
 
 !!test
 2b. Indent-Pre and tables
-!!input
+!! wikitext
   {|
  |-
 |foo
 |}
-!!result
+!! html
 <table>
 
 <tr>
 
 !!test
 2c. Indent-Pre and tables (bug 42252)
-!!input
+!! wikitext
 {|
  |+ foo
  !  | bar
 |}
-!!result
+!! html
 <table>
 <caption> foo
 </caption>
 
 !!test
 3a. Indent-Pre and block tags (single-line html)
-!!input
+!! wikitext
  a <p> foo </p>
  b <div> foo </div>
  c <blockquote> foo </blockquote>
  <span> foo </span>
-!!result
+!! html
  a <p> foo </p>
  b <div> foo </div>
  c <blockquote> foo </blockquote>
 
 !!test
 3b. Indent-Pre and block tags (multi-line html)
-!!input
+!! wikitext
  a <span>foo</span>
  b <div> foo </div>
-!!result
+!! html
 <pre>a <span>foo</span>
 </pre>
  b <div> foo </div>
@@ -2169,7 +2122,7 @@ c
 
 !!test
 3c. Indent-Pre and block tags (pre-content on separate line)
-!!input
+!! wikitext
 <p>
  foo
 </p>
@@ -2200,7 +2153,7 @@ foo
   foo
 </li></ul>
 
-!!result
+!! html
 <p>
  foo
 </p>
@@ -2233,11 +2186,11 @@ foo
 
 !!test
 4. Indent-Pre and extension tags
-!!input
+!! wikitext
  a <gallery>
 File:foobar.jpg
 </gallery>
-!!result
+!! html
  a <ul class="gallery mw-gallery-traditional">
                <li class="gallerybox" style="width: 155px"><div style="width: 155px">
                        <div class="thumb" style="width: 150px;"><div style="margin:68px auto;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" width="120" height="14" /></a></div></div>
@@ -2252,9 +2205,9 @@ File:foobar.jpg
 Leading pipes outside of tables
 !! options
 parsoid
-!! input
+!! wikitext
 | foo
-!! result
+!! html
 <p>| foo</p>
 !! end
 
@@ -2262,11 +2215,11 @@ parsoid
 Leading pipes outside of tables 2
 !! options
 parsoid
-!! input
+!! wikitext
 a
 | foo
 b
-!! result
+!! html
 <p>a
 | foo
 b</p>
@@ -2276,11 +2229,11 @@ b</p>
 Leading pipes outside of tables 3
 !! options
 parsoid
-!! input
+!! wikitext
 a
 | class="foo bar" | baz
 b
-!! result
+!! html
 <p>a
 | class="foo bar" | baz
 b</p>
@@ -2288,13 +2241,13 @@ b</p>
 
 !!test
 Render paragraphs when indent-pre is suppressed in blocklevels
-!!input
+!! wikitext
 <blockquote>
  foo
 
  bar
 </blockquote>
-!! result
+!! html
 <blockquote>
 <p> foo
 </p><p> bar
@@ -2305,13 +2258,13 @@ Render paragraphs when indent-pre is suppressed in blocklevels
 
 !!test
 4. Multiple spaces at start-of-line
-!!input
+!! wikitext
     <p> foo </p>
     foo
        {|
 |foo
 |}
-!!result
+!! html
     <p> foo </p>
 <pre>   foo
 </pre>
@@ -2325,11 +2278,11 @@ Render paragraphs when indent-pre is suppressed in blocklevels
 ## NOTE: the leading white-space chars on empty line are significant
 !! test
 5a. White-space in indent-pre
-!! input
+!! wikitext
  a<br />
  
  b
-!! result
+!! html
 <pre>a<br />
 
 b
 ## NOTE: the leading white-space chars on empty line are significant
 !! test
 5b. White-space in indent-pre
-!! input
+!! wikitext
  a
  
  b
  
  
  c
-!! result
+!! html
 <pre>a
 
 b
 
 !! test
 5c. White-space in indent-pre
-!! input
+!! wikitext
  ''a''
   ''b''
    ''c''
-!! result
+!! html
 <pre><i>a</i>
  <i>b</i>
   <i>c</i>
@@ -2371,7 +2324,7 @@ c
 
 !! test
 6. Pre-blocks should extend across lines with leading WS even when there is no wrappable content
-!! input
+!! wikitext
  a
  
  <!-- continue -->
@@ -2380,7 +2333,7 @@ c
  c
  
 d
-!! result
+!! html
 <pre>a
 
 b
 7a. Indent-pre and category links
 !! options
 parsoid=wt2html,wt2wt
-!! input
+!! wikitext
  [[Category:foo]] <!-- No pre-wrapping -->
 {{echo| [[Category:foo]]}} <!-- No pre-wrapping -->
-!! result
+!! html
  <link rel="mw:PageProp/Category" href="./Category:Foo"> <!-- No pre-wrapping -->
 <span about="#mwt1" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":" [[Category:foo]]"}},"i":0}}]}'> </span>
 <link rel="mw:PageProp/Category" href="./Category:Foo" about="#mwt1"> <!-- No pre-wrapping -->
@@ -2409,10 +2362,10 @@ parsoid=wt2html,wt2wt
 7b. Indent-pre and category links
 !! options
 parsoid=wt2html,wt2wt
-!! input
+!! wikitext
  [[Category:foo]] a
  [[Category:foo]] {{echo|b}}
-!! result
+!! html
 <pre>
 <link rel="mw:PageProp/Category" href="./Category:Foo"> a
 
@@ -2425,7 +2378,7 @@ parsoid=wt2html,wt2wt
 
 !!test
 HTML-pre: 1. embedded newlines
-!!input
+!! wikitext
 <pre>foo</pre>
 
 <pre>
@@ -2442,7 +2395,7 @@ foo
 
 foo
 </pre>
-!!result
+!! html
 <pre>foo</pre>
 <pre>
 foo
@@ -2461,11 +2414,11 @@ foo
 
 !!test
 HTML-pre: 2: indented text
-!!input
+!! wikitext
 <pre>
  foo
 </pre>
-!!result
+!! html
 <pre>
  foo
 </pre>
@@ -2474,7 +2427,7 @@ HTML-pre: 2: indented text
 
 !!test
 HTML-pre: 3: other wikitext
-!!input
+!! wikitext
 <pre>
 * foo
 # bar
@@ -2482,7 +2435,7 @@ HTML-pre: 3: other wikitext
 '' no-italic ''
 [[ NoLink ]]
 </pre>
-!!result
+!! html
 <pre>
 * foo
 # bar
@@ -2498,9 +2451,9 @@ HTML-pre: 3: other wikitext
 ###
 !! test
 Simple definition
-!! input
+!! wikitext
 ; name : Definition
-!! result
+!! html
 <dl>
 <dt> name&#160;</dt>
 <dd> Definition
@@ -2511,9 +2464,9 @@ Simple definition
 
 !! test
 Definition list for indentation only
-!! input
+!! wikitext
 : Indented text
-!! result
+!! html
 <dl>
 <dd> Indented text
 </dd>
@@ -2523,9 +2476,9 @@ Definition list for indentation only
 
 !! test
 Definition list with no space
-!! input
+!! wikitext
 ;name:Definition
-!! result
+!! html
 <dl>
 <dt>name</dt>
 <dd>Definition
@@ -2536,9 +2489,9 @@ Definition list with no space
 
 !! test
 Definition list with URL link
-!! input
+!! wikitext
 ; http://example.com/ : definition
-!! result
+!! html
 <dl>
 <dt> <a rel="nofollow" class="external free" href="http://example.com/">http://example.com/</a>&#160;</dt>
 <dd> definition
@@ -2549,9 +2502,9 @@ Definition list with URL link
 
 !! test
 Definition list with bracketed URL link
-!! input
+!! wikitext
 ;[http://www.example.com/ Example]:Something about it
-!! result
+!! html
 <dl>
 <dt><a rel="nofollow" class="external text" href="http://www.example.com/">Example</a></dt>
 <dd>Something about it
@@ -2562,9 +2515,9 @@ Definition list with bracketed URL link
 
 !! test
 Definition list with wikilink containing colon
-!! input
+!! wikitext
 ; [[Help:FAQ]]: The least-read page on Wikipedia
-!! result
+!! html
 <dl>
 <dt> <a href="/index.php?title=Help:FAQ&amp;action=edit&amp;redlink=1" class="new" title="Help:FAQ (page does not exist)">Help:FAQ</a></dt>
 <dd> The least-read page on Wikipedia
@@ -2576,9 +2529,9 @@ Definition list with wikilink containing colon
 # At Brion's and JeLuF's insistence... :)
 !! test
 Definition list with news link containing colon
-!! input
+!! wikitext
 ;  news:alt.wikipedia.rox: This isn't even a real newsgroup!
-!! result
+!! html
 <dl>
 <dt>  <a rel="nofollow" class="external free" href="news:alt.wikipedia.rox">news:alt.wikipedia.rox</a></dt>
 <dd> This isn't even a real newsgroup!
@@ -2589,9 +2542,9 @@ Definition list with news link containing colon
 
 !! test
 Malformed definition list with colon
-!! input
+!! wikitext
 ;  news:alt.wikipedia.rox -- don't crash or enter an infinite loop
-!! result
+!! html
 <dl>
 <dt>  <a rel="nofollow" class="external free" href="news:alt.wikipedia.rox">news:alt.wikipedia.rox</a> -- don't crash or enter an infinite loop
 </dt>
@@ -2601,9 +2554,9 @@ Malformed definition list with colon
 
 !! test
 Definition lists: colon in external link text
-!! input
+!! wikitext
 ; [http://www.wikipedia2.org/ Wikipedia : The Next Generation]: OK, I made that up
-!! result
+!! html
 <dl>
 <dt> <a rel="nofollow" class="external text" href="http://www.wikipedia2.org/">Wikipedia&#160;: The Next Generation</a></dt>
 <dd> OK, I made that up
@@ -2614,9 +2567,9 @@ Definition lists: colon in external link text
 
 !! test
 Definition lists: colon in HTML attribute
-!! input
+!! wikitext
 ;<b style="display: inline">bold</b>
-!! result
+!! html
 <dl>
 <dt><b style="display: inline">bold</b>
 </dt>
@@ -2626,9 +2579,9 @@ Definition lists: colon in HTML attribute
 
 !! test
 Definition lists: self-closed tag
-!! input
+!! wikitext
 ;one<br/>two : two-line fun
-!! result
+!! html
 <dl>
 <dt>one<br />two&#160;</dt>
 <dd> two-line fun
@@ -2639,14 +2592,14 @@ Definition lists: self-closed tag
 
 !! test
 Bug 11748: Literal closing tags
-!! input
+!! wikitext
 <dl>
 <dt>test 1</dt>
 <dd>test test test test test</dd>
 <dt>test 2</dt>
 <dd>test test test test test</dd>
 </dl>
-!! result
+!! html
 <dl>
 <dt>test 1</dt>
 <dd>test test test test test</dd>
@@ -2658,12 +2611,12 @@ Bug 11748: Literal closing tags
 
 !! test
 Definition and unordered list using wiki syntax nested in unordered list using html tags.
-!! input
+!! wikitext
 <ul><li>
 ; term : description
 * unordered
 </li></ul>
-!! result
+!! html
 <ul><li>
 <dl>
 <dt> term&#160;</dt>
@@ -2681,10 +2634,10 @@ Definition and unordered list using wiki syntax nested in unordered list using h
 !! test
 
 Definition list with empty definition and following paragraph
-!! input
+!! wikitext
 ; term:
 Paragraph text
-!! result
+!! html
 <dl>
 <dt> term</dt>
 <dd>
@@ -2696,13 +2649,13 @@ Paragraph text
 
 !! test
 Nested definition lists using html syntax
-!! input
+!! wikitext
 <dl><dd>
 <dl>
 <dd>Foo</dd>
 </dl>
 </dd></dl>
-!! result
+!! html
 <dl><dd>
 <dl>
 <dd>Foo</dd>
@@ -2713,11 +2666,11 @@ Nested definition lists using html syntax
 
 !! test
 Definition Lists: No nesting: Multiple dd's
-!! input
+!! wikitext
 ;x
 :a
 :b
-!! result
+!! html
 <dl>
 <dt>x
 </dt>
@@ -2731,11 +2684,11 @@ Definition Lists: No nesting: Multiple dd's
 
 !! test
 Definition Lists: Indentation: Regular
-!! input
+!! wikitext
 :i1
 ::i2
 :::i3
-!! result
+!! html
 <dl>
 <dd>i1
 <dl>
@@ -2753,10 +2706,10 @@ Definition Lists: Indentation: Regular
 
 !! test
 Definition Lists: Indentation: Missing 1st level
-!! input
+!! wikitext
 ::i2
 :::i3
-!! result
+!! html
 <dl>
 <dd><dl>
 <dd>i2
@@ -2773,9 +2726,9 @@ Definition Lists: Indentation: Missing 1st level
 
 !! test
 Definition Lists: Indentation: Multi-level indent
-!! input
+!! wikitext
 :::i3
-!! result
+!! html
 <dl>
 <dd><dl>
 <dd><dl>
@@ -2791,14 +2744,14 @@ Definition Lists: Indentation: Multi-level indent
 
 !! test
 Definition Lists: Hacky use to indent tables
-!! input
+!! wikitext
 ::{|
 |foo
 |bar
 |}
 this text
 should be left alone
-!! result
+!! html
 <dl><dd><dl><dd><table>
 <tr>
 <td>foo
@@ -2815,11 +2768,11 @@ should be left alone
 Definition Lists: Hacky use to indent tables (WS-insensitive)
 !! options
 parsoid
-!! input
+!! wikitext
 : {|
 |a
 |} 
-!! result
+!! html
 <dl>
 <dd> <table><tr><td>a</td></tr></table> </dd>
 </dl>
@@ -2861,7 +2814,7 @@ parsoid
 
 !! test
 Table / list interaction: indented table with lists in table contents
-!! input
+!! wikitext
 :{|
 |-
 | a
@@ -2870,7 +2823,7 @@ Table / list interaction: indented table with lists in table contents
 | c
 * d
 |}
-!! result
+!! html
 <dl><dd><table>
 
 <tr>
@@ -2892,7 +2845,7 @@ Table / list interaction: indented table with lists in table contents
 
 !!test
 Table / list interaction: lists nested in tables nested in indented lists
-!!input
+!! wikitext
 :{|
 |
 :a
@@ -2904,7 +2857,7 @@ Table / list interaction: lists nested in tables nested in indented lists
 
 *e
 *f
-!!result
+!! html
 <dl><dd><table>
 <tr>
 <td>
@@ -2936,11 +2889,11 @@ Table / list interaction: lists nested in tables nested in indented lists
 Definition Lists: Nesting: Multi-level (Parsoid only)
 !! options
 parsoid
-!! input
+!! wikitext
 ;t1 :d1
 ;;t2 ::d2
 ;;;t3 :::d3
-!! result
+!! html
 <dl>
   <dt>t1 </dt>
   <dd>d1</dd>
@@ -2966,10 +2919,10 @@ parsoid
 Definition Lists: Nesting: Test 2 (Parsoid only)
 !! options
 parsoid
-!! input
+!! wikitext
 ;t1
 ::d2
-!! result
+!! html
 <dl>
   <dt>t1</dt>
   <dd>
@@ -2986,10 +2939,10 @@ parsoid
 Definition Lists: Nesting: Test 3 (Parsoid only)
 !! options
 parsoid
-!! input
+!! wikitext
 :;t1
 ::::d2
-!! result
+!! html
 <dl>
   <dd>
     <dl>
@@ -3012,10 +2965,10 @@ parsoid
 
 !! test
 Definition Lists: Nesting: Test 4
-!! input
+!! wikitext
 ::;t3
 :::d3
-!! result
+!! html
 <dl>
 <dd><dl>
 <dd><dl>
@@ -3036,14 +2989,12 @@ Definition Lists: Nesting: Test 4
 ## bug in the PHP parser.  (Parsoid team thinks the PHP parser is
 ## wrong to close the <dl> after the <dt> containing the <ul>.)
 !! test
-Definition Lists: Mixed Lists: Test 1 (php)
-!! options
-php
-!! input
+Definition Lists: Mixed Lists: Test 1
+!! wikitext
 :;* foo
 ::* bar
 :; baz
-!! result
+!! html/php
 <dl>
 <dd><dl>
 <dt><ul>
@@ -3061,16 +3012,7 @@ php
 </dd>
 </dl>
 
-!! end
-!! test
-Definition Lists: Mixed Lists: Test 1 (parsoid)
-!! options
-parsoid
-!! input
-:;* foo
-::* bar
-:; baz
-!! result
+!! html/parsoid
 <dl>
 <dd><dl>
 <dt><ul>
@@ -3088,10 +3030,10 @@ parsoid
 
 !! test
 Definition Lists: Mixed Lists: Test 2
-!! input
+!! wikitext
 *: d1
 *: d2
-!! result
+!! html
 <ul>
 <li><dl>
 <dd> d1
@@ -3107,10 +3049,10 @@ Definition Lists: Mixed Lists: Test 2
 
 !! test
 Definition Lists: Mixed Lists: Test 3
-!! input
+!! wikitext
 *::: d1
 *::: d2
-!! result
+!! html
 <ul>
 <li><dl>
 <dd><dl>
@@ -3132,10 +3074,10 @@ Definition Lists: Mixed Lists: Test 3
 
 !! test
 Definition Lists: Mixed Lists: Test 4
-!! input
+!! wikitext
 *;d1 :d2
 *;d3 :d4
-!! result
+!! html
 <ul>
 <li><dl>
 <dt>d1&#160;</dt>
@@ -3153,10 +3095,10 @@ Definition Lists: Mixed Lists: Test 4
 
 !! test
 Definition Lists: Mixed Lists: Test 5
-!! input
+!! wikitext
 *:d1
 *:: d2
-!! result
+!! html
 <ul>
 <li><dl>
 <dd>d1
@@ -3174,10 +3116,10 @@ Definition Lists: Mixed Lists: Test 5
 
 !! test
 Definition Lists: Mixed Lists: Test 6
-!! input
+!! wikitext
 #*:d1
 #*::: d3
-!! result
+!! html
 <ol>
 <li><ul>
 <li><dl>
@@ -3201,10 +3143,10 @@ Definition Lists: Mixed Lists: Test 6
 
 !! test
 Definition Lists: Mixed Lists: Test 7
-!! input
+!! wikitext
 :* d1
 :* d2
-!! result
+!! html
 <dl>
 <dd><ul>
 <li> d1
@@ -3220,10 +3162,10 @@ Definition Lists: Mixed Lists: Test 7
 
 !! test
 Definition Lists: Mixed Lists: Test 8
-!! input
+!! wikitext
 :* d1
 ::* d2
-!! result
+!! html
 <dl>
 <dd><ul>
 <li> d1
@@ -3244,9 +3186,9 @@ Definition Lists: Mixed Lists: Test 8
 
 !! test
 Definition Lists: Mixed Lists: Test 9
-!! input
+!! wikitext
 *;foo :bar
-!! result
+!! html
 <ul>
 <li><dl>
 <dt>foo&#160;</dt>
@@ -3261,9 +3203,9 @@ Definition Lists: Mixed Lists: Test 9
 
 !! test
 Definition Lists: Mixed Lists: Test 10
-!! input
+!! wikitext
 *#;foo :bar
-!! result
+!! html
 <ul>
 <li><ol>
 <li><dl>
@@ -3284,13 +3226,11 @@ Definition Lists: Mixed Lists: Test 10
 # still-open tags around until the nesting is complete.
 
 !! test
-Definition Lists: Mixed Lists: Test 11 (php)
-!! options
-php
-!! input
+Definition Lists: Mixed Lists: Test 11
+!! wikitext
 *#*#;*;;foo :bar
 *#*#;boo :baz
-!! result
+!! html/php
 <ul>
 <li><ol>
 <li><ul>
@@ -3323,15 +3263,7 @@ php
 </li>
 </ul>
 
-!! end
-!! test
-Definition Lists: Mixed Lists: Test 11 (parsoid)
-!! options
-parsoid
-!! input
-*#*#;*;;foo :bar
-*#*#;boo :baz
-!! result
+!! html/parsoid
 <ul>
 <li>
 <ol>
@@ -3363,12 +3295,10 @@ parsoid
 
 
 !! test
-Definition Lists: Weird Ones: Test 1 (php)
-!! options
-php
-!! input
+Definition Lists: Weird Ones: Test 1
+!! wikitext
 *#;*::;; foo : bar (who uses this?)
-!! result
+!! html/php
 <ul>
 <li><ol>
 <li><dl>
@@ -3396,14 +3326,7 @@ php
 </li>
 </ul>
 
-!! end
-!! test
-Definition Lists: Weird Ones: Test 1 (parsoid)
-!! options
-parsoid
-!! input
-*#;*::;; foo : bar (who uses this?)
-!! result
+!! html/parsoid
 <ul>
 <li>
 <ol>
@@ -3436,20 +3359,20 @@ parsoid
 ###
 !! test
 External links: non-bracketed
-!! input
+!! wikitext
 Non-bracketed: http://example.com
-!! result
+!! html
 <p>Non-bracketed: <a rel="nofollow" class="external free" href="http://example.com">http://example.com</a>
 </p>
 !! end
 
 !! test
 External links: numbered
-!! input
+!! wikitext
 Numbered: [http://example.com]
 Numbered: [http://example.net]
 Numbered: [http://example.com]
-!! result
+!! html
 <p>Numbered: <a rel="nofollow" class="external autonumber" href="http://example.com">[1]</a>
 Numbered: <a rel="nofollow" class="external autonumber" href="http://example.net">[2]</a>
 Numbered: <a rel="nofollow" class="external autonumber" href="http://example.com">[3]</a>
@@ -3458,73 +3381,73 @@ Numbered: <a rel="nofollow" class="external autonumber" href="http://example.com
 
 !! test
 External links: specified text
-!! input
+!! wikitext
 Specified text: [http://example.com link]
-!! result
+!! html
 <p>Specified text: <a rel="nofollow" class="external text" href="http://example.com">link</a>
 </p>
 !!end
 
 !! test
 External links: trail
-!! input
+!! wikitext
 Linktrails should not work for external links: [http://example.com link]s
-!! result
+!! html
 <p>Linktrails should not work for external links: <a rel="nofollow" class="external text" href="http://example.com">link</a>s
 </p>
 !! end
 
 !! test
 External links: dollar sign in URL
-!! input
+!! wikitext
 http://example.com/1$2345
-!! result
+!! html
 <p><a rel="nofollow" class="external free" href="http://example.com/1$2345">http://example.com/1$2345</a>
 </p>
 !! end
 
 !! test
 External links: dollar sign in URL (named)
-!! input
+!! wikitext
 [http://example.com/1$2345]
-!! result
+!! html
 <p><a rel="nofollow" class="external autonumber" href="http://example.com/1$2345">[1]</a>
 </p>
 !!end
 
 !! test
 External links: open square bracket forbidden in URL (bug 4377)
-!! input
+!! wikitext
 http://example.com/1[2345
-!! result
+!! html
 <p><a rel="nofollow" class="external free" href="http://example.com/1">http://example.com/1</a>[2345
 </p>
 !! end
 
 !! test
 External links: open square bracket forbidden in URL (named) (bug 4377)
-!! input
+!! wikitext
 [http://example.com/1[2345]
-!! result
+!! html
 <p><a rel="nofollow" class="external text" href="http://example.com/1">[2345</a>
 </p>
 !!end
 
 !! test
 External links: nowiki in URL link text (bug 6230)
-!!input
+!! wikitext
 [http://example.com/ <nowiki>''example site''</nowiki>]
-!! result
+!! html
 <p><a rel="nofollow" class="external text" href="http://example.com/">''example site''</a>
 </p>
 !! end
 
 !! test
 External links: newline forbidden in text (bug 6230 regression check)
-!! input
+!! wikitext
 [http://example.com/ first
 second]
-!! result
+!! html
 <p>[<a rel="nofollow" class="external free" href="http://example.com/">http://example.com/</a> first
 second]
 </p>
@@ -3532,63 +3455,63 @@ second]
 
 !! test
 External links: Pipe char between url and text
-!! input
+!! wikitext
 [http://example.com | link]
-!! result
+!! html
 <p><a rel="nofollow" class="external text" href="http://example.com">| link</a>
 </p>
 !!end
 
 !! test
 External links: protocol-relative URL in brackets
-!! input
+!! wikitext
 [//example.com/ Test]
-!! result
+!! html
 <p><a rel="nofollow" class="external text" href="//example.com/">Test</a>
 </p>
 !! end
 
 !! test
 External links: protocol-relative URL in brackets without text
-!! input
+!! wikitext
 [//example.com]
-!! result
+!! html
 <p><a rel="nofollow" class="external autonumber" href="//example.com">[1]</a>
 </p>
 !! end
 
 !! test
 External links: protocol-relative URL in free text is left alone
-!! input
+!! wikitext
 //example.com/Foo
-!! result
+!! html
 <p>//example.com/Foo
 </p>
 !!end
 
 !! test
 External links: protocol-relative URL in the middle of a word is left alone (bug 30269)
-!! input
+!! wikitext
 foo//example.com/Foo
-!! result
+!! html
 <p>foo//example.com/Foo
 </p>
 !! end
 
 !! test
 External image
-!! input
+!! wikitext
 External image: http://meta.wikimedia.org/upload/f/f1/Ncwikicol.png
-!! result
+!! html
 <p>External image: <img src="http://meta.wikimedia.org/upload/f/f1/Ncwikicol.png" alt="Ncwikicol.png" />
 </p>
 !! end
 
 !! test
 External image from https
-!! input
+!! wikitext
 External image from https: https://meta.wikimedia.org/upload/f/f1/Ncwikicol.png
-!! result
+!! html
 <p>External image from https: <img src="https://meta.wikimedia.org/upload/f/f1/Ncwikicol.png" alt="Ncwikicol.png" />
 </p>
 !! end
@@ -3597,135 +3520,135 @@ External image from https: https://meta.wikimedia.org/upload/f/f1/Ncwikicol.png
 External image (when not allowed)
 !! options
 wgAllowExternalImages=0
-!! input
+!! wikitext
 External image: http://meta.wikimedia.org/upload/f/f1/Ncwikicol.png
-!! result
+!! html
 <p>External image: <a rel="nofollow" class="external free" href="http://meta.wikimedia.org/upload/f/f1/Ncwikicol.png">http://meta.wikimedia.org/upload/f/f1/Ncwikicol.png</a>
 </p>
 !! end
 
 !! test
 Link to non-http image, no img tag
-!! input
+!! wikitext
 Link to non-http image, no img tag: ftp://example.com/test.jpg
-!! result
+!! html
 <p>Link to non-http image, no img tag: <a rel="nofollow" class="external free" href="ftp://example.com/test.jpg">ftp://example.com/test.jpg</a>
 </p>
 !! end
 
 !! test
 External links: terminating separator
-!! input
+!! wikitext
 Terminating separator: http://example.com/thing,
-!! result
+!! html
 <p>Terminating separator: <a rel="nofollow" class="external free" href="http://example.com/thing">http://example.com/thing</a>,
 </p>
 !! end
 
 !! test
 External links: intervening separator
-!! input
+!! wikitext
 Intervening separator: http://example.com/1,2,3
-!! result
+!! html
 <p>Intervening separator: <a rel="nofollow" class="external free" href="http://example.com/1,2,3">http://example.com/1,2,3</a>
 </p>
 !! end
 
 !! test
 External links: old bug with URL in query
-!! input
+!! wikitext
 Old bug with URL in query: [http://example.com/thing?url=http://example.com link]
-!! result
+!! html
 <p>Old bug with URL in query: <a rel="nofollow" class="external text" href="http://example.com/thing?url=http://example.com">link</a>
 </p>
 !! end
 
 !! test
 External links: old URL-in-URL bug, mixed protocols
-!! input
+!! wikitext
 And again with mixed protocols: [ftp://example.com?url=http://example.com link]
-!! result
+!! html
 <p>And again with mixed protocols: <a rel="nofollow" class="external text" href="ftp://example.com?url=http://example.com">link</a>
 </p>
 !!end
 
 !! test
 External links: URL in text
-!! input
+!! wikitext
 URL in text: [http://example.com http://example.com]
-!! result
+!! html
 <p>URL in text: <a rel="nofollow" class="external free" href="http://example.com">http://example.com</a>
 </p>
 !! end
 
 !! test
 External links: Clickable images
-!! input
+!! wikitext
 ja-style clickable images: [http://example.com http://meta.wikimedia.org/upload/f/f1/Ncwikicol.png]
-!! result
+!! html
 <p>ja-style clickable images: <a rel="nofollow" class="external text" href="http://example.com"><img src="http://meta.wikimedia.org/upload/f/f1/Ncwikicol.png" alt="Ncwikicol.png" /></a>
 </p>
 !!end
 
 !! test
 External links: raw ampersand
-!! input
+!! wikitext
 Old &amp; use: http://x&y
-!! result
+!! html
 <p>Old &amp; use: <a rel="nofollow" class="external free" href="http://x&amp;y">http://x&amp;y</a>
 </p>
 !! end
 
 !! test
 External links: encoded ampersand
-!! input
+!! wikitext
 Old &amp; use: http://x&amp;y
-!! result
+!! html
 <p>Old &amp; use: <a rel="nofollow" class="external free" href="http://x&amp;y">http://x&amp;y</a>
 </p>
 !! end
 
 !! test
 External links: encoded equals (bug 6102)
-!! input
+!! wikitext
 http://example.com/?foo&#61;bar
-!! result
+!! html
 <p><a rel="nofollow" class="external free" href="http://example.com/?foo=bar">http://example.com/?foo=bar</a>
 </p>
 !! end
 
 !! test
 External links: [raw ampersand]
-!! input
+!! wikitext
 Old &amp; use: [http://x&y]
-!! result
+!! html
 <p>Old &amp; use: <a rel="nofollow" class="external autonumber" href="http://x&amp;y">[1]</a>
 </p>
 !! end
 
 !! test
 External links: [encoded ampersand]
-!! input
+!! wikitext
 Old &amp; use: [http://x&amp;y]
-!! result
+!! html
 <p>Old &amp; use: <a rel="nofollow" class="external autonumber" href="http://x&amp;y">[1]</a>
 </p>
 !! end
 
 !! test
 External links: [encoded equals] (bug 6102)
-!! input
+!! wikitext
 [http://example.com/?foo&#61;bar]
-!! result
+!! html
 <p><a rel="nofollow" class="external autonumber" href="http://example.com/?foo=bar">[1]</a>
 </p>
 !! end
 
 !! test
 External links: [IDN ignored character reference in hostname; strip it right off]
-!! input
+!! wikitext
 [http://e&zwnj;xample.com/]
-!! result
+!! html
 <p><a rel="nofollow" class="external autonumber" href="http://example.com/">[1]</a>
 </p>
 !! end
@@ -3749,118 +3672,118 @@ External links: [IDN ignored character reference in hostname; strip it right off
 # The Parsoid team.
 !! test
 External links: IDN ignored character reference in hostname; strip it right off
-!! input
+!! wikitext
 http://e&zwnj;xample.com/
-!! result
+!! html
 <p><a rel="nofollow" class="external free" href="http://example.com/">http://example.com/</a>
 </p>
 !! end
 
 !! test
 External links: www.jpeg.org (bug 554)
-!! input
+!! wikitext
 http://www.jpeg.org
-!!result
+!! html
 <p><a rel="nofollow" class="external free" href="http://www.jpeg.org">http://www.jpeg.org</a>
 </p>
 !! end
 
 !! test
 External links: URL within URL (original bug 2)
-!! input
+!! wikitext
 [http://www.unausa.org/newindex.asp?place=http://www.unausa.org/programs/mun.asp]
-!! result
+!! html
 <p><a rel="nofollow" class="external autonumber" href="http://www.unausa.org/newindex.asp?place=http://www.unausa.org/programs/mun.asp">[1]</a>
 </p>
 !! end
 
 !! test
 BUG 361: URL inside bracketed URL
-!! input
+!! wikitext
 [http://www.example.com/foo http://www.example.com/bar]
-!! result
+!! html
 <p><a rel="nofollow" class="external text" href="http://www.example.com/foo">http://www.example.com/bar</a>
 </p>
 !! end
 
 !! test
 BUG 361: URL within URL, not bracketed
-!! input
+!! wikitext
 http://www.example.com/foo?=http://www.example.com/bar
-!! result
+!! html
 <p><a rel="nofollow" class="external free" href="http://www.example.com/foo?=http://www.example.com/bar">http://www.example.com/foo?=http://www.example.com/bar</a>
 </p>
 !! end
 
 !! test
 BUG 289: ">"-token in URL-tail
-!! input
+!! wikitext
 http://www.example.com/<hello>
-!! result
+!! html
 <p><a rel="nofollow" class="external free" href="http://www.example.com/">http://www.example.com/</a>&lt;hello&gt;
 </p>
 !!end
 
 !! test
 BUG 289: literal ">"-token in URL-tail
-!! input
+!! wikitext
 http://www.example.com/<b>html</b>
-!! result
+!! html
 <p><a rel="nofollow" class="external free" href="http://www.example.com/">http://www.example.com/</a><b>html</b>
 </p>
 !!end
 
 !! test
 BUG 289: ">"-token in bracketed URL
-!! input
+!! wikitext
 [http://www.example.com/<hello> stuff]
-!! result
+!! html
 <p><a rel="nofollow" class="external text" href="http://www.example.com/">&lt;hello&gt; stuff</a>
 </p>
 !!end
 
 !! test
 BUG 289: literal ">"-token in bracketed URL
-!! input
+!! wikitext
 [http://www.example.com/<b>html</b> stuff]
-!! result
+!! html
 <p><a rel="nofollow" class="external text" href="http://www.example.com/"><b>html</b> stuff</a>
 </p>
 !!end
 
 !! test
 BUG 289: literal double quote at end of URL
-!! input
+!! wikitext
 http://www.example.com/"hello"
-!! result
+!! html
 <p><a rel="nofollow" class="external free" href="http://www.example.com/">http://www.example.com/</a>"hello"
 </p>
 !!end
 
 !! test
 BUG 289: literal double quote in bracketed URL
-!! input
+!! wikitext
 [http://www.example.com/"hello" stuff]
-!! result
+!! html
 <p><a rel="nofollow" class="external text" href="http://www.example.com/">"hello" stuff</a>
 </p>
 !!end
 
 !! test
 External links: multiple legal whitespace is fine, Magnus. Don't break it please. (bug 5081)
-!! input
+!! wikitext
 [http://www.example.com  test]
-!! result
+!! html
 <p><a rel="nofollow" class="external text" href="http://www.example.com">test</a>
 </p>
 !! end
 
 !! test
 External links: link text with spaces
-!! input
+!! wikitext
 [http://www.example.com a b c]
 [http://www.example.com ''a'' ''b'']
-!! result
+!! html
 <p><a rel="nofollow" class="external text" href="http://www.example.com">a b c</a>
 <a rel="nofollow" class="external text" href="http://www.example.com"><i>a</i> <i>b</i></a>
 </p>
@@ -3868,32 +3791,22 @@ External links: link text with spaces
 
 !! test
 External links: wiki links within external link (Bug 3695)
-!! options
-php
-!! input
+!! wikitext
 [http://example.com [[wikilink]] embedded in ext link]
-!! result
+!! html/php
 <p><a rel="nofollow" class="external text" href="http://example.com"></a><a href="/index.php?title=Wikilink&amp;action=edit&amp;redlink=1" class="new" title="Wikilink (page does not exist)">wikilink</a><a rel="nofollow" class="external text" href="http://example.com"> embedded in ext link</a>
 </p>
-!! end
-
-!! test
-Parsoid: External links: wiki links within external link (Bug 3695)
-!! options
-parsoid
-!! input
-[http://example.com [[wikilink]] embedded in ext link]
-!! result
+!! html/parsoid
 <p><a rel="mw:ExtLink" href="http://example.com"></a><a rel="mw:WikiLink" href="./Wikilink">wikilink</a><span> embedded in ext link</span></p>
 !! end
 
 !! test
 BUG 787: Links with one slash after the url protocol are invalid
-!! input
+!! wikitext
 http:/example.com
 
 [http:/example.com title]
-!! result
+!! html
 <p>http:/example.com
 </p><p>[http:/example.com title]
 </p>
@@ -3901,22 +3814,22 @@ http:/example.com
 
 !! test
 Bracketed external links with template-generated invalid target
-!! input
+!! wikitext
 [{{echo|http:/example.com}} title]
-!! result
+!! html
 <p>[http:/example.com title]
 </p>
 !! end
 
 !! test
 Bug 2702: Mismatched <i>, <b> and <a> tags are invalid
-!! input
+!! wikitext
 ''[http://example.com text'']
 [http://example.com '''text]'''
 ''Something [http://example.com in italic'']
 ''Something [http://example.com mixed''''', even bold]'''
 '''''Now [http://example.com both''''']
-!! result
+!! html
 <p><a rel="nofollow" class="external text" href="http://example.com"><i>text</i></a>
 <a rel="nofollow" class="external text" href="http://example.com"><b>text</b></a>
 <i>Something </i><a rel="nofollow" class="external text" href="http://example.com"><i>in italic</i></a>
@@ -3928,9 +3841,9 @@ Bug 2702: Mismatched <i>, <b> and <a> tags are invalid
 
 !! test
 Bug 4781: %26 in URL
-!! input
+!! wikitext
 http://www.example.com/?title=AT%26T
-!! result
+!! html
 <p><a rel="nofollow" class="external free" href="http://www.example.com/?title=AT%26T">http://www.example.com/?title=AT%26T</a>
 </p>
 !! end
@@ -3939,18 +3852,18 @@ http://www.example.com/?title=AT%26T
 # % is actually legal in HTML5. Any change in output would need testing though.
 !! test
 Bug 4781, 5267: %25 in URL
-!! input
+!! wikitext
 http://www.example.com/?title=100%25_Bran
-!! result
+!! html
 <p><a rel="nofollow" class="external free" href="http://www.example.com/?title=100%25_Bran">http://www.example.com/?title=100%25_Bran</a>
 </p>
 !! end
 
 !! test
 Bug 4781, 5267: %28, %29 in URL
-!! input
+!! wikitext
 http://www.example.com/?title=Ben-Hur_%281959_film%29
-!! result
+!! html
 <p><a rel="nofollow" class="external free" href="http://www.example.com/?title=Ben-Hur_%281959_film%29">http://www.example.com/?title=Ben-Hur_%281959_film%29</a>
 </p>
 !! end
@@ -3958,27 +3871,27 @@ http://www.example.com/?title=Ben-Hur_%281959_film%29
 
 !! test
 Bug 4781: %26 in autonumber URL
-!! input
+!! wikitext
 [http://www.example.com/?title=AT%26T]
-!! result
+!! html
 <p><a rel="nofollow" class="external autonumber" href="http://www.example.com/?title=AT%26T">[1]</a>
 </p>
 !! end
 
 !! test
 Bug 4781, 5267: %26 in autonumber URL
-!! input
+!! wikitext
 [http://www.example.com/?title=100%25_Bran]
-!! result
+!! html
 <p><a rel="nofollow" class="external autonumber" href="http://www.example.com/?title=100%25_Bran">[1]</a>
 </p>
 !! end
 
 !! test
 Bug 4781, 5267: %28, %29 in autonumber URL
-!! input
+!! wikitext
 [http://www.example.com/?title=Ben-Hur_%281959_film%29]
-!! result
+!! html
 <p><a rel="nofollow" class="external autonumber" href="http://www.example.com/?title=Ben-Hur_%281959_film%29">[1]</a>
 </p>
 !! end
@@ -3986,104 +3899,94 @@ Bug 4781, 5267: %28, %29 in autonumber URL
 
 !! test
 Bug 4781: %26 in bracketed URL
-!! input
+!! wikitext
 [http://www.example.com/?title=AT%26T link]
-!! result
+!! html
 <p><a rel="nofollow" class="external text" href="http://www.example.com/?title=AT%26T">link</a>
 </p>
 !! end
 
 !! test
 Bug 4781, 5267: %26 in bracketed URL
-!! input
+!! wikitext
 [http://www.example.com/?title=100%25_Bran link]
-!! result
+!! html
 <p><a rel="nofollow" class="external text" href="http://www.example.com/?title=100%25_Bran">link</a>
 </p>
 !! end
 
 !! test
 Bug 4781, 5267: %28, %29 in bracketed URL
-!! input
+!! wikitext
 [http://www.example.com/?title=Ben-Hur_%281959_film%29 link]
-!! result
+!! html
 <p><a rel="nofollow" class="external text" href="http://www.example.com/?title=Ben-Hur_%281959_film%29">link</a>
 </p>
 !! end
 
 !! test
 External link containing double-single-quotes in text '' (bug 4598 sanity check)
-!! input
+!! wikitext
 Some [http://example.com/ pretty ''italics'' and stuff]!
-!! result
+!! html
 <p>Some <a rel="nofollow" class="external text" href="http://example.com/">pretty <i>italics</i> and stuff</a>!
 </p>
 !! end
 
 !! test
 External link containing double-single-quotes in text embedded in italics (bug 4598 sanity check)
-!! input
+!! wikitext
 ''Some [http://example.com/ pretty ''italics'' and stuff]!''
-!! result
+!! html
 <p><i>Some </i><a rel="nofollow" class="external text" href="http://example.com/"><i>pretty </i>italics<i> and stuff</i></a><i>!</i>
 </p>
 !! end
 
 !! test
 External link containing double-single-quotes with no space separating the url from text in italics
-!! options
-php
-!! input
+!! wikitext
 [http://www.musee-picasso.fr/pages/page_id18528_u1l2.htm''La muerte de Casagemas'' (1901) en el sitio de [[Museo Picasso (París)|Museo Picasso]].]
-!! result
+!! html/php
 <p><a rel="nofollow" class="external text" href="http://www.musee-picasso.fr/pages/page_id18528_u1l2.htm"><i>La muerte de Casagemas</i> (1901) en el sitio de <a href="/index.php?title=Museo_Picasso_(Par%C3%ADs)&amp;action=edit&amp;redlink=1" class="new" title="Museo Picasso (París) (page does not exist)">Museo Picasso</a>.</a>
 </p>
-!! end
-
-!! test
-Parsoid:External link containing double-single-quotes with no space separating the url from text in italics
-!! options
-parsoid
-!! input
-[http://www.musee-picasso.fr/pages/page_id18528_u1l2.htm''La muerte de Casagemas'' (1901) en el sitio de [[Museo Picasso (París)|Museo Picasso]].]
-!! result
+!! html/parsoid
 <p><a rel="mw:ExtLink" href="http://www.musee-picasso.fr/pages/page_id18528_u1l2.htm"><i>La muerte de Casagemas</i> (1901) en el sitio de </a><a rel="mw:WikiLink" href="./Museo_Picasso_(París)">Museo Picasso</a><span>.</span></p>
 !! end
 
 !! test
 External link with comments in link text
-!! input
+!! wikitext
 [http://www.google.com Google <!-- comment -->]
-!! result
+!! html
 <p><a rel="nofollow" class="external text" href="http://www.google.com">Google </a>
 </p>
 !! end
 
 !! test
 URL-encoding in URL functions (single parameter)
-!! input
+!! wikitext
 {{localurl:Some page|amp=&}}
-!! result
+!! html
 <p>/index.php?title=Some_page&amp;amp=&amp;
 </p>
 !! end
 
 !! test
 URL-encoding in URL functions (multiple parameters)
-!! input
+!! wikitext
 {{localurl:Some page|q=?&amp=&}}
-!! result
+!! html
 <p>/index.php?title=Some_page&amp;q=?&amp;amp=&amp;
 </p>
 !! end
 
 !! test
 Brackets in urls
-!! input
+!! wikitext
 http://example.com/index.php?foozoid%5B%5D=bar
 
 http://example.com/index.php?foozoid&#x5B;&#x5D;=bar
-!! result
+!! html
 <p><a rel="nofollow" class="external free" href="http://example.com/index.php?foozoid%5B%5D=bar">http://example.com/index.php?foozoid%5B%5D=bar</a>
 </p><p><a rel="nofollow" class="external free" href="http://example.com/index.php?foozoid%5B%5D=bar">http://example.com/index.php?foozoid%5B%5D=bar</a>
 </p>
@@ -4093,16 +3996,16 @@ http://example.com/index.php?foozoid&#x5B;&#x5D;=bar
 IPv6 urls (bug 21261)
 !! options
 disabled
-!! input
+!! wikitext
 http://[2404:130:0:1000::187:2]/index.php
-!! result
+!! html
 <p><a rel="nofollow" class="external free" href="http://[2404:130:0:1000::187:2]/index.php">http://[2404:130:0:1000::187:2]/index.php</a>
 </p>
 !! end
 
 !! test
 Non-extlinks in brackets
-!! input
+!! wikitext
 [foo]
 [foo bar]
 [foo ''bar'']
@@ -4115,7 +4018,7 @@ Non-extlinks in brackets
 [{{echo|foo}}l's errand]
 [url={{echo|foo}}]
 [url=http://example.com]
-!! result
+!! html
 <p>[foo]
 [foo bar]
 [foo <i>bar</i>]
@@ -4132,32 +4035,31 @@ Non-extlinks in brackets
 !! end
 
 !! test
-Parsoid: Percent encoding in external links
-!! options
-parsoid
-!! input
+Percent encoding in external links
+!! wikitext
 [https://github.com/search?l=&q=ResourceLoader+%40wikimedia Search]
-!! result
+!! html/php
+<p><a rel="nofollow" class="external text" href="https://github.com/search?l=&amp;q=ResourceLoader+%40wikimedia">Search</a>
+</p>
+!! html/parsoid
 <p><a rel="mw:ExtLink"
 href="https://github.com/search?l=&amp;q=ResourceLoader+%40wikimedia">Search</a></p>
 !! end
 
 !! test
-Parsoid: use url link syntax for links where the content is equal the link
-target
-!! options
-parsoid
-!! input
+Use url link syntax for links where the content is equal the link target
+!! wikitext
 http://example.com
-!! result
+!! html/php
+<p><a rel="nofollow" class="external free" href="http://example.com">http://example.com</a>
+</p>
+!! html/parsoid
 <p><a rel="mw:ExtLink" href="http://example.com">http://example.com</a></p>
 !! end
 
 !! test
 Parenthesis in external links, especially URL links
-!! options
-php
-!! input 
+!! wikitext
 http://example.com)
 
 http://example.com/test)
@@ -4173,7 +4075,7 @@ http://example.com/((test)
 http://example.com/a)b
 
 [http://example.com) foo]
-!! result
+!! html/php
 <p><a rel="nofollow" class="external free" href="http://example.com">http://example.com</a>)
 </p><p><a rel="nofollow" class="external free" href="http://example.com/test">http://example.com/test</a>)
 </p><p><a rel="nofollow" class="external free" href="http://example.com/(test)">http://example.com/(test)</a>
@@ -4183,29 +4085,7 @@ http://example.com/a)b
 </p><p><a rel="nofollow" class="external free" href="http://example.com/a)b">http://example.com/a)b</a>
 </p><p><a rel="nofollow" class="external text" href="http://example.com)">foo</a>
 </p>
-!! end
-
-!! test
-Parenthesis in external links, especially URL links (Parsoid)
-!! options
-parsoid
-!! input 
-http://example.com)
-
-http://example.com/test)
-
-http://example.com/(test)
-
-http://example.com/((test)
-
-(http://example.com/(test))
-
-(http://example.com/(test)))))
-
-http://example.com/a)b
-
-[http://example.com) foo]
-!! result
+!! html/parsoid
 <p><a rel="mw:ExtLink" href="http://example.com">http://example.com</a>)</p>
 <p><a rel="mw:ExtLink" href="http://example.com/test">http://example.com/test</a>)</p>
 <p><a rel="mw:ExtLink" href="http://example.com/(test)">http://example.com/(test)</a></p>
@@ -4218,13 +4098,15 @@ http://example.com/a)b
 
 !! test
 Parenthesis in external links, w/ transclusion or comment
-!! options
-parsoid
-!! input
+!! wikitext
 (http://example.com/{{echo|hi}})
 
 (http://example.com<!-- hi -->)
-!! result
+!! html/php
+<p>(<a rel="nofollow" class="external free" href="http://example.com/hi">http://example.com/hi</a>)
+</p><p>(<a rel="nofollow" class="external free" href="http://example.com">http://example.com</a>)
+</p>
+!! html/parsoid
 <p>(<a data-mw='{"attribs":[[{"txt":"href"},{"html":"http://example.com/&lt;span about=\"#mwt1\" typeof=\"mw:Transclusion\" data-mw=\"{&amp;quot;parts&amp;quot;:[{&amp;quot;template&amp;quot;:{&amp;quot;target&amp;quot;:{&amp;quot;wt&amp;quot;:&amp;quot;echo&amp;quot;,&amp;quot;href&amp;quot;:&amp;quot;./Template:Echo&amp;quot;},&amp;quot;params&amp;quot;:{&amp;quot;1&amp;quot;:{&amp;quot;wt&amp;quot;:&amp;quot;hi&amp;quot;}},&amp;quot;i&amp;quot;:0}}]}\" data-parsoid=\"{&amp;quot;dsr&amp;quot;:[20,31,null,null],&amp;quot;pi&amp;quot;:[[{&amp;quot;k&amp;quot;:&amp;quot;1&amp;quot;,&amp;quot;spc&amp;quot;:[&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;]}]]}\">hi&lt;/span>"}]]}' typeof="mw:ExpandedAttrs" about="#mwt2" rel="mw:ExtLink" href="http://example.com/hi" data-parsoid='{"stx":"url","a":{"href":"http://example.com/hi"},"sa":{"href":"http://example.com/{{echo|hi}}"}}'>http://example.com/hi</a>)</p>
 
 <p>(<a rel="mw:ExtLink" href="http://example.com" data-parsoid='{"stx":"url","a":{"href":"http://example.com"},"sa":{"href":"http://example.com&lt;!-- hi -->"}}'>http://example.com</a>)</p>
@@ -4236,22 +4118,23 @@ parsoid
 
 !! test
 Quotes
-!! input
+!! wikitext
 Normal text. '''Bold text.''' Normal text. ''Italic text.''
 
 Normal text. '''''Bold italic text.''''' Normal text.
-!!result
+!! html
 <p>Normal text. <b>Bold text.</b> Normal text. <i>Italic text.</i>
 </p><p>Normal text. <i><b>Bold italic text.</b></i> Normal text.
 </p>
 !! end
 
 
+# Parsoid inserts an empty bold tag pair at the end of the line, that the PHP
+# parser strips. The wikitext contains just the first half of the bold
+# quote pair.
 !! test
-Unclosed and unmatched quotes (php)
-!! options
-php
-!! input
+Unclosed and unmatched quotes
+!! wikitext
 '''''Bold italic text '''with bold deactivated''' in between.'''''
 
 '''''Bold italic text ''with italic deactivated'' in between.'''''
@@ -4272,7 +4155,7 @@ Normal text.
 ''Tom'''s car is bigger than ''Susan'''s.
 
 Plain ''italic'''s plain
-!! result
+!! html/php
 <p><i><b>Bold italic text </b>with bold deactivated<b> in between.</b></i>
 </p><p><b><i>Bold italic text </i>with italic deactivated<i> in between.</i></b>
 </p><p><b>Bold text..</b>
@@ -4284,36 +4167,7 @@ Plain ''italic'''s plain
 </p><p><i>Tom<b>s car is bigger than </b></i><b>Susan</b>s.
 </p><p>Plain <i>italic'</i>s plain
 </p>
-!! end
-# Parsoid inserts an empty bold tag pair at the end of the line, that the PHP
-# parser strips. The wikitext contains just the first half of the bold
-# quote pair.
-!! test
-Unclosed and unmatched quotes (parsoid)
-!! options
-parsoid
-!! input
-'''''Bold italic text '''with bold deactivated''' in between.'''''
-
-'''''Bold italic text ''with italic deactivated'' in between.'''''
-
-'''Bold text..
-
-..spanning two paragraphs (should not work).'''
-
-'''Bold tag left open
-
-''Italic tag left open
-
-Normal text.
-
-<!-- Unmatching number of opening, closing tags: -->
-'''This year''''s election ''should'' beat '''last year''''s.
-
-''Tom'''s car is bigger than ''Susan'''s.
-
-Plain ''italic'''s plain
-!! result
+!! html/parsoid
 <p><i><b>Bold italic text </b>with bold deactivated<b> in between.</b></i>
 </p><p><b><i>Bold italic text </i>with italic deactivated<i> in between.</i></b>
 </p><p><b>Bold text..</b>
@@ -4336,24 +4190,16 @@ Plain ''italic'''s plain
 # This should not produce <table></table> as <table><tr><td></td></tr></table>
 # is the bare minimum required by the spec, see:
 # http://www.w3.org/TR/xhtml-modularization/dtd_module_defs.html#a_module_Basic_Tables
-!! test
-A table with no data. (php)
-!! options
-php
-!! input
-{||}
-!! result
-
-!! end
-
 # Parsoid team replies: empty table tags are legal in HTML5
 !! test
-A table with no data. (parsoid)
+A table with no data.
 !! options
 parsoid=wt2html
-!! input
+!! wikitext
 {||}
-!! result
+!! html/php
+
+!! html/parsoid
 <table></table>
 
 !! end
@@ -4362,7 +4208,7 @@ parsoid=wt2html
 A table with stray table end tags on start tag line (wt2html)
 !! options
 parsoid=wt2html
-!! input
+!! wikitext
 {|style="color: red;"|}
 
 {|style="color: red;" |}
@@ -4376,7 +4222,7 @@ parsoid=wt2html
 {|style="color: red;" |} id="foo"
 |foo
 |}
-!! result
+!! html
 <table style="color: red;"></table>
 
 <table style="color: red;">
@@ -4400,54 +4246,41 @@ parsoid=wt2html
 !! end
 
 !! test
-A table with no data (take 2) (parsoid)
-!! options
-parsoid
-!! input
+A table with no data (take 2)
+!! wikitext
 {|
 |}
-!! result
+!! html/parsoid
 <table></table>
 !! end
 
 # A table with nothing but a caption is invalid XHTML, we might want to render
 # this as <p>caption</p>
+# Parsoid team replies: table with only a caption is legal in HTML5
 !! test
-A table with nothing but a caption (php)
-!! options
-php
-!! input
+A table with nothing but a caption
+!! wikitext
 {|
 |+ caption
 |}
-!! result
+!! html/php
 <table>
 <caption> caption
 </caption><tr><td></td></tr></table>
 
-!! end
-# Parsoid team replies: table with only a caption is legal in HTML5
-!! test
-A table with nothing but a caption (parsoid)
-!! options
-parsoid
-!! input
-{|
-|+ caption
-|}
-!! result
+!! html/parsoid
 <table><caption> caption</caption></table>
 !! end
 
 !! test
 A table with caption with default-spaced attributes and a table row
-!! input
+!! wikitext
 {|
 |+ style="color: red;" | caption1
 |-
 | foo
 |}
-!! result
+!! html
 <table>
 <caption style="color: red;"> caption1
 </caption>
@@ -4459,14 +4292,14 @@ A table with caption with default-spaced attributes and a table row
 
 !! test
 A table with captions with non-default spaced attributes and a table row
-!! input
+!! wikitext
 {|
 |+style="color: red;"|caption2
 |+ style="color: red;"| caption3
 |-
 | foo
 |}
-!! result
+!! html
 <table>
 <caption style="color: red;">caption2
 </caption>
@@ -4480,14 +4313,14 @@ A table with captions with non-default spaced attributes and a table row
 
 !! test
 Table td-cell syntax variations
-!! input
+!! wikitext
 {|
 | foo bar foo | baz
 | foo bar foo || baz
 | style='color:red;' | baz
 | style='color:red;' || baz
 |}
-!! result
+!! html
 <table>
 <tr>
 <td> baz
@@ -4505,13 +4338,13 @@ Table td-cell syntax variations
 
 !! test
 Simple table
-!! input
+!! wikitext
 {|
 | 1 || 2
 |-
 | 3 || 4
 |}
-!! result
+!! html
 <table>
 <tr>
 <td> 1 </td>
@@ -4526,13 +4359,13 @@ Simple table
 
 !! test
 Simple table but with multiple dashes for row wikitext
-!! input
+!! wikitext
 {|
 | foo
 |-----
 | bar
 |}
-!! result
+!! html
 <table>
 <tr>
 <td> foo
@@ -4544,7 +4377,7 @@ Simple table but with multiple dashes for row wikitext
 !! end
 !! test
 Multiplication table
-!! input
+!! wikitext
 {| border="1" cellpadding="2"
 |+Multiplication table
 |-
@@ -4565,7 +4398,7 @@ Multiplication table
 ! 5
 | 5 || 10 || 15
 |}
-!! result
+!! html
 <table border="1" cellpadding="2">
 <caption>Multiplication table
 </caption>
@@ -4615,11 +4448,11 @@ Multiplication table
 
 !! test
 Accept "||" in table headings
-!! input
+!! wikitext
 {|
 !h1 || h2
 |}
-!! result
+!! html
 <table>
 <tr>
 <th>h1 </th>
@@ -4630,11 +4463,11 @@ Accept "||" in table headings
 
 !! test
 Accept "||" in indented table headings
-!! input
+!! wikitext
 :{|
 !h1 || h2
 |}
-!! result
+!! html
 <dl><dd><table>
 <tr>
 <th>h1 </th>
@@ -4645,12 +4478,12 @@ Accept "||" in indented table headings
 
 !! test
 Accept empty attributes in td/th cells (td/th cells starting with leading ||)
-!! input
+!! wikitext
 {|
 !| h1
 || a
 |}
-!! result
+!! html
 <table>
 <tr>
 <th> h1
@@ -4662,12 +4495,12 @@ Accept empty attributes in td/th cells (td/th cells starting with leading ||)
 
 !!test
 Accept "| !" at start of line in tables (ignore !-attribute)
-!!input
+!! wikitext
 {|
 |-
 | !style="color:red" | bar
 |}
-!!result
+!! html
 <table>
 
 <tr>
@@ -4678,7 +4511,7 @@ Accept "| !" at start of line in tables (ignore !-attribute)
 
 !!test
 Allow +/- in 2nd and later cells in a row, in 1st cell when td-attrs are present, or in 1st cell when there is a space between "|" and +/- 
-!!input
+!! wikitext
 {|
 |-
 |style='color:red;'|+1
@@ -4690,7 +4523,7 @@ Allow +/- in 2nd and later cells in a row, in 1st cell when td-attrs are present
 | +1
 | -1
 |}
-!!result
+!! html
 <table>
 
 <tr>
@@ -4717,7 +4550,7 @@ Allow +/- in 2nd and later cells in a row, in 1st cell when td-attrs are present
 
 !! test
 Table rowspan
-!! input
+!! wikitext
 {| border=1
 | Cell 1, row 1
 |rowspan=2| Cell 2, row 1 (and 2)
@@ -4726,7 +4559,7 @@ Table rowspan
 | Cell 1, row 2
 | Cell 3, row 2
 |}
-!! result
+!! html
 <table border="1">
 <tr>
 <td> Cell 1, row 1
@@ -4745,7 +4578,7 @@ Table rowspan
 
 !! test
 Nested table
-!! input
+!! wikitext
 {| border=1
 | &alpha;
 |
@@ -4756,7 +4589,7 @@ Nested table
 |}
 |the original table again
 |}
-!! result
+!! html
 <table border="1">
 <tr>
 <td> &#945;
@@ -4777,11 +4610,11 @@ Nested table
 
 !! test
 Invalid attributes in table cell (bug 1830)
-!! input
+!! wikitext
 {|
 |Cell:|broken
 |}
-!! result
+!! html
 <table>
 <tr>
 <td>broken
@@ -4792,10 +4625,10 @@ Invalid attributes in table cell (bug 1830)
 
 !! test
 Table security: embedded pipes (http://lists.wikimedia.org/mailman/htdig/wikitech-l/2006-April/022293.html)
-!! input
+!! wikitext
 {|
 | |[ftp://|x||]" onmouseover="alert(document.cookie)">test
-!! result
+!! html
 <table>
 <tr>
 <td>[<a rel="nofollow" class="external free" href="ftp://%7Cx">ftp://%7Cx</a></td>
@@ -4809,7 +4642,7 @@ Table security: embedded pipes (http://lists.wikimedia.org/mailman/htdig/wikitec
 
 !! test
 Indented table markup mixed with indented pre content (proposed in bug 6200)
-!! input
+!! wikitext
  <table>
  <tr>
  <td>
@@ -4817,7 +4650,7 @@ Indented table markup mixed with indented pre content (proposed in bug 6200)
  </td>
  </tr>
  </table>
-!! result
+!! html
  <table>
  <tr>
  <td>
@@ -4831,12 +4664,12 @@ Indented table markup mixed with indented pre content (proposed in bug 6200)
 
 !! test
 Template-generated table cell attributes and cell content
-!! input
+!! wikitext
 {|
 |{{table_attribs}}
 | {{table_attribs}}
 |}
-!! result
+!! html
 <table>
 <tr>
 <td style="color: red"> Foo
@@ -4848,11 +4681,11 @@ Template-generated table cell attributes and cell content
 
 !! test
 Template-generated table cell attributes and cell content (2)
-!! input
+!! wikitext
 {|
 |align=center {{table_attribs}}
 |}
-!! result
+!! html
 <table>
 <tr>
 <td align="center" style="color: red"> Foo
@@ -4862,11 +4695,11 @@ Template-generated table cell attributes and cell content (2)
 
 !! test
 Template-generated table cell attributes and cell content (3)
-!! input
+!! wikitext
 {|
 |align=center {{table_cells}}
 |}
-!! result
+!! html
 <table>
 <tr>
 <td align="center" style="color: red"> Foo </td>
@@ -4878,13 +4711,13 @@ Template-generated table cell attributes and cell content (3)
 
 !! test
 Table with row followed by newlines and table heading
-!! input
+!! wikitext
 {|
 |-
 
 ! foo
 |}
-!! result
+!! html
 <table>
 
 
@@ -4896,13 +4729,13 @@ Table with row followed by newlines and table heading
 
 !! test
 Table with empty line following the start tag
-!! input
+!! wikitext
 {|
 
 |-
 | foo
 |}
-!! result
+!! html
 <table>
 
 
@@ -4916,13 +4749,11 @@ Table with empty line following the start tag
 # the PHP parser. Parsoid implements the behavior below.
 !! test
 Table attributes with empty value
-!! options
-parsoid
-!! input
+!! wikitext
 {|
 | style=| hello
 |}
-!! result
+!! html/parsoid
 <table>
 <tbody>
 <tr>
@@ -4933,7 +4764,7 @@ parsoid
 
 !! test
 Wikitext table with a lot of comments
-!! input
+!! wikitext
 {|
 <!-- c0 -->
 | foo
@@ -4943,7 +4774,7 @@ Wikitext table with a lot of comments
 |<!-- c4 -->
 <!-- c5 -->
 |}
-!! result
+!! html
 <table>
 <tr>
 <td> foo
@@ -4956,12 +4787,12 @@ Wikitext table with a lot of comments
 
 !! test
 Wikitext table with double-line table cell
-!! input
+!! wikitext
 {|
 |a
 b
 |}
-!! result
+!! html
 <table>
 <tr>
 <td>a
 
 !! test
 Table cell with a single comment
-!! input
+!! wikitext
 {|
 | <!-- c1 -->
 | a
 |}
-!! result
+!! html
 <table>
 <tr>
 <td>
@@ -4992,15 +4823,13 @@ Table cell with a single comment
 # not parse this kind of table at all. The main focus for Parsoid is on
 # round-tripping, so this output is ok for now. TODO: revisit!
 !! test
-Wikitext table with html-syntax row (Parsoid)
-!! options
-parsoid
-!! input
+Wikitext table with html-syntax row
+!! wikitext
 {|
 |-
 <td>foo</td>
 |}
-!! result
+!! html/parsoid
 <table>
 <tbody>
 <tr>
@@ -5012,12 +4841,12 @@ Implicit <td> after a |-
 (PHP parser relies on Tidy to add the missing <td> tags)
 !! options
 parsoid=wt2html,wt2wt
-!! input
+!! wikitext
 {|
 |-
 a
 |}
-!! result
+!! html
 <table>
 <tr><td>a</td></tr>
 </table>
@@ -5028,7 +4857,7 @@ Pres should be recognized in an explicit <td> context, but not in an implicit <t
 (PHP parser relies on Tidy to add the missing <td> tags)
 !! options
 parsoid=wt2html,wt2wt
-!! input
+!! wikitext
 {|
 |-
 |
@@ -5036,7 +4865,7 @@ parsoid=wt2html,wt2wt
 |-
  b
 |}
-!! result
+!! html
 <table>
 <tbody>
 <tr><td><pre>a</pre></td></tr>
@@ -5050,12 +4879,12 @@ Lists should be recognized in an implicit <td> context
 (PHP parser relies on Tidy to add the missing <td> tags)
 !! options
 parsoid=wt2html,wt2wt
-!! input
+!! wikitext
 {|
 |-
 *a
 |}
-!! result
+!! html
 <table>
 <tr>
 <td><ul>
@@ -5069,7 +4898,7 @@ parsoid=wt2html,wt2wt
 Parsoid: Round-trip tables directly followed by content (bug 51219)
 !! options
 parsoid=wt2html,wt2wt
-!! input
+!! wikitext
 {|
 |foo
 |} bar
@@ -5077,7 +4906,7 @@ parsoid=wt2html,wt2wt
 {|
 |baz
 |}<b>quux</b>
-!! result
+!! html
 <table><tbody>
 <tr>
 <td>foo</td></tr></tbody></table> bar
@@ -5091,7 +4920,7 @@ parsoid=wt2html,wt2wt
 Parsoid: Default to a newline after tables in new content (bug 51219)
 !! options
 parsoid=html2wt
-!! input
+!! wikitext
 {|
 |foo
 |}
@@ -5100,7 +4929,7 @@ parsoid=html2wt
 |baz
 |}
 '''quux'''
-!! result
+!! html
 <table><tbody>
 <tr><td>foo</td></tr></tbody></table> bar
 <table><tbody>
@@ -5111,11 +4940,11 @@ parsoid=html2wt
 Parsoid: newline inducing block nodes don't suppress <nowiki>
 !! options
 parsoid=html2wt
-!! input
+!! wikitext
 <nowiki> </nowiki>a
 
 = foo =
-!! result
+!! html
  a<h1>foo</h1>
 !! end
 
@@ -5124,90 +4953,90 @@ parsoid=html2wt
 ###
 !! test
 Plain link, capitalized
-!! input
+!! wikitext
 [[Main Page]]
-!! result
+!! html
 <p><a href="/wiki/Main_Page" title="Main Page">Main Page</a>
 </p>
 !! end
 
 !! test
 Plain link, uncapitalized
-!! input
+!! wikitext
 [[main Page]]
-!! result
+!! html
 <p><a href="/wiki/Main_Page" title="Main Page">main Page</a>
 </p>
 !! end
 
 !! test
 Piped link
-!! input
+!! wikitext
 [[Main Page|The Main Page]]
-!! result
+!! html
 <p><a href="/wiki/Main_Page" title="Main Page">The Main Page</a>
 </p>
 !! end
 
 !! test
 Piped link with comment in link text
-!! input
+!! wikitext
 [[Main Page|The Main<!--front--> Page]]
-!! result
+!! html
 <p><a href="/wiki/Main_Page" title="Main Page">The Main Page</a>
 </p>
 !! end
 
 !! test
 Broken link
-!! input
+!! wikitext
 [[Zigzagzogzagzig]]
-!! result
+!! html
 <p><a href="/index.php?title=Zigzagzogzagzig&amp;action=edit&amp;redlink=1" class="new" title="Zigzagzogzagzig (page does not exist)">Zigzagzogzagzig</a>
 </p>
 !! end
 
 !! test
 Broken link with fragment
-!! input
+!! wikitext
 [[Zigzagzogzagzig#zug]]
-!! result
+!! html
 <p><a href="/index.php?title=Zigzagzogzagzig&amp;action=edit&amp;redlink=1" class="new" title="Zigzagzogzagzig (page does not exist)">Zigzagzogzagzig#zug</a>
 </p>
 !! end
 
 !! test
 Special page link with fragment
-!! input
+!! wikitext
 [[Special:Version#anchor]]
-!! result
+!! html
 <p><a href="/wiki/Special:Version#anchor" title="Special:Version">Special:Version#anchor</a>
 </p>
 !! end
 
 !! test
 Nonexistent special page link with fragment
-!! input
+!! wikitext
 [[Special:ThisNameWillHopefullyNeverBeUsed#anchor]]
-!! result
+!! html
 <p><a href="/wiki/Special:ThisNameWillHopefullyNeverBeUsed" class="new" title="Special:ThisNameWillHopefullyNeverBeUsed (page does not exist)">Special:ThisNameWillHopefullyNeverBeUsed#anchor</a>
 </p>
 !! end
 
 !! test
 Link with prefix
-!! input
+!! wikitext
 xxx[[main Page]], xxx[[Main Page]], Xxx[[main Page]] XXX[[main Page]], XXX[[Main Page]]
-!! result
+!! html
 <p>xxx<a href="/wiki/Main_Page" title="Main Page">main Page</a>, xxx<a href="/wiki/Main_Page" title="Main Page">Main Page</a>, Xxx<a href="/wiki/Main_Page" title="Main Page">main Page</a> XXX<a href="/wiki/Main_Page" title="Main Page">main Page</a>, XXX<a href="/wiki/Main_Page" title="Main Page">Main Page</a>
 </p>
 !! end
 
 !! test
 Link with suffix
-!! input
+!! wikitext
 [[Main Page]]xxx, [[Main Page]]XXX, [[Main Page]]!!!
-!! result
+!! html
 <p><a href="/wiki/Main_Page" title="Main Page">Main Pagexxx</a>, <a href="/wiki/Main_Page" title="Main Page">Main Page</a>XXX, <a href="/wiki/Main_Page" title="Main Page">Main Page</a>!!!
 </p>
 !! end
@@ -5220,13 +5049,13 @@ Some text
 
 !! test
 Bug 43661: Piped links with identical prefixes
-!! input
+!! wikitext
 [[prefixed article|prefixed articles with spaces]]
 
 [[prefixed article|prefixed articlesaoeu]]
 
 [[Main Page|Main Page test]]
-!! result
+!! html
 <p><a href="/wiki/Prefixed_article" title="Prefixed article">prefixed articles with spaces</a>
 </p><p><a href="/wiki/Prefixed_article" title="Prefixed article">prefixed articlesaoeu</a>
 </p><p><a href="/wiki/Main_Page" title="Main Page">Main Page test</a>
@@ -5236,46 +5065,46 @@ Bug 43661: Piped links with identical prefixes
 
 !! test
 Link with HTML entity in suffix / tail
-!! input
+!! wikitext
 [[Main Page]]&quot;, [[Main Page]]&#97;
-!! result
+!! html
 <p><a href="/wiki/Main_Page" title="Main Page">Main Page</a>&quot;, <a href="/wiki/Main_Page" title="Main Page">Main Page</a>&#97;
 </p>
 !! end
 
 !! test
 Link with 3 brackets
-!! input
+!! wikitext
 [[[Main Page]]]
-!! result
+!! html
 <p>[[[Main Page]]]
 </p>
 !! end
 
 !! test
 Link with 4 brackets
-!! input
+!! wikitext
 [[[[Main Page]]]]
-!! result
+!! html
 <p>[[<a href="/wiki/Main_Page" title="Main Page">Main Page</a>]]
 </p>
 !! end
 
 !! test
 Piped link with 3 brackets
-!! input
+!! wikitext
 [[[main page|the main page]]]
-!! result
+!! html
 <p>[[[main page|the main page]]]
 </p>
 !! end
 
 !! test
 Piped link with extlink-like text
-!! input
+!! wikitext
 [[Main Page|[bar]]]
 [[Main Page|This is a [bar]]]
-!! result
+!! html
 <p><a href="/wiki/Main_Page" title="Main Page">[bar]</a>
 <a href="/wiki/Main_Page" title="Main Page">This is a [bar]</a>
 </p>
@@ -5283,18 +5112,18 @@ Piped link with extlink-like text
 
 !! test
 Link with multiple pipes
-!! input
+!! wikitext
 [[Main Page|The|Main|Page]]
-!! result
+!! html
 <p><a href="/wiki/Main_Page" title="Main Page">The|Main|Page</a>
 </p>
 !! end
 
 !! test
 Link to namespaces
-!! input
+!! wikitext
 [[Talk:Parser testing]], [[Meta:Disclaimers]]
-!! result
+!! html
 <p><a href="/index.php?title=Talk:Parser_testing&amp;action=edit&amp;redlink=1" class="new" title="Talk:Parser testing (page does not exist)">Talk:Parser testing</a>, <a href="/index.php?title=Meta:Disclaimers&amp;action=edit&amp;redlink=1" class="new" title="Meta:Disclaimers (page does not exist)">Meta:Disclaimers</a>
 </p>
 !! end
@@ -5308,9 +5137,9 @@ This is an article in the MemoryAlpha namespace
 
 !! test
 Namespace takes precedence over interwiki link (bug 51680)
-!! input
+!! wikitext
 [[MemoryAlpha:AlphaTest]]
-!! result
+!! html
 <p><a href="/wiki/MemoryAlpha:AlphaTest" title="MemoryAlpha:AlphaTest">MemoryAlpha:AlphaTest</a>
 </p>
 !! end
@@ -5321,54 +5150,54 @@ Namespace takes precedence over interwiki link (bug 51680)
 Link to namespace preferred over interwiki with correct rel attribute
 !! options
 parsoid=html2wt,html2html
-!! input
+!! wikitext
 [[MemoryAlpha:AlphaTest]]
-!! result
+!! html
 <p><a rel="mw:WikiLink" href="./MemoryAlpha:AlphaTest">MemoryAlpha:AlphaTest</a>
 </p>
 !! end
 
 !! test
 Piped link to namespace
-!! input
+!! wikitext
 [[Meta:Disclaimers|The disclaimers]]
-!! result
+!! html
 <p><a href="/index.php?title=Meta:Disclaimers&amp;action=edit&amp;redlink=1" class="new" title="Meta:Disclaimers (page does not exist)">The disclaimers</a>
 </p>
 !! end
 
 !! test
 Link containing }
-!! input
+!! wikitext
 [[Usually caused by a typo (oops}]]
-!! result
+!! html
 <p>[[Usually caused by a typo (oops}]]
 </p>
 !! end
 
 !! test
 Link containing % (not as a hex sequence)
-!! input
+!! wikitext
 [[7% Solution]]
-!! result
+!! html
 <p><a href="/index.php?title=7%25_Solution&amp;action=edit&amp;redlink=1" class="new" title="7% Solution (page does not exist)">7% Solution</a>
 </p>
 !! end
 
 !! test
 Link containing % as a single hex sequence interpreted to char
-!! input
+!! wikitext
 [[7%25 Solution]]
-!! result
+!! html
 <p><a href="/index.php?title=7%25_Solution&amp;action=edit&amp;redlink=1" class="new" title="7% Solution (page does not exist)">7% Solution</a>
 </p>
 !!end
 
 !! test
 Link containing % as a double hex sequence interpreted to hex sequence
-!! input
+!! wikitext
 [[7%2525 Solution]]
-!! result
+!! html
 <p>[[7%2525 Solution]]
 </p>
 !!end
@@ -5376,27 +5205,27 @@ Link containing % as a double hex sequence interpreted to hex sequence
 !! test
 Link containing "#<" and "#>" % as a hex sequences- these are valid section anchors
 Example for such a section: == < ==
-!! input
+!! wikitext
 [[%23%3c]][[%23%3e]]
-!! result
+!! html
 <p><a href="#.3C">#&lt;</a><a href="#.3E">#&gt;</a>
 </p>
 !! end
 
 !! test
 Link containing "<#" and ">#" as a hex sequences
-!! input
+!! wikitext
 [[%3c%23]][[%3e%23]]
-!! result
+!! html
 <p>[[%3c%23]][[%3e%23]]
 </p>
 !! end
 
 !! test
 Link containing an equals sign
-!! input
+!! wikitext
 [[Special:BookSources/isbn=4-00-026157-6]]
-!! result
+!! html
 <p><a href="/wiki/Special:BookSources/isbn%3D4-00-026157-6" title="Special:BookSources/isbn=4-00-026157-6">Special:BookSources/isbn=4-00-026157-6</a>
 </p>
 !! end
@@ -5412,43 +5241,43 @@ Just a test of an article title containing a tilde.
 # seen by the parser.
 !! test
 Link containing a tilde
-!! input
+!! wikitext
 [[Foo~bar]]
-!! result
+!! html
 <p><a href="/wiki/Foo%7Ebar" title="Foo~bar">Foo~bar</a>
 </p>
 !! end
 
 !! test
 Link containing double-single-quotes '' (bug 4598)
-!! input
+!! wikitext
 [[Lista d''e paise d''o munno]]
-!! result
+!! html
 <p><a href="/index.php?title=Lista_d%27%27e_paise_d%27%27o_munno&amp;action=edit&amp;redlink=1" class="new" title="Lista d''e paise d''o munno (page does not exist)">Lista d''e paise d''o munno</a>
 </p>
 !! end
 
 !! test
 Link containing double-single-quotes '' in text (bug 4598 sanity check)
-!! input
+!! wikitext
 Some [[Link|pretty ''italics'' and stuff]]!
-!! result
+!! html
 <p>Some <a href="/index.php?title=Link&amp;action=edit&amp;redlink=1" class="new" title="Link (page does not exist)">pretty <i>italics</i> and stuff</a>!
 </p>
 !! end
 
 !! test
 Link containing double-single-quotes '' in text embedded in italics (bug 4598 sanity check)
-!! input
+!! wikitext
 ''Some [[Link|pretty ''italics'' and stuff]]!
-!! result
+!! html
 <p><i>Some <a href="/index.php?title=Link&amp;action=edit&amp;redlink=1" class="new" title="Link (page does not exist)">pretty <i>italics</i> and stuff</a>!</i>
 </p>
 !! end
 
 !! test
 Link with double quotes in title part (literal) and alternate part (interpreted)
-!! input
+!! wikitext
 [[File:Denys Savchenko ''Pentecoste''.jpg]]
 
 [[''Pentecoste'']]
@@ -5456,7 +5285,7 @@ Link with double quotes in title part (literal) and alternate part (interpreted)
 [[''Pentecoste''|Pentecoste]]
 
 [[''Pentecoste''|''Pentecoste'']]
-!! result
+!! html
 <p><a href="/index.php?title=Special:Upload&amp;wpDestFile=Denys_Savchenko_%27%27Pentecoste%27%27.jpg" class="new" title="File:Denys Savchenko &#39;&#39;Pentecoste&#39;&#39;.jpg">File:Denys Savchenko <i>Pentecoste</i>.jpg</a>
 </p><p><a href="/index.php?title=%27%27Pentecoste%27%27&amp;action=edit&amp;redlink=1" class="new" title="''Pentecoste'' (page does not exist)">''Pentecoste''</a>
 </p><p><a href="/index.php?title=%27%27Pentecoste%27%27&amp;action=edit&amp;redlink=1" class="new" title="''Pentecoste'' (page does not exist)">Pentecoste</a>
@@ -5466,12 +5295,12 @@ Link with double quotes in title part (literal) and alternate part (interpreted)
 
 !! test
 Broken image links with HTML captions (bug 39700)
-!! input
+!! wikitext
 [[File:Nonexistent|<script></script>]]
 [[File:Nonexistent|100px|<script></script>]]
 [[File:Nonexistent|&lt;]]
 [[File:Nonexistent|a<i>b</i>c]]
-!! result
+!! html
 <p><a href="/index.php?title=Special:Upload&amp;wpDestFile=Nonexistent" class="new" title="File:Nonexistent">&lt;script&gt;&lt;/script&gt;</a>
 <a href="/index.php?title=Special:Upload&amp;wpDestFile=Nonexistent" class="new" title="File:Nonexistent">&lt;script&gt;&lt;/script&gt;</a>
 <a href="/index.php?title=Special:Upload&amp;wpDestFile=Nonexistent" class="new" title="File:Nonexistent">&lt;</a>
@@ -5481,47 +5310,47 @@ Broken image links with HTML captions (bug 39700)
 
 !! test
 Plain link to URL
-!! input
+!! wikitext
 [[http://www.example.com]]
-!! result
+!! html
 <p>[<a rel="nofollow" class="external autonumber" href="http://www.example.com">[1]</a>]
 </p>
 !! end
 
 !! test
 Plain link to URL with link text
-!! input
+!! wikitext
 [[http://www.example.com Link text]]
-!! result
+!! html
 <p>[<a rel="nofollow" class="external text" href="http://www.example.com">Link text</a>]
 </p>
 !! end
 
 !! test
 Plain link to protocol-relative URL
-!! input
+!! wikitext
 [[//www.example.com]]
-!! result
+!! html
 <p>[<a rel="nofollow" class="external autonumber" href="//www.example.com">[1]</a>]
 </p>
 !! end
 
 !! test
 Plain link to protocol-relative URL with link text
-!! input
+!! wikitext
 [[//www.example.com Link text]]
-!! result
+!! html
 <p>[<a rel="nofollow" class="external text" href="//www.example.com">Link text</a>]
 </p>
 !! end
 
 !! test
 Plain link to page with question mark in title
-!! input
+!! wikitext
 [[A?b]]
 
 [[A?b|Baz]]
-!! result
+!! html
 <p><a href="/wiki/A%3Fb" title="A?b">A?b</a>
 </p><p><a href="/wiki/A%3Fb" title="A?b">Baz</a>
 </p>
@@ -5541,18 +5370,18 @@ Plain link to page with question mark in title
 # -- wtm
 !! test
 Piped link to URL
-!! input
+!! wikitext
 Piped link to URL: [[http://www.example.com|an example URL]]
-!! result
+!! html
 <p>Piped link to URL: [<a rel="nofollow" class="external text" href="http://www.example.com%7Can">example URL</a>]
 </p>
 !! end
 
 !! test
 BUG 2: [[page|http://url/]] should link to page, not http://url/
-!! input
+!! wikitext
 [[Main Page|http://url/]]
-!! result
+!! html
 <p><a href="/wiki/Main_Page" title="Main Page">http://url/</a>
 </p>
 !! end
@@ -5561,9 +5390,9 @@ BUG 2: [[page|http://url/]] should link to page, not http://url/
 BUG 337: Escaped self-links should be bold
 !! options
 title=[[Bug462]]
-!! input
+!! wikitext
 [[Bu&#103;462]] [[Bug462]]
-!! result
+!! html
 <p><strong class="selflink">Bu&#103;462</strong> <strong class="selflink">Bug462</strong>
 </p>
 !! end
@@ -5572,9 +5401,9 @@ title=[[Bug462]]
 Self-link to section should not be bold
 !! options
 title=[[Main Page]]
-!! input
+!! wikitext
 [[Main Page#section]]
-!! result
+!! html
 <p><a href="/wiki/Main_Page#section" title="Main Page">Main Page#section</a>
 </p>
 !! end
@@ -5589,9 +5418,9 @@ This is 00.
 Self-link to numeric title
 !!options
 title=[[0]]
-!!input
+!! wikitext
 [[0]]
-!!result
+!! html
 <p><strong class="selflink">0</strong>
 </p>
 !!end
@@ -5600,27 +5429,27 @@ title=[[0]]
 Link to numeric-equivalent title
 !!options
 title=[[0]]
-!!input
+!! wikitext
 [[00]]
-!!result
+!! html
 <p><a href="/wiki/00" title="00">00</a>
 </p>
 !!end
 
 !! test
 <nowiki> inside a link
-!! input
+!! wikitext
 [[Main<nowiki> Page</nowiki>]] [[Main Page|the main page <nowiki>[it's not very good]</nowiki>]]
-!! result
+!! html
 <p>[[Main Page]] <a href="/wiki/Main_Page" title="Main Page">the main page [it's not very good]</a>
 </p>
 !! end
 
 !! test
 Non-breaking spaces in title
-!! input
+!! wikitext
 [[&nbsp; Main &nbsp; Page &nbsp;]]
-!! result
+!! html
 <p><a href="/wiki/Main_Page" title="Main Page">&#160; Main &#160; Page &#160;</a>
 </p>
 !!end
@@ -5629,9 +5458,9 @@ Non-breaking spaces in title
 Internal link with ca linktrail, surrounded by bold apostrophes (bug 27473 primary issue)
 !! options
 language=ca
-!! input
+!! wikitext
 '''[[Main Page]]'''
-!! result
+!! html
 <p><b><a href="/wiki/Main_Page" title="Main Page">Main Page</a></b>
 </p>
 !! end
@@ -5640,9 +5469,9 @@ language=ca
 Internal link with ca linktrail, surrounded by italic apostrophes (bug 27473 primary issue)
 !! options
 language=ca
-!! input
+!! wikitext
 ''[[Main Page]]''
-!! result
+!! html
 <p><i><a href="/wiki/Main_Page" title="Main Page">Main Page</a></i>
 </p>
 !! end
@@ -5651,9 +5480,9 @@ language=ca
 Internal link with en linktrail: no apostrophes (bug 27473)
 !! options
 language=en
-!! input
+!! wikitext
 [[Something]]'nice
-!! result
+!! html
 <p><a href="/index.php?title=Something&amp;action=edit&amp;redlink=1" class="new" title="Something (page does not exist)">Something</a>'nice
 </p>
 !! end
@@ -5662,9 +5491,9 @@ language=en
 Internal link with ca linktrail with apostrophes (bug 27473)
 !! options
 language=ca
-!! input
+!! wikitext
 [[Something]]'nice
-!! result
+!! html
 <p><a href="/index.php?title=Something&amp;action=edit&amp;redlink=1" class="new" title="Something (encara no existeix)">Something'nice</a>
 </p>
 !! end
@@ -5673,9 +5502,9 @@ language=ca
 Internal link with kaa linktrail with apostrophes (bug 27473)
 !! options
 language=kaa
-!! input
+!! wikitext
 [[Something]]'nice
-!! result
+!! html
 <p><a href="/index.php?title=Something&amp;action=edit&amp;redlink=1" class="new" title="Something (bet ele jaratılmag'an)">Something'nice</a>
 </p>
 !! end
@@ -5684,9 +5513,9 @@ language=kaa
 1. Interaction of linktrail and template encapsulation
 !! options
 parsoid
-!! input
+!! wikitext
 {{echo|[[Foo]]}}l
-!! result
+!! html
 <p><a rel="mw:WikiLink" href="Foo" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"[[Foo]]"}},"i":0}},"l"]}'>Fool</a></p>
 !! end
 
@@ -5694,9 +5523,9 @@ parsoid
 2. Interaction of linktrail and template encapsulation
 !! options
 parsoid
-!! input
+!! wikitext
 {{echo|Some [[Fool]]}}s
-!! result
+!! html
 <p data-parsoid='{}'><span about="#mwt1" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"Some [[Fool]]"}},"i":0}},"s"]}' data-parsoid='{"pi":[[{"k":"1","spc":["","","",""]}]]}'>Some </span><a rel="mw:WikiLink" href="./Fool" about="#mwt1" data-parsoid='{"stx":"simple","a":{"href":"./Fool"},"sa":{"href":"Fool"},"tail":"s"}'>Fools</a></p>
 !! end
 
@@ -5704,9 +5533,9 @@ parsoid
 3. Interaction of linktrail and template encapsulation
 !! options
 parsoid
-!! input
+!! wikitext
 {{echo|Some [[Fool]]s are '''bold and foolish'''}}
-!! result
+!! html
 <p about="#mwt1" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"Some [[Fool]]s are &#39;&#39;&#39;bold and foolish&#39;&#39;&#39;"}},"i":0}}]}' data-parsoid='{"pi":[[{"k":"1","spc":["","","",""]}]]}'>Some <a rel="mw:WikiLink" href="./Fool" data-parsoid='{"stx":"simple","a":{"href":"./Fool"},"sa":{"href":"Fool"},"tail":"s"}'>Fools</a> are <b data-parsoid="{}">bold and foolish</b></p>
 !! end
 
@@ -5720,9 +5549,9 @@ Test.
 Internal link with is link prefix
 !! options
 language=is
-!! input
+!! wikitext
 Aðrir mótmælenda[[söfnuður|söfnuðir]] og
-!! result
+!! html
 <p>Aðrir <a href="/wiki/S%C3%B6fnu%C3%B0ur" title="Söfnuður">mótmælendasöfnuðir</a> og
 </p>
 !! end
@@ -5737,13 +5566,13 @@ Test.
 Internal link with is link trail and link prefix
 !! options
 language=is
-!! input
+!! wikitext
 [[mótmælendatrú|xxx]]ar
 [[mótmælendatrú]]ar
 mótmælenda[[söfnuður]]
 mótmælenda[[söfnuður|söfnuðir]]
 mótmælenda[[söfnuður|söfnuðir]]xxx
-!! result
+!! html
 <p><a href="/wiki/M%C3%B3tm%C3%A6lendatr%C3%BA" title="Mótmælendatrú">xxxar</a>
 <a href="/wiki/M%C3%B3tm%C3%A6lendatr%C3%BA" title="Mótmælendatrú">mótmælendatrúar</a>
 <a href="/wiki/S%C3%B6fnu%C3%B0ur" title="Söfnuður">mótmælendasöfnuður</a>
@@ -5756,9 +5585,9 @@ mótmælenda[[söfnuður|söfnuðir]]xxx
 Parsoid link trail escaping
 !! options
 parsoid=html2wt,html2html
-!! input
+!! wikitext
 [[apple]]<nowiki/>s
-!! result
+!! html
 <p><a rel="mw:WikiLink" href="Apple">apple</a>s</p>
 !! end
 
@@ -5767,15 +5596,15 @@ Parsoid link prefix escaping
 !! options
 language=is
 parsoid=html2wt,html2html
-!! input
+!! wikitext
 Aðrir mótmælenda<nowiki/>[[söfnuður]]
-!! result
+!! html
 <p>Aðrir mótmælenda<a rel="mw:WikiLink" href="Söfnuður">söfnuður</a></p>
 !! end
 
 !! test
 Parsoid-centric test: Whitespace in ext- and wiki-links should be preserved
-!! input
+!! wikitext
 [[Foo|  bar]]
 
 [[Foo|  ''bar'']]
@@ -5783,7 +5612,7 @@ Parsoid-centric test: Whitespace in ext- and wiki-links should be preserved
 [http://wp.org   foo]
 
 [http://wp.org   ''foo'']
-!! result
+!! html
 <p><a href="/index.php?title=Foo&amp;action=edit&amp;redlink=1" class="new" title="Foo (page does not exist)">  bar</a>
 </p><p><a href="/index.php?title=Foo&amp;action=edit&amp;redlink=1" class="new" title="Foo (page does not exist)">  <i>bar</i></a>
 </p><p><a rel="nofollow" class="external text" href="http://wp.org">foo</a>
@@ -5795,9 +5624,9 @@ Parsoid-centric test: Whitespace in ext- and wiki-links should be preserved
 Parsoid: Scoped parsing should handle mixed transclusions and plain text
 !! options
 parsoid
-!! input
+!! wikitext
 [[Foo|{{echo|a}} b {{echo|c}}]]
-!! result
+!! html
 <p><a rel="mw:WikiLink" href="Foo"><span about="#mwt2" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"a"}},"i":0}}]}'>a</span> b <span about="#mwt3" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"c"}},"i":0}}]}'>c</span></a></p>
 !! end
 
@@ -5807,28 +5636,28 @@ parsoid
 
 !! test
 Inline interwiki link
-!! input
+!! wikitext
 [[MeatBall:SoftSecurity]]
-!! result
+!! html
 <p><a href="http://www.usemod.com/cgi-bin/mb.pl?SoftSecurity" class="extiw" title="meatball:SoftSecurity">MeatBall:SoftSecurity</a>
 </p>
 !! end
 
 !! test
 Inline interwiki link with empty title (bug 2372)
-!! input
+!! wikitext
 [[MeatBall:]]
-!! result
+!! html
 <p><a href="http://www.usemod.com/cgi-bin/mb.pl" class="extiw" title="meatball:">MeatBall:</a>
 </p>
 !! end
 
 !! test
 Interwiki link encoding conversion (bug 1636)
-!! input
+!! wikitext
 *[[Wikipedia:ro:Olteni&#0355;a]]
 *[[Wikipedia:ro:Olteni&#355;a]]
-!! result
+!! html
 <ul>
 <li><a href="http://en.wikipedia.org/wiki/ro:Olteni%C5%A3a" class="extiw" title="wikipedia:ro:Olteniţa">Wikipedia:ro:Olteni&#355;a</a>
 </li>
@@ -5840,9 +5669,9 @@ Interwiki link encoding conversion (bug 1636)
 
 !! test
 Interwiki link with fragment (bug 2130)
-!! input
+!! wikitext
 [[MeatBall:SoftSecurity#foo]]
-!! result
+!! html
 <p><a href="http://www.usemod.com/cgi-bin/mb.pl?SoftSecurity#foo" class="extiw" title="meatball:SoftSecurity">MeatBall:SoftSecurity#foo</a>
 </p>
 !! end
@@ -5852,11 +5681,11 @@ Interwiki link with fragment (bug 2130)
 Different interwiki prefixes mapping to the same URL
 !! options
 parsoid
-!! input
+!! wikitext
 [[wikipedia:Foo]]
 
 [[:en:Foo]]
-!! result
+!! html
 <p><a rel="mw:ExtLink" href="http://en.wikipedia.org/wiki/Foo" data-parsoid='{"stx":"simple","a":{"href":"http://en.wikipedia.org/wiki/Foo"},"sa":{"href":"wikipedia:Foo"},"isIW":true}'>wikipedia:Foo</a></p>
 
 <p><a rel="mw:ExtLink" href="//en.wikipedia.org/wiki/Foo" data-parsoid='{"stx":"simple","a":{"href":"//en.wikipedia.org/wiki/Foo"},"sa":{"href":":en:Foo"},"isIW":true}'>en:Foo</a></p>
@@ -5866,14 +5695,14 @@ parsoid
 Interwiki links that cannot be represented in wiki syntax
 !! options
 parsoid
-!! input
+!! wikitext
 [[meatball:ok]]
 [[meatball:ok#foo|ok with fragment]]
 [[meatball:ok_as_well?|ok ending with ? mark]]
 [http://de.wikipedia.org/wiki/Foo?action=history has query]
 [http://de.wikipedia.org/wiki/#foo is just fragment]
 
-!! result
+!! html
 <p><a rel="mw:ExtLink" href="http://www.usemod.com/cgi-bin/mb.pl?ok">meatball:ok</a>
 <a rel="mw:ExtLink" href="http://www.usemod.com/cgi-bin/mb.pl?ok#foo">ok with fragment</a>
 <a rel="mw:ExtLink" href="http://www.usemod.com/cgi-bin/mb.pl?ok_as_well%3F">ok ending with ? mark</a>
@@ -5885,9 +5714,9 @@ parsoid
 Interwiki links: trail
 !! options
 parsoid
-!! input
+!! wikitext
 [[wikipedia:Foo|Ba]]r
-!! result
+!! html
 <p data-parsoid='{}'><a rel="mw:ExtLink" href="http://en.wikipedia.org/wiki/Foo" data-parsoid='{"stx":"piped","a":{"href":"http://en.wikipedia.org/wiki/Foo"},"sa":{"href":"wikipedia:Foo"},"isIW":true,"tail":"r"}'>Bar</a></p>
 !! end
 
@@ -5898,21 +5727,21 @@ parsoid
 
 !! test
 Interlanguage link
-!! input
+!! wikitext
 Blah blah blah
 [[zh:Chinese]]
-!!result
+!! html
 <p>Blah blah blah
 </p>
 !! end
 
 !! test
 Double interlanguage link
-!! input
+!! wikitext
 Blah blah blah
 [[es:Spanish]]
 [[zh:Chinese]]
-!!result
+!! html
 <p>Blah blah blah
 </p>
 !! end
@@ -5921,10 +5750,10 @@ Blah blah blah
 Interlanguage link, with prefix links
 !! options
 language=ln
-!! input
+!! wikitext
 Blah blah blah
 [[zh:Chinese]]
-!!result
+!! html
 <p>Blah blah blah
 </p>
 !! end
@@ -5933,11 +5762,11 @@ Blah blah blah
 Double interlanguage link, with prefix links (bug 8897)
 !! options
 language=ln
-!! input
+!! wikitext
 Blah blah blah
 [[es:Spanish]]
 [[zh:Chinese]]
-!!result
+!! html
 <p>Blah blah blah
 </p>
 !! end
@@ -5946,9 +5775,9 @@ Blah blah blah
 Parsoid-specific test: Wikilinks with &nbsp; should RT properly
 !! options
 language=ln
-!! input
+!! wikitext
 [[WW&nbsp;II]]
-!!result
+!! html
 <p><a href="/index.php?title=WW_II&amp;action=edit&amp;redlink=1" class="new" title="WW II (lonkásá  ezalí tɛ̂)">WW&#160;II</a>
 </p>
 !! end
@@ -5957,11 +5786,11 @@ language=ln
 Parsoid bug 53221: Wikilinks should be properly entity-escaped
 !! options
 parsoid=html2wt
-!! input
+!! wikitext
 He&amp;nbsp;llo [[Foo|He&amp;nbsp;llo]]
 
 He&amp;nbsp;llo [[He&amp;nbsp;llo]]
-!!result
+!! html
 <p>He&amp;nbsp;llo <a href="Foo" rel="mw:WikiLink">He&amp;nbsp;llo</a></p>
 <p>He&amp;nbsp;llo <a href="He&amp;nbsp;llo" rel="mw:WikiLink">He&amp;nbsp;llo</a></p>
 !! end
@@ -5970,11 +5799,11 @@ He&amp;nbsp;llo [[He&amp;nbsp;llo]]
 Parsoid: handle constructor well
 !! options
 parsoid
-!! input
+!! wikitext
 [[constructor]]
 
 [[constructor:foo]]
-!! result
+!! html
 <p><a rel="mw:WikiLink" href="./Constructor" data-parsoid="{&quot;stx&quot;:&quot;simple&quot;,&quot;a&quot;:{&quot;href&quot;:&quot;./Constructor&quot;},&quot;sa&quot;:{&quot;href&quot;:&quot;constructor&quot;}}">constructor</a></p>
 
 <p><a rel="mw:WikiLink" href="./Foo" data-parsoid="{&quot;stx&quot;:&quot;simple&quot;,&quot;a&quot;:{&quot;href&quot;:&quot;./Foo&quot;},&quot;sa&quot;:{&quot;href&quot;:&quot;constructor:foo&quot;}}">constructor:foo</a></p>
@@ -5984,9 +5813,9 @@ parsoid
 Parsoid: recognize interlanguage links without a target page
 !! options
 parsoid
-!! input
+!! wikitext
 [[ko:]]
-!! result
+!! html
 <p>
 <link rel="mw:PageProp/Language" href="http://ko.wikipedia.org/wiki/"></p>
 !! end
@@ -5995,9 +5824,9 @@ parsoid
 Parsoid: recognize interwiki links without a target page
 !! options
 parsoid
-!! input
+!! wikitext
 [[:ko:]]
-!! result
+!! html
 <p><a rel="mw:ExtLink" href="//ko.wikipedia.org/wiki/">ko:</a></p>
 !! end
 
@@ -6005,9 +5834,9 @@ parsoid
 Parsoid: Bug #45209, handle interwiki links pointing to the current wiki as plain wiki links
 !! options
 parsoid
-!! input
+!! wikitext
 [[en:Foo]]
-!! result
+!! html
 <p><a rel="mw:WikiLink" href="./Foo" data-parsoid='{"stx":"simple","a":{"href":"./Foo"},"sa":{"href":"en:Foo"}}'>Foo</a></p>
 !! end
 
@@ -6018,9 +5847,9 @@ parsoid
 1. Simple redirect to page
 !! options
 parsoid
-!! input
+!! wikitext
 #REDIRECT [[Main Page]]
-!! result
+!! html
 <link rel="mw:PageProp/redirect" href="./Main_Page">
 !! end
 
@@ -6029,10 +5858,10 @@ parsoid
 2. Other redirect variants
 !! options
 parsoid=wt2html,wt2wt
-!! input
+!! wikitext
 #REDIRECT [[Main_Page]]
 #REDIRECT [[<nowiki>[[Bar]]</nowiki>]]
-!! result
+!! html
 <link rel="mw:PageProp/redirect" href="./Main_Page">
 <link rel="mw:PageProp/redirect" href="./%5B%5BBar%5D%5D">
 !! end
@@ -6043,9 +5872,9 @@ Optional colon in #REDIRECT
 # the colon is archaic syntax.  we support it for wt2html, but we
 # don't care that it roundtrips back to the modern syntax.
 parsoid=wt2html,html2html
-!! input
+!! wikitext
 #REDIRECT:[[Main Page]]
-!! result
+!! html
 <link rel="mw:PageProp/redirect" href="./Main_Page">
 !! end
 
@@ -6056,12 +5885,12 @@ Whitespace in #REDIRECT with optional colon
 # it for wt2html, but we don't care that it roundtrips back to the
 # modern syntax (without extra whitespace)
 parsoid=wt2html,html2html
-!! input
+!! wikitext
  
  #REDIRECT 
 : 
 [[Main Page]]
-!! result
+!! html
 <link rel="mw:PageProp/redirect" href="./Main_Page">
 !! end
 
@@ -6071,9 +5900,9 @@ Piped link in #REDIRECT
 # content after piped link is ignored.  we support this syntax,
 # but don't care that the piped link is lost when we roundtrip this.
 parsoid=wt2html
-!! input
+!! wikitext
 #REDIRECT [[Main Page|bar]]
-!! result
+!! html
 <link rel="mw:PageProp/redirect" href="./Main_Page">
 !! end
 
@@ -6081,9 +5910,9 @@ parsoid=wt2html
 Redirect to category
 !! options
 parsoid=wt2html
-!! input
+!! wikitext
 #REDIRECT [[Category:Foo]]
-!! result
+!! html
 <link rel="mw:PageProp/redirect" href="./Category:Foo"><link rel="mw:PageProp/Category" href="./Category:Foo">
 !! end
 
@@ -6091,9 +5920,9 @@ parsoid=wt2html
 Redirect to category with URL encoding
 !! options
 parsoid=wt2html
-!! input
+!! wikitext
 #REDIRECT [[Category%3AFoo]]
-!! result
+!! html
 <link rel="mw:PageProp/redirect" href="./Category:Foo"><link rel="mw:PageProp/Category" href="./Category:Foo">
 !! end
 
@@ -6101,9 +5930,9 @@ parsoid=wt2html
 Redirect to category page
 !! options
 parsoid=wt2html,html2html
-!! input
+!! wikitext
 #REDIRECT [[:Category:Foo]]
-!! result
+!! html
 <p><a rel="mw:WikiLink" href="Category:Foo">Category:Foo</a></p>
 !! end
 
@@ -6111,9 +5940,9 @@ parsoid=wt2html,html2html
 Redirect to image page (1)
 !! options
 parsoid
-!! input
+!! wikitext
 #REDIRECT [[File:Wiki.png]]
-!! result
+!! html
 <link rel="mw:PageProp/redirect" href="./File:Wiki.png">
 !! end
 
@@ -6121,9 +5950,9 @@ parsoid
 Redirect to image page (2)
 !! options
 parsoid
-!! input
+!! wikitext
 #REDIRECT [[Image:Wiki.png]]
-!! result
+!! html
 <link rel="mw:PageProp/redirect" href="./File:Wiki.png">
 !! end
 
@@ -6131,9 +5960,9 @@ parsoid
 Redirect to language
 !! options
 parsoid
-!! input
+!! wikitext
 #REDIRECT [[en:File:Wiki.png]]
-!! result
+!! html
 <link rel="mw:PageProp/redirect" href="File:Wiki.png">
 !! end
 
@@ -6141,9 +5970,9 @@ parsoid
 Redirect to interwiki
 !! options
 parsoid
-!! input
+!! wikitext
 #REDIRECT [[meatball:File:Wiki.png]]
-!! result
+!! html
 <link rel="mw:PageProp/redirect" href="File:Wiki.png">
 !! end
 
@@ -6152,9 +5981,9 @@ Non-English #REDIRECT
 !! options
 parsoid
 language=is
-!! input
+!! wikitext
 #TILVÍSUN [[Main Page]]
-!! result
+!! html
 <link rel="mw:PageProp/redirect" href="./Main_Page">
 !! end
 
@@ -6162,10 +5991,10 @@ language=is
 New redirect
 !! options
 parsoid=html2wt
-!! input
+!! wikitext
 Foo
 #REDIRECT [[Foo]]
-!! result
+!! html
 <p>Foo<link rel="mw:PageProp/redirect" href="./Foo"></p>
 !! end
 
@@ -6175,20 +6004,18 @@ Foo
 
 !! test
 <br> to <br />
-!! input
+!! wikitext
 1<br>2<br />3
-!! result
+!! html
 <p>1<br />2<br />3
 </p>
 !! end
 
 !! test
 Broken br tag sanitization
-!! options
-php
-!! input
+!! wikitext
 </br>
-!! result
+!! html/php
 <p>&lt;/br&gt;
 </p>
 !! end
@@ -6198,28 +6025,28 @@ php
 Parsoid: Broken br tag recognition
 !! options
 parsoid=wt2html
-!! input
+!! wikitext
 </br>
-!! result
+!! html/parsoid
 <p><br></p>
 !! end
 
 !! test
 Incorrecly removing closing slashes from correctly formed XHTML
-!! input
+!! wikitext
 <br style="clear:both;" />
-!! result
+!! html
 <p><br style="clear:both;" />
 </p>
 !! end
 
 !! test
 Failing to transform badly formed HTML into correct XHTML
-!! input
+!! wikitext
 <br style="clear: left;">
 <br style="clear: right;">
 <br style="clear: both;">
-!! result
+!! html
 <p><br style="clear: left;" />
 <br style="clear: right;" />
 <br style="clear: both;" />
@@ -6228,14 +6055,14 @@ Failing to transform badly formed HTML into correct XHTML
 
 !! test
 Handling html with a div self-closing tag
-!! input
+!! wikitext
 <div title />
 <div title/>
 <div title/ >
 <div title=bar />
 <div title=bar/>
 <div title=bar/ >
-!! result
+!! html
 <p>&lt;div title /&gt;
 &lt;div title/&gt;
 </p>
@@ -6250,14 +6077,14 @@ Handling html with a div self-closing tag
 
 !! test
 Handling html with a br self-closing tag
-!! input
+!! wikitext
 <br title />
 <br title/>
 <br title/ >
 <br title=bar />
 <br title=bar/>
 <br title=bar/ >
-!! result
+!! html
 <p><br title="title" />
 <br title="title" />
 <br />
@@ -6269,12 +6096,12 @@ Handling html with a br self-closing tag
 
 !! test
 Horizontal ruler (should it add that extra space?)
-!! input
+!! wikitext
 <hr>
 <hr >
 foo <hr
 > bar
-!! result
+!! html
 <hr />
 <hr />
 foo <hr /> bar
@@ -6283,28 +6110,28 @@ foo <hr /> bar
 
 !! test
 Horizontal ruler -- 4+ dashes render hr
-!! input
+!! wikitext
 ----
-!! result
+!! html
 <hr />
 
 !! end
 
 !! test
 Horizontal ruler -- eats additional dashes on the same line
-!! input
+!! wikitext
 ---------
-!! result
+!! html
 <hr />
 
 !! end
 
 !! test
 Horizontal ruler -- does not collapse dashes on consecutive lines
-!! input
+!! wikitext
 ----
 ----
-!! result
+!! html
 <hr />
 <hr />
 
@@ -6312,18 +6139,18 @@ Horizontal ruler -- does not collapse dashes on consecutive lines
 
 !! test
 Horizontal ruler -- <4 dashes render as plain text
-!! input
+!! wikitext
 ---
-!! result
+!! html
 <p>---
 </p>
 !! end
 
 !! test
 Horizontal ruler -- Supports content following dashes on same line
-!! input
+!! wikitext
 ---- Foo
-!! result
+!! html
 <hr /> Foo
 
 !! end
@@ -6333,11 +6160,11 @@ Horizontal ruler -- Supports content following dashes on same line
 ###
 !! test
 Common list
-!! input
+!! wikitext
 *Common list
 * item 2
 *item 3
-!! result
+!! html
 <ul>
 <li>Common list
 </li>
@@ -6351,11 +6178,11 @@ Common list
 
 !! test
 Numbered list
-!! input
+!! wikitext
 #Numbered list
 #item 2
 # item 3
-!! result
+!! html
 <ol>
 <li>Numbered list
 </li>
@@ -6369,7 +6196,7 @@ Numbered list
 
 !! test
 Mixed list
-!! input
+!! wikitext
 *Mixed list
 *# with numbers
 ** and bullets
@@ -6385,7 +6212,7 @@ Mixed list
 *Level 1
 *** Level 3
 #** Level 3, but ordered
-!! result
+!! html
 <ul>
 <li>Mixed list
 <ol>
@@ -6452,10 +6279,10 @@ Mixed list
 
 !! test
 Nested lists 1
-!! input
+!! wikitext
 *foo
 **bar
-!! result
+!! html
 <ul>
 <li>foo
 <ul>
@@ -6469,10 +6296,10 @@ Nested lists 1
 
 !! test
 Nested lists 2
-!! input
+!! wikitext
 **foo
 *bar
-!! result
+!! html
 <ul>
 <li><ul>
 <li>foo
@@ -6487,10 +6314,10 @@ Nested lists 2
 
 !! test
 Nested lists 3 (first element empty)
-!! input
+!! wikitext
 *
 **bar
-!! result
+!! html
 <ul>
 <li>
 <ul>
@@ -6504,10 +6331,10 @@ Nested lists 3 (first element empty)
 
 !! test
 Nested lists 4 (first element empty)
-!! input
+!! wikitext
 **
 *bar
-!! result
+!! html
 <ul>
 <li><ul>
 <li>
@@ -6522,10 +6349,10 @@ Nested lists 4 (first element empty)
 
 !! test
 Nested lists 5 (both elements empty)
-!! input
+!! wikitext
 **
 *
-!! result
+!! html
 <ul>
 <li><ul>
 <li>
@@ -6540,10 +6367,10 @@ Nested lists 5 (both elements empty)
 
 !! test
 Nested lists 6 (both elements empty)
-!! input
+!! wikitext
 *
 **
-!! result
+!! html
 <ul>
 <li>
 <ul>
@@ -6557,9 +6384,9 @@ Nested lists 6 (both elements empty)
 
 !! test
 Nested lists 7 (skip initial nesting levels)
-!! input
+!! wikitext
 *** foo
-!! result
+!! html
 <ul>
 <li><ul>
 <li><ul>
@@ -6575,12 +6402,12 @@ Nested lists 7 (skip initial nesting levels)
 
 !! test
 Nested lists 8 (multiple nesting transitions)
-!! input
+!! wikitext
 * foo
 *** bar
 ** baz
 * boo
-!! result
+!! html
 <ul>
 <li> foo
 <ul>
@@ -6601,11 +6428,11 @@ Nested lists 8 (multiple nesting transitions)
 
 !! test
 1. Lists with start-of-line-transparent tokens before bullets: Comments
-!! input
+!! wikitext
 *foo
 *<!--cmt-->bar
 <!--cmt-->*baz
-!! result
+!! html
 <ul>
 <li>foo
 </li>
@@ -6619,10 +6446,10 @@ Nested lists 8 (multiple nesting transitions)
 
 !! test
 2. Lists with start-of-line-transparent tokens before bullets: Template close
-!! input
+!! wikitext
 *foo {{echo|bar
 }}*baz
-!! result
+!! html
 <ul>
 <li>foo bar
 </li>
@@ -6634,11 +6461,11 @@ Nested lists 8 (multiple nesting transitions)
 
 !! test
 List items are not parsed correctly following a <pre> block (bug 785)
-!! input
+!! wikitext
 * <pre>foo</pre>
 * <pre>bar</pre>
 * zar
-!! result
+!! html
 <ul>
 <li> <pre>foo</pre>
 </li>
@@ -6652,7 +6479,7 @@ List items are not parsed correctly following a <pre> block (bug 785)
 
 !! test
 List items from template
-!! input
+!! wikitext
 
 {{inner list}}
 * item 2
@@ -6664,7 +6491,7 @@ List items from template
 * item 0
 * notSOL{{inner list}}
 * item 2
-!! result
+!! html
 <ul>
 <li> item 1
 </li>
@@ -6694,13 +6521,13 @@ List items from template
 
 !! test
 List interrupted by empty line or heading
-!! input
+!! wikitext
 * foo
 
 ** bar
 == A heading ==
 * Another list item
-!! result
+!! html
 <ul>
 <li> foo
 </li>
@@ -6722,11 +6549,11 @@ List interrupted by empty line or heading
 
 !!test
 Multiple list tags generated by templates
-!!input
+!! wikitext
 {{echo|<li>}}a
 {{echo|<li>}}b
 {{echo|<li>}}c
-!!result
+!! html
 <li>a
 <li>b
 <li>c</li>
@@ -6737,7 +6564,7 @@ Multiple list tags generated by templates
 
 !!test
 Single-comment whitespace lines dont break lists, and neither do multi-comment whitespace lines
-!!input
+!! wikitext
 *a
 <!--This line will NOT split the list-->
 *b
@@ -6745,7 +6572,7 @@ Single-comment whitespace lines dont break lists, and neither do multi-comment w
 *c
  <!--foo--> <!----> <!--This line NOT split the list either--> 
 *d
-!!result
+!! html
 <ul>
 <li>a
 </li>
@@ -6761,7 +6588,7 @@ Single-comment whitespace lines dont break lists, and neither do multi-comment w
 
 !!test
 Replacing whitespace with tabs still doesn't break the list (gerrit 78327)
-!!input
+!! wikitext
 *a
 <!--This line will NOT split the list-->       
 *b
@@ -6770,7 +6597,7 @@ Replacing whitespace with tabs still doesn't break the list (gerrit 78327)
        <!--foo--> <!---->      <!--This line NOT split the list
         either-->       
 *d
-!!result
+!! html
 <ul>
 <li>a
 </li>
@@ -6789,7 +6616,7 @@ Test the li-hack
 (Cannot test this with PHP parser since it relies on Tidy for the hack)
 !!options
 parsoid=wt2html,wt2wt
-!!input
+!! wikitext
 * foo
 * <li>li-hack
 * {{echo|<li>templated li-hack}}
@@ -6799,7 +6626,7 @@ parsoid=wt2html,wt2wt
 <li><li>not a li-hack
 </li>
 </ul>
-!!result
+!! html
 <ul>
 <li> foo</li>
 <li>li-hack</li>
@@ -6819,14 +6646,14 @@ parsoid=wt2html,wt2wt
 Parsoid: Make sure nested lists are serialized on their own line even if HTML contains no newlines
 !! options
 parsoid
-!! input
+!! wikitext
 # foo
 ## bar
 * foo
 ** bar
 : foo
 :: bar
-!! result
+!! html
 <ol>
 <li> foo<ol>
 <li> bar</li>
@@ -6846,9 +6673,9 @@ parsoid
 Parsoid: Test of whitespace serialization with Templated bullets
 !! options
 parsoid
-!! input
+!! wikitext
 * {{bullet}}
-!! result
+!! html
 <ul>
 <li> </li><li about="#mwt1" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"bullet","href":"./Template:Bullet"},"params":{},"i":0}}]}'> Bar</li>
 </ul>
@@ -6862,13 +6689,11 @@ parsoid
 !! test
 Unbalanced closing block tags break a list
 (Parsoid-only since php parser generates broken html -- relies on Tidy to fix up)
-!! options
-parsoid
-!! input
+!! wikitext
 <div>
 *a</div><div>
 *b</div>
-!! result
+!! html/parsoid
 <div>
 <ul>
 <li>a
@@ -6883,13 +6708,11 @@ parsoid
 !! test
 Unbalanced closing non-block tags don't break a list
 (Parsoid-only since php parser generates broken html -- relies on Tidy to fix up)
-!! options
-parsoid
-!! input
+!! wikitext
 <span>
 *a</span><span>
 *b</span>
-!! result
+!! html/parsoid
 <p><span></span>
 </p>
 <ul>
@@ -6903,12 +6726,10 @@ parsoid
 !! test
 Unclosed formatting tags that straddle lists are closed and reopened
 (Parsoid-only since php parser generates broken html -- relies on Tidy to fix up)
-!! options
-parsoid
-!! input
+!! wikitext
 # <s> a
 # b </s>
-!! result
+!! html/parsoid
 <ol>
 <li> <s> a </s>
 </li>
@@ -6920,13 +6741,11 @@ parsoid
 !!test
 List embedded in a non-block tag
 (Ugly Parsoid output -- worth fixing; Disabled for PHP parser since it relies on Tidy)
-!! options
-parsoid
-!!input
+!! wikitext
 <small>
 * foo
 </small>
-!!result
+!! html/parsoid
 <p><small></small></p>
 <small>
 <ul>
@@ -6940,12 +6759,12 @@ parsoid
 Table with missing opening <tr> tag
 !! options
 parsoid=wt2html,wt2wt
-!! input
+!! wikitext
 <table>
 <td>foo</td>
 </tr>
 </table>
-!! result
+!! html/parsoid
 <table>
 <tr>
 <td>foo</td>
@@ -6964,133 +6783,133 @@ parsoid=wt2html,wt2wt
 
 !! test
 Magic Word: {{CURRENTDAY}}
-!! input
+!! wikitext
 {{CURRENTDAY}}
-!! result
+!! html
 <p>1
 </p>
 !! end
 
 !! test
 Magic Word: {{CURRENTDAY2}}
-!! input
+!! wikitext
 {{CURRENTDAY2}}
-!! result
+!! html
 <p>01
 </p>
 !! end
 
 !! test
 Magic Word: {{CURRENTDAYNAME}}
-!! input
+!! wikitext
 {{CURRENTDAYNAME}}
-!! result
+!! html
 <p>Thursday
 </p>
 !! end
 
 !! test
 Magic Word: {{CURRENTDOW}}
-!! input
+!! wikitext
 {{CURRENTDOW}}
-!! result
+!! html
 <p>4
 </p>
 !! end
 
 !! test
 Magic Word: {{CURRENTMONTH}}
-!! input
+!! wikitext
 {{CURRENTMONTH}}
-!! result
+!! html
 <p>01
 </p>
 !! end
 
 !! test
 Magic Word: {{CURRENTMONTH1}}
-!! input
+!! wikitext
 {{CURRENTMONTH1}}
-!! result
+!! html
 <p>1
 </p>
 !! end
 
 !! test
 Magic Word: {{CURRENTMONTHABBREV}}
-!! input
+!! wikitext
 {{CURRENTMONTHABBREV}}
-!! result
+!! html
 <p>Jan
 </p>
 !! end
 
 !! test
 Magic Word: {{CURRENTMONTHNAME}}
-!! input
+!! wikitext
 {{CURRENTMONTHNAME}}
-!! result
+!! html
 <p>January
 </p>
 !! end
 
 !! test
 Magic Word: {{CURRENTMONTHNAMEGEN}}
-!! input
+!! wikitext
 {{CURRENTMONTHNAMEGEN}}
-!! result
+!! html
 <p>January
 </p>
 !! end
 
 !! test
 Magic Word: {{CURRENTTIME}}
-!! input
+!! wikitext
 {{CURRENTTIME}}
-!! result
+!! html
 <p>00:02
 </p>
 !! end
 
 !! test
 Magic Word: {{CURRENTHOUR}}
-!! input
+!! wikitext
 {{CURRENTHOUR}}
-!! result
+!! html
 <p>00
 </p>
 !! end
 
 !! test
 Magic Word: {{CURRENTWEEK}} (@bug 4594)
-!! input
+!! wikitext
 {{CURRENTWEEK}}
-!! result
+!! html
 <p>1
 </p>
 !! end
 
 !! test
 Magic Word: {{CURRENTYEAR}}
-!! input
+!! wikitext
 {{CURRENTYEAR}}
-!! result
+!! html
 <p>1970
 </p>
 !! end
 
 !! test
 Magic Word: {{CURRENTTIMESTAMP}}
-!! input
+!! wikitext
 {{CURRENTTIMESTAMP}}
-!! result
+!! html
 <p>19700101000203
 </p>
 !! end
 
 !! test
 Magic Words LOCAL (UTC)
-!! input
+!! wikitext
 * {{LOCALMONTH}}
 * {{LOCALMONTH1}}
 * {{LOCALMONTHNAME}}
@@ -7105,7 +6924,7 @@ Magic Words LOCAL (UTC)
 * {{LOCALWEEK}}
 * {{LOCALDOW}}
 * {{LOCALTIMESTAMP}}
-!! result
+!! html
 <ul>
 <li> 01
 </li>
@@ -7143,9 +6962,9 @@ Magic Words LOCAL (UTC)
 Magic Word: {{FULLPAGENAME}}
 !! options
 title=[[User:Ævar Arnfjörð Bjarmason]]
-!! input
+!! wikitext
 {{FULLPAGENAME}}
-!! result
+!! html
 <p>User:Ævar Arnfjörð Bjarmason
 </p>
 !! end
@@ -7154,9 +6973,9 @@ title=[[User:Ævar Arnfjörð Bjarmason]]
 Magic Word: {{FULLPAGENAMEE}}
 !! options
 title=[[User:Ævar Arnfjörð Bjarmason]]
-!! input
+!! wikitext
 {{FULLPAGENAMEE}}
-!! result
+!! html
 <p>User:%C3%86var_Arnfj%C3%B6r%C3%B0_Bjarmason
 </p>
 !! end
@@ -7165,9 +6984,9 @@ title=[[User:Ævar Arnfjörð Bjarmason]]
 Magic Word: {{TALKSPACE}}
 !! options
 title=[[User:Ævar Arnfjörð Bjarmason]]
-!! input
+!! wikitext
 {{TALKSPACE}}
-!! result
+!! html
 <p>User talk
 </p>
 !! end
@@ -7176,9 +6995,9 @@ title=[[User:Ævar Arnfjörð Bjarmason]]
 Magic Word: {{TALKSPACE}}, same namespace
 !! options
 title=[[User talk:Ævar Arnfjörð Bjarmason]]
-!! input
+!! wikitext
 {{TALKSPACE}}
-!! result
+!! html
 <p>User talk
 </p>
 !! end
@@ -7187,9 +7006,9 @@ title=[[User talk:Ævar Arnfjörð Bjarmason]]
 Magic Word: {{TALKSPACE}}, main namespace
 !! options
 title=[[Parser Test]]
-!! input
+!! wikitext
 {{TALKSPACE}}
-!! result
+!! html
 <p>Talk
 </p>
 !! end
@@ -7198,9 +7017,9 @@ title=[[Parser Test]]
 Magic Word: {{TALKSPACEE}}
 !! options
 title=[[User:Ævar Arnfjörð Bjarmason]]
-!! input
+!! wikitext
 {{TALKSPACEE}}
-!! result
+!! html
 <p>User_talk
 </p>
 !! end
@@ -7209,9 +7028,9 @@ title=[[User:Ævar Arnfjörð Bjarmason]]
 Magic Word: {{SUBJECTSPACE}}
 !! options
 title=[[User talk:Ævar Arnfjörð Bjarmason]]
-!! input
+!! wikitext
 {{SUBJECTSPACE}}
-!! result
+!! html
 <p>User
 </p>
 !! end
@@ -7220,9 +7039,9 @@ title=[[User talk:Ævar Arnfjörð Bjarmason]]
 Magic Word: {{SUBJECTSPACE}}, same namespace
 !! options
 title=[[User:Ævar Arnfjörð Bjarmason]]
-!! input
+!! wikitext
 {{SUBJECTSPACE}}
-!! result
+!! html
 <p>User
 </p>
 !! end
@@ -7231,9 +7050,9 @@ title=[[User:Ævar Arnfjörð Bjarmason]]
 Magic Word: {{SUBJECTSPACE}}, main namespace
 !! options
 title=[[Parser Test]]
-!! input
+!! wikitext
 {{SUBJECTSPACE}}
-!! result
+!! html
 
 !! end
 
@@ -7241,9 +7060,9 @@ title=[[Parser Test]]
 Magic Word: {{SUBJECTSPACEE}}
 !! options
 title=[[User talk:Ævar Arnfjörð Bjarmason]]
-!! input
+!! wikitext
 {{SUBJECTSPACEE}}
-!! result
+!! html
 <p>User
 </p>
 !! end
@@ -7252,9 +7071,9 @@ title=[[User talk:Ævar Arnfjörð Bjarmason]]
 Magic Word: {{NAMESPACE}}
 !! options
 title=[[User:Ævar Arnfjörð Bjarmason]]
-!! input
+!! wikitext
 {{NAMESPACE}}
-!! result
+!! html
 <p>User
 </p>
 !! end
@@ -7263,9 +7082,9 @@ title=[[User:Ævar Arnfjörð Bjarmason]]
 Magic Word: {{NAMESPACEE}}
 !! options
 title=[[User:Ævar Arnfjörð Bjarmason]]
-!! input
+!! wikitext
 {{NAMESPACEE}}
-!! result
+!! html
 <p>User
 </p>
 !! end
@@ -7274,9 +7093,9 @@ title=[[User:Ævar Arnfjörð Bjarmason]]
 Magic Word: {{NAMESPACENUMBER}}
 !! options
 title=[[User:Ævar Arnfjörð Bjarmason]]
-!! input
+!! wikitext
 {{NAMESPACENUMBER}}
-!! result
+!! html
 <p>2
 </p>
 !! end
@@ -7285,9 +7104,9 @@ title=[[User:Ævar Arnfjörð Bjarmason]]
 Magic Word: {{SUBPAGENAME}}
 !! options
 title=[[Ævar Arnfjörð Bjarmason/sub ö]] subpage
-!! input
+!! wikitext
 {{SUBPAGENAME}}
-!! result
+!! html
 <p>sub ö
 </p>
 !! end
@@ -7296,9 +7115,9 @@ title=[[Ævar Arnfjörð Bjarmason/sub ö]] subpage
 Magic Word: {{SUBPAGENAMEE}}
 !! options
 title=[[Ævar Arnfjörð Bjarmason/sub ö]] subpage
-!! input
+!! wikitext
 {{SUBPAGENAMEE}}
-!! result
+!! html
 <p>sub_%C3%B6
 </p>
 !! end
@@ -7307,9 +7126,9 @@ title=[[Ævar Arnfjörð Bjarmason/sub ö]] subpage
 Magic Word: {{ROOTPAGENAME}}
 !! options
 title=[[Ævar Arnfjörð Bjarmason/sub/sub2]] subpage
-!! input
+!! wikitext
 {{ROOTPAGENAME}}
-!! result
+!! html
 <p>Ævar Arnfjörð Bjarmason
 </p>
 !! end
@@ -7318,9 +7137,9 @@ title=[[Ævar Arnfjörð Bjarmason/sub/sub2]] subpage
 Magic Word: {{ROOTPAGENAMEE}}
 !! options
 title=[[Ævar Arnfjörð Bjarmason/sub/sub2]] subpage
-!! input
+!! wikitext
 {{ROOTPAGENAMEE}}
-!! result
+!! html
 <p>%C3%86var_Arnfj%C3%B6r%C3%B0_Bjarmason
 </p>
 !! end
@@ -7329,9 +7148,9 @@ title=[[Ævar Arnfjörð Bjarmason/sub/sub2]] subpage
 Magic Word: {{BASEPAGENAME}}
 !! options
 title=[[Ævar Arnfjörð Bjarmason/sub]] subpage
-!! input
+!! wikitext
 {{BASEPAGENAME}}
-!! result
+!! html
 <p>Ævar Arnfjörð Bjarmason
 </p>
 !! end
@@ -7340,9 +7159,9 @@ title=[[Ævar Arnfjörð Bjarmason/sub]] subpage
 Magic Word: {{BASEPAGENAMEE}}
 !! options
 title=[[Ævar Arnfjörð Bjarmason/sub]] subpage
-!! input
+!! wikitext
 {{BASEPAGENAMEE}}
-!! result
+!! html
 <p>%C3%86var_Arnfj%C3%B6r%C3%B0_Bjarmason
 </p>
 !! end
@@ -7351,9 +7170,9 @@ title=[[Ævar Arnfjörð Bjarmason/sub]] subpage
 Magic Word: {{TALKPAGENAME}}
 !! options
 title=[[User:Ævar Arnfjörð Bjarmason]]
-!! input
+!! wikitext
 {{TALKPAGENAME}}
-!! result
+!! html
 <p>User talk:Ævar Arnfjörð Bjarmason
 </p>
 !! end
@@ -7362,9 +7181,9 @@ title=[[User:Ævar Arnfjörð Bjarmason]]
 Magic Word: {{TALKPAGENAMEE}}
 !! options
 title=[[User:Ævar Arnfjörð Bjarmason]]
-!! input
+!! wikitext
 {{TALKPAGENAMEE}}
-!! result
+!! html
 <p>User_talk:%C3%86var_Arnfj%C3%B6r%C3%B0_Bjarmason
 </p>
 !! end
@@ -7373,9 +7192,9 @@ title=[[User:Ævar Arnfjörð Bjarmason]]
 Magic Word: {{SUBJECTPAGENAME}}
 !! options
 title=[[User talk:Ævar Arnfjörð Bjarmason]]
-!! input
+!! wikitext
 {{SUBJECTPAGENAME}}
-!! result
+!! html
 <p>User:Ævar Arnfjörð Bjarmason
 </p>
 !! end
@@ -7384,18 +7203,18 @@ title=[[User talk:Ævar Arnfjörð Bjarmason]]
 Magic Word: {{SUBJECTPAGENAMEE}}
 !! options
 title=[[User talk:Ævar Arnfjörð Bjarmason]]
-!! input
+!! wikitext
 {{SUBJECTPAGENAMEE}}
-!! result
+!! html
 <p>User:%C3%86var_Arnfj%C3%B6r%C3%B0_Bjarmason
 </p>
 !! end
 
 !! test
 Magic Word: {{NUMBEROFFILES}}
-!! input
+!! wikitext
 {{NUMBEROFFILES}}
-!! result
+!! html
 <p>4
 </p>
 !! end
@@ -7404,9 +7223,9 @@ Magic Word: {{NUMBEROFFILES}}
 Magic Word: {{PAGENAME}}
 !! options
 title=[[User:Ævar Arnfjörð Bjarmason]]
-!! input
+!! wikitext
 {{PAGENAME}}
-!! result
+!! html
 <p>Ævar Arnfjörð Bjarmason
 </p>
 !! end
@@ -7415,9 +7234,9 @@ title=[[User:Ævar Arnfjörð Bjarmason]]
 Magic Word: {{PAGENAME}} with metacharacters
 !! options
 title=[['foo & bar = baz']]
-!! input
+!! wikitext
 ''{{PAGENAME}}''
-!! result
+!! html
 <p><i>&#39;foo &#38; bar &#61; baz&#39;</i>
 </p>
 !! end
@@ -7426,9 +7245,9 @@ title=[['foo & bar = baz']]
 Magic Word: {{PAGENAME}} with metacharacters (bug 26781)
 !! options
 title=[[*RFC 1234 http://example.com/]]
-!! input
+!! wikitext
 {{PAGENAME}}
-!! result
+!! html
 <p>&#42;RFC&#32;1234 http&#58;//example.com/
 </p>
 !! end
@@ -7437,9 +7256,9 @@ title=[[*RFC 1234 http://example.com/]]
 Magic Word: {{PAGENAMEE}}
 !! options
 title=[[User:Ævar Arnfjörð Bjarmason]]
-!! input
+!! wikitext
 {{PAGENAMEE}}
-!! result
+!! html
 <p>%C3%86var_Arnfj%C3%B6r%C3%B0_Bjarmason
 </p>
 !! end
@@ -7448,75 +7267,75 @@ title=[[User:Ævar Arnfjörð Bjarmason]]
 Magic Word: {{PAGENAMEE}} with metacharacters (bug 26781)
 !! options
 title=[[*RFC 1234 http://example.com/]]
-!! input
+!! wikitext
 {{PAGENAMEE}}
-!! result
+!! html
 <p>&#42;RFC_1234_http&#58;//example.com/
 </p>
 !! end
 
 !! test
 Magic Word: {{REVISIONID}}
-!! input
+!! wikitext
 {{REVISIONID}}
-!! result
+!! html
 <p>1337
 </p>
 !! end
 
 !! test
 Magic Word: {{SCRIPTPATH}}
-!! input
+!! wikitext
 {{SCRIPTPATH}}
-!! result
+!! html
 <p>/
 </p>
 !! end
 
 !! test
 Magic Word: {{STYLEPATH}}
-!! input
+!! wikitext
 {{STYLEPATH}}
-!! result
+!! html
 <p>/skins
 </p>
 !! end
 
 !! test
 Magic Word: {{SERVER}}
-!! input
+!! wikitext
 {{SERVER}}
-!! result
+!! html
 <p><a rel="nofollow" class="external free" href="http://example.org">http://example.org</a>
 </p>
 !! end
 
 !! test
 Magic Word: {{SERVERNAME}}
-!! input
+!! wikitext
 {{SERVERNAME}}
-!! result
+!! html
 <p>example.org
 </p>
 !! end
 
 !! test
 Magic Word: {{SITENAME}}
-!! input
+!! wikitext
 {{SITENAME}}
-!! result
+!! html
 <p>MediaWiki
 </p>
 !! end
 
 !! test
 Case-sensitive magic words, when cased differently, should just be template transclusions
-!! input
+!! wikitext
 {{CurrentMonth}}
 {{currentday}}
 {{cURreNTweEK}}
 {{currentHour}}
-!! result
+!! html
 <p><a href="/index.php?title=Template:CurrentMonth&amp;action=edit&amp;redlink=1" class="new" title="Template:CurrentMonth (page does not exist)">Template:CurrentMonth</a>
 <a href="/index.php?title=Template:Currentday&amp;action=edit&amp;redlink=1" class="new" title="Template:Currentday (page does not exist)">Template:Currentday</a>
 <a href="/index.php?title=Template:CURreNTweEK&amp;action=edit&amp;redlink=1" class="new" title="Template:CURreNTweEK (page does not exist)">Template:CURreNTweEK</a>
@@ -7526,12 +7345,12 @@ Case-sensitive magic words, when cased differently, should just be template tran
 
 !! test
 Case-insensitive magic words should still work with weird casing.
-!! input
+!! wikitext
 {{sErVeRNaMe}}
 {{LCFirst:AOEU}}
 {{ucFIRST:aoeu}}
 {{SERver}}
-!! result
+!! html
 <p>example.org
 aOEU
 Aoeu
@@ -7541,88 +7360,88 @@ Aoeu
 
 !! test
 Namespace 1 {{ns:1}}
-!! input
+!! wikitext
 {{ns:1}}
-!! result
+!! html
 <p>Talk
 </p>
 !! end
 
 !! test
 Namespace 1 {{ns:01}}
-!! input
+!! wikitext
 {{ns:01}}
-!! result
+!! html
 <p>Talk
 </p>
 !! end
 
 !! test
 Namespace 0 {{ns:0}} (bug 4783)
-!! input
+!! wikitext
 {{ns:0}}
-!! result
+!! html
 
 !! end
 
 !! test
 Namespace 0 {{ns:00}} (bug 4783)
-!! input
+!! wikitext
 {{ns:00}}
-!! result
+!! html
 
 !! end
 
 !! test
 Namespace -1 {{ns:-1}}
-!! input
+!! wikitext
 {{ns:-1}}
-!! result
+!! html
 <p>Special
 </p>
 !! end
 
 !! test
 Namespace User {{ns:User}}
-!! input
+!! wikitext
 {{ns:User}}
-!! result
+!! html
 <p>User
 </p>
 !! end
 
 !! test
 Namespace User talk {{ns:User_talk}}
-!! input
+!! wikitext
 {{ns:User_talk}}
-!! result
+!! html
 <p>User talk
 </p>
 !! end
 
 !! test
 Namespace User talk {{ns:uSeR tAlK}}
-!! input
+!! wikitext
 {{ns:uSeR tAlK}}
-!! result
+!! html
 <p>User talk
 </p>
 !! end
 
 !! test
 Namespace File {{ns:File}}
-!! input
+!! wikitext
 {{ns:File}}
-!! result
+!! html
 <p>File
 </p>
 !! end
 
 !! test
 Namespace File {{ns:Image}}
-!! input
+!! wikitext
 {{ns:Image}}
-!! result
+!! html
 <p>File
 </p>
 !! end
@@ -7631,9 +7450,9 @@ Namespace File {{ns:Image}}
 Namespace (lang=de) Benutzer {{ns:User}}
 !! options
 language=de
-!! input
+!! wikitext
 {{ns:User}}
-!! result
+!! html
 <p>Benutzer
 </p>
 !! end
@@ -7642,9 +7461,9 @@ language=de
 Namespace (lang=de) Benutzer Diskussion {{ns:3}}
 !! options
 language=de
-!! input
+!! wikitext
 {{ns:3}}
-!! result
+!! html
 <p>Benutzer Diskussion
 </p>
 !! end
@@ -7652,12 +7471,12 @@ language=de
 
 !! test
 Urlencode
-!! input
+!! wikitext
 {{urlencode:hi world?!}}
 {{urlencode:hi world?!|WIKI}}
 {{urlencode:hi world?!|PATH}}
 {{urlencode:hi world?!|QUERY}}
-!! result
+!! html
 <p>hi+world%3F%21
 hi_world%3F!
 hi%20world%3F%21
@@ -7669,9 +7488,9 @@ hi+world%3F%21
 Magic Word: prioritize type info over data-parsoid
 !! options
 parsoid=html2wt
-!! input
+!! wikitext
 __FORCETOC__
-!! result
+!! html
 <meta property="mw:PageProp/forcetoc" data-parsoid='{"src":"__NOTOC__","magicSrc":"__NOTOC__"}'/>
 !! end
 
@@ -7679,11 +7498,11 @@ __FORCETOC__
 Magic Word: serialize on separate line (parsoid)
 !! options
 parsoid=wt2wt,html2wt
-!! input
+!! wikitext
 foo
 __NOTOC__
 bar
-!! result
+!! html
 foo<meta property="mw:PageProp/notoc"/>bar
 !! end
 
@@ -7692,9 +7511,9 @@ Magic Word: rt non-english wikis
 !! options
 parsoid=wt2wt
 language=de
-!! input
+!! wikitext
 __NOEDITSECTION__
-!! result
+!! html
 <meta property="mw:PageProp/noeditsection" data-parsoid='{"src":"__NOEDITSECTION__","magicSrc":"__NOEDITSECTION__"}'/>
 !! end
 
@@ -7703,36 +7522,36 @@ __NOEDITSECTION__
 ###
 !! test
 Magic links: internal link to RFC (bug 479)
-!! input
+!! wikitext
 [[RFC 123]]
-!! result
+!! html
 <p><a href="/index.php?title=RFC_123&amp;action=edit&amp;redlink=1" class="new" title="RFC 123 (page does not exist)">RFC 123</a>
 </p>
 !! end
 
 !! test
 Magic links: RFC (bug 479)
-!! input
+!! wikitext
 RFC 822
-!! result
+!! html
 <p><a class="external mw-magiclink-rfc" rel="nofollow" href="//tools.ietf.org/html/rfc822">RFC 822</a>
 </p>
 !! end
 
 !! test
 Magic links: ISBN (bug 1937)
-!! input
+!! wikitext
 ISBN 0-306-40615-2
-!! result
+!! html
 <p><a href="/wiki/Special:BookSources/0306406152" class="internal mw-magiclink-isbn">ISBN 0-306-40615-2</a>
 </p>
 !! end
 
 !! test
 Magic links: PMID incorrectly converts space to underscore
-!! input
+!! wikitext
 PMID 1234
-!! result
+!! html
 <p><a class="external mw-magiclink-pmid" rel="nofollow" href="//www.ncbi.nlm.nih.gov/pubmed/1234?dopt=Abstract">PMID 1234</a>
 </p>
 !! end
@@ -7743,49 +7562,39 @@ PMID 1234
 
 !! test
 Nonexistent template
-!! input
+!! wikitext
 {{thistemplatedoesnotexist}}
-!! result
+!! html
 <p><a href="/index.php?title=Template:Thistemplatedoesnotexist&amp;action=edit&amp;redlink=1" class="new" title="Template:Thistemplatedoesnotexist (page does not exist)">Template:Thistemplatedoesnotexist</a>
 </p>
 !! end
 
 !! test
 Template with invalid target containing tags
-!! input
+!! wikitext
 {{a<b>b</b>|{{echo|foo}}|{{echo|a}}={{echo|b}}|a = b}}
-!! result
+!! html
 <p>{{a<b>b</b>|foo|a=b|a = b}}
 </p>
 !! end
 
 !! test
 Template with invalid target containing unclosed tag
-!! input
+!! wikitext
 {{a<b>|{{echo|foo}}|{{echo|a}}={{echo|b}}|a = b}}
-!! result
+!! html
 <p>{{a<b>|foo|a=b|a = b}}</b>
 </p>
 !! end
 
 !! test
-Template with invalid target containing wikilink (php)
-!! options
-php
-!! input
+Template with invalid target containing wikilink
+!! wikitext
 {{[[Main Page]]}}
-!! result
+!! html/php
 <p>{{<a href="/wiki/Main_Page" title="Main Page">Main Page</a>}}
 </p>
-!! end
-
-!! test
-Template with invalid target containing wikilink (parsoid)
-!! options
-parsoid
-!! input
-{{[[Main Page]]}}
-!! result
+!! html/parsoid
 <p><span typeof="mw:Transclusion" about="#mwt1" data-mw='{"parts":[{"template":{"target":{"wt":"[[Main Page]]"},"params":{},"i":0}}]}'>{{</span><a rel="mw:WikiLink" href="./Main_Page" about="#mwt1">Main Page</a><span about="#mwt1">}}</span></p>
 !! end
 
@@ -7797,18 +7606,18 @@ This is a test template
 
 !! test
 Simple template
-!! input
+!! wikitext
 {{test}}
-!! result
+!! html
 <p>This is a test template
 </p>
 !! end
 
 !! test
 Template with explicit namespace
-!! input
+!! wikitext
 {{Template:test}}
-!! result
+!! html
 <p>This is a test template
 </p>
 !! end
@@ -7822,9 +7631,9 @@ This is a test template with parameter {{{param}}}
 
 !! test
 Template parameter
-!! input
+!! wikitext
 {{paramtest|param=foo}}
-!! result
+!! html
 <p>This is a test template with parameter foo
 </p>
 !! end
@@ -7837,9 +7646,9 @@ Template:paramtestnum
 
 !! test
 Template unnamed parameter
-!! input
+!! wikitext
 {{paramtestnum|Main Page|the main page}}
-!! result
+!! html
 <p><a href="/wiki/Main_Page" title="Main Page">the main page</a>
 </p>
 !! end
@@ -7876,27 +7685,27 @@ Template:templateasargtest2
 
 !! test
 Template with template name as unnamed argument
-!! input
+!! wikitext
 {{templateasargtestnum|templatesimple}}
-!! result
+!! html
 <p>(test)
 </p>
 !! end
 
 !! test
 Template with template name as argument
-!! input
+!! wikitext
 {{templateasargtest|templ=simple}}
-!! result
+!! html
 <p>(test)
 </p>
 !! end
 
 !! test
 Template with template name as argument (2)
-!! input
+!! wikitext
 {{templateasargtest2|templ=templatesimple}}
-!! result
+!! html
 <p>(test)
 </p>
 !! end
@@ -7915,58 +7724,58 @@ Template:templa
 
 !! test
 Template with default value
-!! input
+!! wikitext
 {{templateasargtestdefault}}
-!! result
+!! html
 <p>(test)
 </p>
 !! end
 
 !! test
 Template with default value (value set)
-!! input
+!! wikitext
 {{templateasargtestdefault|templ=templa}}
-!! result
+!! html
 <p><b>templ</b>
 </p>
 !! end
 
 !! test
 Template redirect
-!! input
+!! wikitext
 {{templateredirect}}
-!! result
+!! html
 <p>(test)
 </p>
 !! end
 
 !! test
 Template with argument in separate line
-!! input
+!! wikitext
 {{ templateasargtest  |
  templ = simple }}
-!! result
+!! html
 <p>(test)
 </p>
 !! end
 
 !! test
 Template with complex template as argument
-!! input
+!! wikitext
 {{paramtest|
   param ={{ templateasargtest  |
  templ = simple }}}}
-!! result
+!! html
 <p>This is a test template with parameter (test)
 </p>
 !! end
 
 !! test
 Template with thumb image (with link in description)
-!! input
+!! wikitext
 {{paramtest|
   param =[[Image:noimage.png|thumb|[[no link|link]] [[no link|caption]]]]}}
-!! result
+!! html
 This is a test template with parameter <div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/index.php?title=Special:Upload&amp;wpDestFile=Noimage.png" class="new" title="File:Noimage.png">File:Noimage.png</a>  <div class="thumbcaption"><a href="/index.php?title=No_link&amp;action=edit&amp;redlink=1" class="new" title="No link (page does not exist)">link</a> <a href="/index.php?title=No_link&amp;action=edit&amp;redlink=1" class="new" title="No link (page does not exist)">caption</a></div></div></div>
 
 !! end
@@ -7980,22 +7789,22 @@ Template:complextemplate
 
 !! test
 Template with complex arguments
-!! input
+!! wikitext
 {{complextemplate|
   param ={{ templateasargtest  |
  templ = simple }}|[[Template:complextemplate|link]]}}
-!! result
+!! html
 <p><a href="/wiki/Template:Complextemplate" title="Template:Complextemplate">link</a> This is a test template with parameter (test)
 </p>
 !! end
 
 !! test
 BUG 553: link with two variables in a piped link
-!! input
+!! wikitext
 {|
 |[[{{{1}}}|{{{2}}}]]
 |}
-!! result
+!! html
 <table>
 <tr>
 <td>[[{{{1}}}|{{{2}}}]]
@@ -8005,9 +7814,9 @@ BUG 553: link with two variables in a piped link
 
 !! test
 Magic variable as template parameter
-!! input
+!! wikitext
 {{paramtest|param={{SITENAME}}}}
-!! result
+!! html
 <p>This is a test template with parameter MediaWiki
 </p>
 !! end
@@ -8020,18 +7829,18 @@ Template:linktest
 
 !! test
 Template parameter as link source
-!! input
+!! wikitext
 {{linktest|param=Main Page}}
-!! result
+!! html
 <p><a href="/wiki/Main_Page" title="Main Page">link</a>
 </p>
 !! end
 
 !!test
 Template-generated attribute string (k='v')
-!!input
+!! wikitext
 <span {{attr_str|id|v1}}>bar</span>
-!!result
+!! html
 <p><span id="v1">bar</span>
 </p>
 !!end
@@ -8044,9 +7853,9 @@ including another template, {{paramtest|param={{{arg}}}}}
 
 !! test
 Template passing argument to another template
-!! input
+!! wikitext
 {{paramtest2|arg='hmm'}}
-!! result
+!! html
 <p>including another template, This is a test template with parameter 'hmm'
 </p>
 !! end
@@ -8059,13 +7868,13 @@ Main Page
 
 !! test
 Template as link source
-!! input
+!! wikitext
 [[{{linktest2}}]]
 
 [[{{linktest2}}|Main Page]]
 
 [[{{linktest2}}]]Page
-!! result
+!! html
 <p><a href="/wiki/Main_Page" title="Main Page">Main Page</a>
 </p><p><a href="/wiki/Main_Page" title="Main Page">Main Page</a>
 </p><p><a href="/wiki/Main_Page" title="Main Page">Main Page</a>Page
@@ -8087,18 +7896,18 @@ Template:loop2
 
 !! test
 Template infinite loop
-!! input
+!! wikitext
 {{loop1}}
-!! result
+!! html
 <p><span class="error">Template loop detected: <a href="/wiki/Template:Loop1" title="Template:Loop1">Template:Loop1</a></span>
 </p>
 !! end
 
 !! test
 Template from main namespace
-!! input
+!! wikitext
 {{:Main Page}}
-!! result
+!! html
 <p>blah blah
 </p>
 !! end
@@ -8115,9 +7924,9 @@ Template:table
 
 !! test
 BUG 529: Template with table, not included at beginning of line
-!! input
+!! wikitext
 foo {{table}}
-!! result
+!! html
 <p>foo 
 </p>
 <table>
@@ -8134,10 +7943,10 @@ foo {{table}}
 
 !! test
 BUG 523: Template shouldn't eat newline (or add an extra one before table)
-!! input
+!! wikitext
 foo
 {{table}}
-!! result
+!! html
 <p>foo
 </p>
 <table>
@@ -8154,22 +7963,22 @@ foo
 
 !! test
 BUG 41: Template parameters shown as broken links
-!! input
+!! wikitext
 {{{parameter}}}
-!! result
+!! html
 <p>{{{parameter}}}
 </p>
 !! end
 
 !! test
 Template with targets containing wikilinks
-!! input
+!! wikitext
 {{[[foo]]}}
 
 {{[[{{echo|foo}}]]}}
 
 {{{{echo|[[foo}}]]}}
-!! result
+!! html
 <p>{{<a href="/index.php?title=Foo&amp;action=edit&amp;redlink=1" class="new" title="Foo (page does not exist)">foo</a>}}
 </p><p>{{<a href="/index.php?title=Foo&amp;action=edit&amp;redlink=1" class="new" title="Foo (page does not exist)">foo</a>}}
 </p><p>{{[[foo}}]]
@@ -8190,9 +7999,9 @@ Template:MSGNW test
 msgnw keyword
 !! options
 disabled
-!! input
+!! wikitext
 {{msgnw:MSGNW test}}
-!! result
+!! html
 <p>''None'' of '''this''' should be 
 * interpreted
  but rather passed unmodified
@@ -8202,9 +8011,9 @@ disabled
 
 !! test
 int keyword
-!! input
+!! wikitext
 {{int:youhavenewmessages|lots of money|not!}}
-!! result
+!! html
 <p>You have lots of money (not!).
 </p>
 !! end
@@ -8217,9 +8026,9 @@ Foo<noinclude>zar</noinclude><includeonly>bar</includeonly>
 
 !! test
 <includeonly> and <noinclude> being included
-!! input
+!! wikitext
 {{Includes}}
-!! result
+!! html
 <p>Foobar
 </p>
 !! end
@@ -8232,9 +8041,9 @@ Template:Includes2
 
 !! test
 <onlyinclude> being included
-!! input
+!! wikitext
 {{Includes2}}
-!! result
+!! html
 <p>Foo
 </p>
 !! end
@@ -8248,66 +8057,66 @@ Template:Includes3
 
 !! test
 <onlyinclude> and <includeonly> being included
-!! input
+!! wikitext
 {{Includes3}}
-!! result
+!! html
 <p>Foo
 </p>
 !! end
 
 !! test
 <includeonly> and <noinclude> on a page
-!! input
+!! wikitext
 Foo<noinclude>zar</noinclude><includeonly>bar</includeonly>
-!! result
+!! html
 <p>Foozar
 </p>
 !! end
 
 !! test
 Un-closed <noinclude>
-!! input
+!! wikitext
 <noinclude>
-!! result
+!! html
 !! end
 
 !! test
 <onlyinclude> on a page
-!! input
+!! wikitext
 <onlyinclude>Foo</onlyinclude>bar
-!! result
+!! html
 <p>Foobar
 </p>
 !! end
 
 !! test
 Un-closed <onlyinclude>
-!! input
+!! wikitext
 <onlyinclude>
-!! result
+!! html
 !! end
 
 !!test
 Self-closed noinclude, includeonly, onlyinclude tags
-!!input
+!! wikitext
 <noinclude />
 <includeonly />
 <onlyinclude />
-!!result
+!! html
 <p><br />
 </p>
 !!end
 
 !!test
 Unbalanced includeonly and noinclude tags
-!!input
+!! wikitext
 {|
 |a</noinclude>
 |b</noinclude></noinclude>
 |c</noinclude></includeonly>
 |d</includeonly></includeonly>
 |}
-!!result
+!! html
 <table>
 <tr>
 <td>a
@@ -8332,9 +8141,9 @@ Template:Includeonly section
 
 !! test
 Bug 6563: Edit link generation for section shown by <includeonly>
-!! input
+!! wikitext
 {{includeonly section}}
-!! result
+!! html
 <h2><span class="mw-headline" id="Includeonly_section">Includeonly section</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Template:Includeonly_section&amp;action=edit&amp;section=T-1" title="Template:Includeonly section">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
 <h2><span class="mw-headline" id="Section_T-1">Section T-1</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Template:Includeonly_section&amp;action=edit&amp;section=T-2" title="Template:Includeonly section">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
 
@@ -8345,23 +8154,23 @@ Bug 6563: Edit link generation for section shown by <includeonly>
 Bug 6563: Section extraction for section shown by <includeonly>
 !! options
 section=T-2
-!! input
+!! wikitext
 <includeonly>
 ==Includeonly section==
 </includeonly>
 ==Section T-2==
-!! result
+!! html
 ==Section T-2==
 !! end
 
 !! test
 Bug 6563: Edit link generation for section suppressed by <includeonly>
-!! input
+!! wikitext
 <includeonly>
 ==Includeonly section==
 </includeonly>
 ==Section 1==
-!! result
+!! html
 <h2><span class="mw-headline" id="Section_1">Section 1</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=1" title="Edit section: Section 1">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
 
 !! end
@@ -8370,20 +8179,20 @@ Bug 6563: Edit link generation for section suppressed by <includeonly>
 Bug 6563: Section extraction for section suppressed by <includeonly>
 !! options
 section=1
-!! input
+!! wikitext
 <includeonly>
 ==Includeonly section==
 </includeonly>
 ==Section 1==
-!! result
+!! html
 ==Section 1==
 !! end
 
 !! test
 Un-closed <includeonly>
-!! input
+!! wikitext
 <includeonly>
-!! result
+!! html
 !! end
 
 # TODO: test with DOM fragment reuse!
@@ -8391,7 +8200,7 @@ Un-closed <includeonly>
 Parsoid: DOM fragment reuse
 !! options
 parsoid=wt2wt,wt2html
-!! input
+!! wikitext
 a{{echo|b<table></table>c}}d
 
 a{{echo|b
@@ -8403,7 +8212,7 @@ c}}d
 <table></table>
 
 b}}
-!! result
+!! html
 a<span about="#mwt1" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"b
 <table></table>c"}},"i":0}}]}'>b</span>
 <table about="#mwt1"></table><span about="#mwt1">c</span>d
@@ -8429,11 +8238,11 @@ a<span about="#mwt1" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"t
 Parsoid: Merge double tds (bug 50603)
 !! options
 parsoid
-!! input
+!! wikitext
 {|
 |{{echo|{{!}} foo}}
 |}
-!! result
+!! html
 <table><tbody>
 <tr><td about="#mwt1" typeof="mw:Transclusion" data-mw='{"parts":["|",{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"{{!}} foo"}},"i":0}}]}'> foo</td></tr>
 </tbody></table>
@@ -8443,13 +8252,13 @@ parsoid
 Parsoid: Merge double tds in nested transclusion content (bug 50603)
 !! options
 parsoid
-!! input
+!! wikitext
 {{echo|<div>}}
 {|
 |{{echo|{{!}} foo}}
 |}
 {{echo|</div>}}
-!! result
+!! html
 <div about="#mwt1" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"<div>"}},"i":0}},"\n{|\n|",{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"{{!}} foo"}},"i":1}},"\n|}\n",{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"</div>"}},"i":2}}]}'>
 <table><tbody>
 <tr><td data-mw='{"parts":["|"]}'> foo</td></tr>
@@ -8462,28 +8271,28 @@ parsoid
 ###
 !!test
 0. includeonly around the entire attribute
-!!input
+!! wikitext
 <span <includeonly>id="v1"</includeonly><noinclude>id="v2"</noinclude>>bar</span>
-!!result
+!! html
 <p><span id="v2">bar</span>
 </p>
 !!end
 
 !!test
 1. includeonly in html attr key
-!!input
+!! wikitext
 <span <noinclude>id</noinclude><includeonly>about</includeonly>="foo">bar</span>
-!!result
+!! html
 <p><span id="foo">bar</span>
 </p>
 !!end
 
 !!test
 2. includeonly in html attr value
-!!input
+!! wikitext
 <span id="<noinclude>v1</noinclude><includeonly>v2</includeonly>">bar</span>
 <span id=<noinclude>"v1"</noinclude><includeonly>"v2"</includeonly>>bar</span>
-!!result
+!! html
 <p><span id="v1">bar</span>
 <span id="v1">bar</span>
 </p>
@@ -8491,16 +8300,16 @@ parsoid
 
 !!test
 3. includeonly in part of an attr value
-!!input
+!! wikitext
 <span style="color:<noinclude>red</noinclude><includeonly>blue</includeonly>;">bar</span>
-!!result
+!! html
 <p><span style="color:red;">bar</span>
 </p>
 !!end
 
 !!test
 4. includeonly in table attributes
-!!input
+!! wikitext
 {|
 |- <noinclude>
 |-
@@ -8511,7 +8320,7 @@ parsoid
 |b
 </includeonly>
 |}
-!!result
+!! html
 <table>
 
 
@@ -8535,27 +8344,27 @@ Template:quote
 
 !!test
 Templates: Template Name/Arg clash: 1. Use of positional param
-!!input
+!! wikitext
 {{quote|foo}}
-!!result
+!! html
 <p>foo
 </p>
 !!end
 
 !!test
 Templates: Template Name/Arg clash: 2. Use of named param
-!!input
+!! wikitext
 {{quote|quote=foo}}
-!!result
+!! html
 <p>foo
 </p>
 !!end
 
 !!test
 Templates: Template Name/Arg clash: 3. Use of named param with empty input
-!!input
+!! wikitext
 {{quote|quote}}
-!!result
+!! html
 <p>quote
 </p>
 !!end
@@ -8566,19 +8375,19 @@ Templates: Template Name/Arg clash: 3. Use of named param with empty input
 
 !!test
 Templates: 1. Simple use
-!!input
+!! wikitext
 {{echo|Foo}}
-!!result
+!! html
 <p>Foo
 </p>
 !!end
 
 !!test
 Templates: 2. Inside a block tag
-!!input
+!! wikitext
 <div>{{echo|Foo}}</div>
 <blockquote>{{echo|Foo}}</blockquote>
-!!result
+!! html
 <div>Foo</div>
 <blockquote>Foo</blockquote>
 
@@ -8586,10 +8395,10 @@ Templates: 2. Inside a block tag
 
 !!test
 Templates: P-wrapping: 1a. Templates on consecutive lines
-!!input
+!! wikitext
 {{echo|Foo}}
 {{echo|bar}}
-!!result
+!! html
 <p>Foo
 bar
 </p>
@@ -8597,12 +8406,12 @@ bar
 
 !!test
 Templates: P-wrapping: 1b. Templates on consecutive lines
-!!input
+!! wikitext
 Foo
 
 {{echo|bar}}
 {{echo|baz}}
-!!result
+!! html
 <p>Foo
 </p><p>bar
 baz
@@ -8611,10 +8420,10 @@ baz
 
 !!test
 Templates: P-wrapping: 1c. Templates on consecutive lines
-!!input
+!! wikitext
 {{echo|Foo}}
 {{echo|bar}} <div>baz</div>
-!!result
+!! html
 <p>Foo
 </p>
 bar <div>baz</div>
@@ -8625,10 +8434,10 @@ bar <div>baz</div>
 Templates: P-wrapping: 1d. Template preceded by comment-only line
 !!options
 parsoid
-!!input
+!! wikitext
 <!-- foo -->
 {{echo|Bar}}
-!!result
+!! html
 <!-- foo -->
 
 <p about="#mwt223" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"Bar"}},"i":0}}]}'>Bar</p>
@@ -8636,61 +8445,61 @@ parsoid
 
 !!test
 Templates: Inline Text: 1. Multiple tmeplate uses
-!!input
+!! wikitext
 {{echo|Foo}}bar{{echo|baz}}
-!!result
+!! html
 <p>Foobarbaz
 </p>
 !!end
 
 !!test
 Templates: Inline Text: 2. Back-to-back template uses
-!!input
+!! wikitext
 {{echo|Foo}}{{echo|bar}}
-!!result
+!! html
 <p>Foobar
 </p>
 !!end
 
 !!test
 Templates: Block Tags: 1. Multiple template uses
-!!input
+!! wikitext
 {{echo|<div>Foo</div>}}<div>bar</div>{{echo|<div>baz</div>}}
-!!result
+!! html
 <div>Foo</div><div>bar</div><div>baz</div>
 
 !!end
 
 !!test
 Templates: Block Tags: 2. Back-to-back template uses
-!!input
+!! wikitext
 {{echo|<div>Foo</div>}}{{echo|<div>bar</div>}}
-!!result
+!! html
 <div>Foo</div><div>bar</div>
 
 !!end
 
 !!test
 Templates: Links: 1. Simple example
-!!input
+!! wikitext
 {{echo|[[Foo|bar]]}}
-!!result
+!! html
 <p><a href="/index.php?title=Foo&amp;action=edit&amp;redlink=1" class="new" title="Foo (page does not exist)">bar</a>
 </p>
 !!end
 
 !!test
 Templates: Links: 2. Generation of link href
-!!input
+!! wikitext
 [[{{echo|Foo}}|bar]]
-!!result
+!! html
 <p><a href="/index.php?title=Foo&amp;action=edit&amp;redlink=1" class="new" title="Foo (page does not exist)">bar</a>
 </p>
 !!end
 
 !!test
 Templates: Links: 3. Generation of part of a link href
-!!input
+!! wikitext
 [[Fo{{echo|o}}|bar]]
 
 [[Foo{{echo|bar}}]]
@@ -8702,7 +8511,7 @@ Templates: Links: 3. Generation of part of a link href
 [[:Foo{{echo|bar}}]]
 
 [[:Foo{{echo|bar}}|bar]]
-!!result
+!! html
 <p><a href="/index.php?title=Foo&amp;action=edit&amp;redlink=1" class="new" title="Foo (page does not exist)">bar</a>
 </p><p><a href="/index.php?title=Foobar&amp;action=edit&amp;redlink=1" class="new" title="Foobar (page does not exist)">Foobar</a>
 </p><p><a href="/index.php?title=Foobarbaz&amp;action=edit&amp;redlink=1" class="new" title="Foobarbaz (page does not exist)">Foobarbaz</a>
@@ -8714,180 +8523,180 @@ Templates: Links: 3. Generation of part of a link href
 
 !!test
 Templates: Links: 4. Multiple templates generating link href
-!!input
+!! wikitext
 [[{{echo|F}}{{echo|o}}ob{{echo|ar}}]]
-!!result
+!! html
 <p><a href="/index.php?title=Foobar&amp;action=edit&amp;redlink=1" class="new" title="Foobar (page does not exist)">Foobar</a>
 </p>
 !!end
 
 !!test
 Templates: Links: 5. Generation of link text
-!!input
+!! wikitext
 [[Foo|{{echo|bar}}]]
-!!result
+!! html
 <p><a href="/index.php?title=Foo&amp;action=edit&amp;redlink=1" class="new" title="Foo (page does not exist)">bar</a>
 </p>
 !!end
 
 !!test
 Templates: Links: 5. Nested templates (only outermost template should be marked)
-!!input
+!! wikitext
 {{echo|[[{{echo|Foo}}|bar]]}}
-!!result
+!! html
 <p><a href="/index.php?title=Foo&amp;action=edit&amp;redlink=1" class="new" title="Foo (page does not exist)">bar</a>
 </p>
 !!end
 
 !!test
 Templates: HTML Tag: 1. Generation of HTML attr. key
-!!input
+!! wikitext
 <div {{echo|style}}="color:red;">foo</div>
-!!result
+!! html
 <div style="color:red;">foo</div>
 
 !!end
 
 !!test
 Templates: HTML Tag: 2. Generation of HTML attr. value
-!!input
+!! wikitext
 <div style={{echo|'color:red;'}}>foo</div>
-!!result
+!! html
 <div style="color:red;">foo</div>
 
 !!end
 
 !!test
 Templates: HTML Tag: 3. Generation of HTML attr key and value
-!!input
+!! wikitext
 <div {{echo|style}}={{echo|'color:red;'}}>foo</div>
-!!result
+!! html
 <div style="color:red;">foo</div>
 
 !!end
 
 !!test
 Templates: HTML Tag: 4. Generation of starting piece of HTML attr value
-!!input
+!! wikitext
 <div title="{{echo|This is a long title}} with just one piece templated">foo</div>
-!!result
+!! html
 <div title="This is a long title with just one piece templated">foo</div>
 
 !!end
 
 !!test
 Templates: HTML Tag: 5. Generation of middle piece of HTML attr value
-!!input
+!! wikitext
 <div title="This is a long title with just {{echo|one piece}} templated">foo</div>
-!!result
+!! html
 <div title="This is a long title with just one piece templated">foo</div>
 
 !!end
 
 !!test
 Templates: HTML Tag: 6. Generation of end piece of HTML attr value
-!!input
+!! wikitext
 <div title="This is a long title with just one piece {{echo|templated}}">foo</div>
-!!result
+!! html
 <div title="This is a long title with just one piece templated">foo</div>
 
 !!end
 
 !!test
 Templates: HTML Tag: 7. Generation of partial attribute key string
-!!input
+!! wikitext
 <div st{{echo|yle}}="color:red;">foo</div>
-!!result
+!! html
 <div style="color:red;">foo</div>
 
 !!end
 
 !!test
 Templates: HTML Tables: 1. Generating start of a HTML table
-!!input
+!! wikitext
 {{echo|<table><tr><td>foo</td>}}</tr></table>
-!!result
+!! html
 <table><tr><td>foo</td></tr></table>
 
 !!end
 
 !!test
 Templates: HTML Tables: 2a. Generating middle of a HTML table
-!!input
+!! wikitext
 <table><tr>{{echo|<td>foo</td>}}</tr></table>
-!!result
+!! html
 <table><tr><td>foo</td></tr></table>
 
 !!end
 
 !!test
 Templates: HTML Tables: 2b. Generating middle of a HTML table
-!!input
+!! wikitext
 <table>{{echo|<tr><td>foo</td></tr>}}</table>
-!!result
+!! html
 <table><tr><td>foo</td></tr></table>
 
 !!end
 
 !!test
 Templates: HTML Tables: 3. Generating end of a HTML table
-!!input
+!! wikitext
 <table><tr>{{echo|<td>foo</td></tr></table>}}
-!!result
+!! html
 <table><tr><td>foo</td></tr></table>
 
 !!end
 
 !!test
 Templates: HTML Tables: 4a. Generating a single tag of a HTML table
-!!input
+!! wikitext
 {{echo|<table>}}<tr><td>foo</td></tr></table>
-!!result
+!! html
 <table><tr><td>foo</td></tr></table>
 
 !!end
 
 !!test
 Templates: HTML Tables: 4b. Generating a single tag of a HTML table
-!!input
+!! wikitext
 <table>{{echo|<tr>}}<td>foo</td></tr></table>
-!!result
+!! html
 <table><tr><td>foo</td></tr></table>
 
 !!end
 
 !!test
 Templates: HTML Tables: 4c. Generating a single tag of a HTML table
-!!input
+!! wikitext
 <table><tr>{{echo|<td>}}foo</td></tr></table>
-!!result
+!! html
 <table><tr><td>foo</td></tr></table>
 
 !!end
 
 !!test
 Templates: HTML Tables: 4d. Generating a single tag of a HTML table
-!!input
+!! wikitext
 <table><tr><td>foo{{echo|</td>}}</tr></table>
-!!result
+!! html
 <table><tr><td>foo</td></tr></table>
 
 !!end
 
 !!test
 Templates: HTML Tables: 4e. Generating a single tag of a HTML table
-!!input
+!! wikitext
 <table><tr><td>foo</td>{{echo|</tr>}}</table>
-!!result
+!! html
 <table><tr><td>foo</td></tr></table>
 
 !!end
 
 !!test
 Templates: HTML Tables: 4f. Generating a single tag of a HTML table
-!!input
+!! wikitext
 <table><tr><td>foo</td></tr>{{echo|</table>}}
-!!result
+!! html
 <table><tr><td>foo</td></tr></table>
 
 !!end
@@ -8896,11 +8705,11 @@ Templates: HTML Tables: 4f. Generating a single tag of a HTML table
 Templates: HTML Tables: 5. Proper fostering of categories from inside
 !!options
 parsoid=wt2html,wt2wt
-!!input
+!! wikitext
 <table>[[Category:foo1]]<tr><td>foo</td></tr></table>
 <!--Two categories (Bug 50330)-->
 <table>[[Category:bar1]][[Category:bar2]]<tr><td>foo</td></tr></table>
-!!result
+!! html
 <link rel="mw:PageProp/Category" href="./Category:Foo1"><table><tbody><tr><td>foo</td></tr></tbody></table>
 <!--Two categories (Bug 50330)-->
 <link rel="mw:PageProp/Category" href="./Category:Bar1"><link rel="mw:PageProp/Category" href="./Category:Bar2"><table><tbody><tr><td>foo</td></tr></tbody></table>
@@ -8908,11 +8717,11 @@ parsoid=wt2html,wt2wt
 
 !!test
 Templates: Wiki Tables: 1a. Fostering of entire template content
-!!input
+!! wikitext
 {|
 {{echo|a}}
 |}
-!!result
+!! html
 <table>
 a
 <tr><td></td></tr></table>
 
 !!test
 Templates: Wiki Tables: 1b. Fostering of entire template content
-!!input
+!! wikitext
 {|
 {{echo|<div>}}
 foo
 {{echo|</div>}}
 |}
-!!result
+!! html
 <table>
 <div>
 <p>foo
@@ -8939,12 +8748,12 @@ foo
 
 !!test
 Templates: Wiki Tables: 2. Fostering of partial template content
-!!input
+!! wikitext
 {|
 {{echo|a
 <div>b</div>}}
 |}
-!!result
+!! html
 <table>
 a
 <div>b</div>
 
 !!test
 Templates: Wiki Tables: 3. td-content via multiple templates
-!!input
+!! wikitext
 {|
 {{echo|{{pipe}}a}}{{echo|b}}
 |}
-!!result
+!! html
 <table>
 <tr>
 <td>ab
@@ -8968,10 +8777,10 @@ Templates: Wiki Tables: 3. td-content via multiple templates
 
 !!test
 Templates: Wiki Tables: 4. Templated tags, no content
-!!input
+!! wikitext
 {{tbl-start}}
 {{tbl-end}}
-!!result
+!! html
 <table>
 <tr><td></td></tr></table>
 
@@ -8979,11 +8788,11 @@ Templates: Wiki Tables: 4. Templated tags, no content
 
 !!test
 Templates: Wiki Tables: 5. Templated tags, regular td-tags
-!!input
+!! wikitext
 {{tbl-start}}
 |foo
 {{tbl-end}}
-!!result
+!! html
 <table>
 <tr>
 <td>foo
@@ -8993,11 +8802,11 @@ Templates: Wiki Tables: 5. Templated tags, regular td-tags
 
 !!test
 Templates: Wiki Tables: 6. Templated tags, templated td-tags
-!!input
+!! wikitext
 {{tbl-start}}
 {{!}}foo
 {{tbl-end}}
-!!result
+!! html
 <table>
 <tr>
 <td>foo
@@ -9007,12 +8816,12 @@ Templates: Wiki Tables: 6. Templated tags, templated td-tags
 
 !!test
 Templates: Lists: Multi-line list-items via templates
-!!input
+!! wikitext
 *{{echo|a {{nonexistent|
 unused}}}}
 *{{echo|b {{nonexistent|
 unused}}}}
-!!result
+!! html
 <ul>
 <li>a <a href="/index.php?title=Template:Nonexistent&amp;action=edit&amp;redlink=1" class="new" title="Template:Nonexistent (page does not exist)">Template:Nonexistent</a>
 </li>
@@ -9024,9 +8833,9 @@ unused}}}}
 
 !!test
 Templates: Ugly nesting: 1. Quotes opened/closed across templates (echo)
-!!input
+!! wikitext
 {{echo|''a}}{{echo|b''c''d}}{{echo|''e}}
-!!result
+!! html
 <p><i>ab</i>c<i>d</i>e
 </p>
 !!end
@@ -9034,11 +8843,9 @@ Templates: Ugly nesting: 1. Quotes opened/closed across templates (echo)
 !!test
 Templates: Ugly nesting: 2. Quotes opened/closed across templates (echo_with_span)
 (PHP parser generates misnested html)
-!! options
-parsoid
-!!input
+!! wikitext
 {{echo_with_span|''a}}{{echo_with_span|b''c''d}}{{echo_with_span|''e}}
-!!result
+!! html/parsoid
 <p><span about="#mwt1" typeof="mw:Transclusion" data-mw="{&quot;parts&quot;:[{&quot;template&quot;:{&quot;target&quot;:{&quot;wt&quot;:&quot;echo_with_span&quot;,&quot;href&quot;:&quot;./Template:Echo_with_span&quot;},&quot;params&quot;:{&quot;1&quot;:{&quot;wt&quot;:&quot;''a&quot;}},&quot;i&quot;:0}}]}"><i>a</i></span><i about="#mwt2" typeof="mw:Transclusion" data-mw="{&quot;parts&quot;:[{&quot;template&quot;:{&quot;target&quot;:{&quot;wt&quot;:&quot;echo_with_span&quot;,&quot;href&quot;:&quot;./Template:Echo_with_span&quot;},&quot;params&quot;:{&quot;1&quot;:{&quot;wt&quot;:&quot;b''c''d&quot;}},&quot;i&quot;:0}},{&quot;template&quot;:{&quot;target&quot;:{&quot;wt&quot;:&quot;echo_with_span&quot;,&quot;href&quot;:&quot;./Template:Echo_with_span&quot;},&quot;params&quot;:{&quot;1&quot;:{&quot;wt&quot;:&quot;''e&quot;}},&quot;i&quot;:1}}]}"><span>b</span></i><span about="#mwt2">c</span><i about="#mwt2">d<span></span></i><span about="#mwt2">e</span></p>
 !!end
 
@@ -9047,9 +8854,9 @@ Templates: Ugly nesting: 3. Quotes opened/closed across templates (echo_with_div
 (PHP parser generates misnested html; Parsoid html2wt mode adds newlines between {{echo}}s)
 !! options
 parsoid=wt2html,wt2wt
-!!input
+!! wikitext
 {{echo_with_div|''a}}{{echo_with_div|b''c''d}}{{echo_with_div|''e}}
-!!result
+!! html
 <div about="#mwt1" typeof="mw:Transclusion" data-mw="{&quot;parts&quot;:[{&quot;template&quot;:{&quot;target&quot;:{&quot;wt&quot;:&quot;echo_with_div&quot;,&quot;href&quot;:&quot;./Template:Echo_with_div&quot;},&quot;params&quot;:{&quot;1&quot;:{&quot;wt&quot;:&quot;''a&quot;}},&quot;i&quot;:0}}]}"><i>a</i></div>
 <div about="#mwt2" typeof="mw:Transclusion" data-mw="{&quot;parts&quot;:[{&quot;template&quot;:{&quot;target&quot;:{&quot;wt&quot;:&quot;echo_with_div&quot;,&quot;href&quot;:&quot;./Template:Echo_with_div&quot;},&quot;params&quot;:{&quot;1&quot;:{&quot;wt&quot;:&quot;b''c''d&quot;}},&quot;i&quot;:0}}]}"><i>b</i>c<i>d</i></div>
 <div about="#mwt3" typeof="mw:Transclusion" data-mw="{&quot;parts&quot;:[{&quot;template&quot;:{&quot;target&quot;:{&quot;wt&quot;:&quot;echo_with_div&quot;,&quot;href&quot;:&quot;./Template:Echo_with_div&quot;},&quot;params&quot;:{&quot;1&quot;:{&quot;wt&quot;:&quot;''e&quot;}},&quot;i&quot;:0}}]}">e</div>
@@ -9057,9 +8864,9 @@ parsoid=wt2html,wt2wt
 
 !!test
 Templates: Ugly nesting: 4. Divs opened/closed across templates
-!!input
+!! wikitext
 a<div>b{{echo|c</div>d}}e
-!!result
+!! html
 a<div>bc</div>de
 
 !!end
@@ -9069,12 +8876,12 @@ Templates: Ugly templates: 1. Navbox template parses badly leading to table misn
 (Parsoid-centric)
 !! options
 parsoid
-!!input
+!! wikitext
 {|
 |{{echo|foo</table>}}
 |bar
 |}
-!!result
+!! html
 <table about="#mwt1" typeof="mw:Transclusion" data-mw='{"parts":["{|\n|",{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"foo</table>"}},"i":0}},"\n|bar\n|}"]}'>
 
 <tbody>
@@ -9089,7 +8896,7 @@ Templates: Ugly templates: 2. Navbox template parses badly leading to table misn
 (Parsoid-centric)
 !! options
 parsoid
-!!input
+!! wikitext
 <table>
   <tr>
     <td>
@@ -9109,7 +8916,7 @@ parsoid
     <td>xyz</td>
   </tr>
 </table>
-!!result
+!! html
 <table about="#mwt2" typeof="mw:Transclusion" data-mw='{"parts":["<table>\n  <tr>\n    <td>\n    <table>\n      <tr>\n        <td>1. ",{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"foo </table>"}},"i":0}},"</td>\n        <td> bar </td>\n        <td>2. ",{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"baz </table>"}},"i":1}},"</td>\n      </tr>\n      <tr>\n        <td>abc</td>\n      </tr>\n    </table>\n    </td>\n  </tr>\n  <tr>\n    <td>xyz</td>\n  </tr>\n</table>"]}'>
   <tbody><tr>
     <td>
@@ -9133,10 +8940,10 @@ parsoid
 
 !! test
 Templates: Ugly templates: 3. newline-only template parameter
-!! input
+!! wikitext
 foo {{echo|
 }}
-!! result
+!! html
 <p>foo 
 </p>
 !! end
@@ -9144,10 +8951,10 @@ foo {{echo|
 # This looks like a bug: a single newline triggers p/br for some reason.
 !! test
 Templates: Ugly templates: 4. newline-only template parameter inconsistency
-!! input
+!! wikitext
 {{echo|
 }}
-!! result
+!! html
 <p><br />
 </p>
 !! end
@@ -9155,18 +8962,18 @@ Templates: Ugly templates: 4. newline-only template parameter inconsistency
 
 !!test
 Parser Functions: 1. Simple example
-!!input
+!! wikitext
 {{uc:foo}}
-!!result
+!! html
 <p>FOO
 </p>
 !!end
 
 !!test
 Parser Functions: 2. Nested use (only outermost should be marked up)
-!!input
+!! wikitext
 {{uc:{{lc:FOO}}}}
-!!result
+!! html
 <p>FOO
 </p>
 !!end
@@ -9178,9 +8985,9 @@ Parser Functions: 2. Nested use (only outermost should be marked up)
 pre-save transform: subst:
 !! options
 PST
-!! input
+!! wikitext
 {{subst:test}}
-!! result
+!! html
 This is a test template
 !! end
 
@@ -9188,9 +8995,9 @@ This is a test template
 pre-save transform: normal template
 !! options
 PST
-!! input
+!! wikitext
 {{test}}
-!! result
+!! html
 {{test}}
 !! end
 
@@ -9198,9 +9005,9 @@ PST
 pre-save transform: nonexistent template
 !! options
 PST
-!! input
+!! wikitext
 {{thistemplatedoesnotexist}}
-!! result
+!! html
 {{thistemplatedoesnotexist}}
 !! end
 
@@ -9209,9 +9016,9 @@ PST
 pre-save transform: subst magic variables
 !! options
 PST
-!! input
+!! wikitext
 {{subst:SITENAME}}
-!! result
+!! html
 MediaWiki
 !! end
 
@@ -9220,9 +9027,9 @@ MediaWiki
 pre-save transform: subst: templates with parameters
 !! options
 pst
-!! input
+!! wikitext
 {{subst:paramtest|param="something else"}}
-!! result
+!! html
 This is a test template with parameter "something else"
 !! end
 
@@ -9236,9 +9043,9 @@ Template:nowikitest
 pre-save transform: nowiki in subst (bug 1188)
 !! options
 pst
-!! input
+!! wikitext
 {{subst:nowikitest}}
-!! result
+!! html
 <nowiki>'''not wiki'''</nowiki>
 !! end
 
@@ -9253,9 +9060,9 @@ This template has <!-- a comment --> in it.
 pre-save transform: comment in subst (bug 1936)
 !! options
 pst
-!! input
+!! wikitext
 {{subst:commenttest}}
-!! result
+!! html
 This template has <!-- a comment --> in it.
 !! end
 
@@ -9263,9 +9070,9 @@ This template has <!-- a comment --> in it.
 pre-save transform: unclosed tag
 !! options
 pst noxml
-!! input
+!! wikitext
 <nowiki>'''not wiki'''
-!! result
+!! html
 <nowiki>'''not wiki'''
 !! end
 
@@ -9273,9 +9080,9 @@ pst noxml
 pre-save transform: mixed tag case
 !! options
 pst noxml
-!! input
+!! wikitext
 <NOwiki>'''not wiki'''</noWIKI>
-!! result
+!! html
 <NOwiki>'''not wiki'''</noWIKI>
 !! end
 
@@ -9283,9 +9090,9 @@ pst noxml
 pre-save transform: unclosed comment in <nowiki>
 !! options
 pst noxml
-!! input
+!! wikitext
 wiki<nowiki>nowiki<!--nowiki</nowiki>wiki
-!! result
+!! html
 wiki<nowiki>nowiki<!--nowiki</nowiki>wiki
 !!end
 
@@ -9300,9 +9107,9 @@ Template:dangerous
 
 !!test
 (confirming safety of fix for subst bug 1936)
-!! input
+!! wikitext
 {{Template:dangerous}}
-!! result
+!! html
 <p>@<span>Oh no</span>
 </p>
 !! end
@@ -9311,9 +9118,9 @@ Template:dangerous
 pre-save transform: comment containing gallery (bug 5024)
 !! options
 pst
-!! input
+!! wikitext
 <!-- <gallery>data</gallery> -->
-!!result
+!! html
 <!-- <gallery>data</gallery> -->
 !!end
 
@@ -9321,9 +9128,9 @@ pst
 pre-save transform: comment containing extension
 !! options
 pst
-!! input
+!! wikitext
 <!-- <tag>data</tag> -->
-!!result
+!! html
 <!-- <tag>data</tag> -->
 !!end
 
@@ -9331,9 +9138,9 @@ pst
 pre-save transform: comment containing nowiki
 !! options
 pst
-!! input
+!! wikitext
 <!-- <nowiki>data</nowiki> -->
-!!result
+!! html
 <!-- <nowiki>data</nowiki> -->
 !!end
 
@@ -9341,9 +9148,9 @@ pst
 pre-save transform: <noinclude> in subst (bug 3298)
 !! options
 pst
-!! input
+!! wikitext
 {{subst:Includes}}
-!! result
+!! html
 Foobar
 !! end
 
@@ -9351,9 +9158,9 @@ Foobar
 pre-save transform: <onlyinclude> in subst (bug 3298)
 !! options
 pst
-!! input
+!! wikitext
 {{subst:Includes2}}
-!! result
+!! html
 Foo
 !! end
 
@@ -9373,26 +9180,26 @@ Template:SafeSubstTest
 bug 22297: safesubst: works during PST
 !! options
 pst
-!! input
+!! wikitext
 {{subst:SafeSubstTest}}{{safesubst:SubstTest}}
-!! result
+!! html
 FoobarFoobar
 !! end
 
 !! test
 bug 22297: safesubst: works during normal parse
-!! input
+!! wikitext
 {{SafeSubstTest}}
-!! result
+!! html
 <p>Foobar
 </p>
 !! end
 
-!! test:
+!! test
 subst: does not work during normal parse
-!! input
+!! wikitext
 {{SubstTest}}
-!! result
+!! html
 <p>{{subst:Includes}}
 </p>
 !! end
@@ -9401,7 +9208,7 @@ subst: does not work during normal parse
 pre-save transform: context links ("pipe trick")
 !! options
 pst
-!! input
+!! wikitext
 [[Article (context)|]]
 [[Bar:Article|]]
 [[:Bar:Article|]]
@@ -9411,7 +9218,7 @@ pst
 [[|Article (context)]]
 [[Bar:X (Y) Z|]]
 [[:Bar:X (Y) Z|]]
-!! result
+!! html
 [[Article (context)|Article]]
 [[Bar:Article|Article]]
 [[:Bar:Article|Article]]
@@ -9427,12 +9234,12 @@ pst
 pre-save transform: context links ("pipe trick") with interwiki prefix
 !! options
 pst
-!! input
+!! wikitext
 [[interwiki:Article|]]
 [[:interwiki:Article|]]
 [[interwiki:Bar:Article|]]
 [[:interwiki:Bar:Article|]]
-!! result
+!! html
 [[interwiki:Article|Article]]
 [[:interwiki:Article|Article]]
 [[interwiki:Bar:Article|Bar:Article]]
@@ -9443,9 +9250,9 @@ pst
 pre-save transform: context links ("pipe trick") with parens in title
 !! options
 pst title=[[Somearticle (context)]]
-!! input
+!! wikitext
 [[|Article]]
-!! result
+!! html
 [[Article (context)|Article]]
 !! end
 
@@ -9453,11 +9260,11 @@ pst title=[[Somearticle (context)]]
 pre-save transform: context links ("pipe trick") with comma in title
 !! options
 pst title=[[Someplace, Somewhere]]
-!! input
+!! wikitext
 [[|Otherplace]]
 [[Otherplace, Elsewhere|]]
 [[Otherplace, Elsewhere, Anywhere|]]
-!! result
+!! html
 [[Otherplace, Somewhere|Otherplace]]
 [[Otherplace, Elsewhere|Otherplace]]
 [[Otherplace, Elsewhere, Anywhere|Otherplace]]
@@ -9467,10 +9274,10 @@ pst title=[[Someplace, Somewhere]]
 pre-save transform: context links ("pipe trick") with parens and comma
 !! options
 pst title=[[Someplace (IGNORED), Somewhere]]
-!! input
+!! wikitext
 [[|Otherplace]]
 [[Otherplace (place), Elsewhere|]]
-!! result
+!! html
 [[Otherplace, Somewhere|Otherplace]]
 [[Otherplace (place), Elsewhere|Otherplace]]
 !! end
@@ -9479,10 +9286,10 @@ pst title=[[Someplace (IGNORED), Somewhere]]
 pre-save transform: context links ("pipe trick") with comma and parens
 !! options
 pst title=[[Who, me? (context)]]
-!! input
+!! wikitext
 [[|Yes, you.]]
 [[Me, Myself, and I (1937 song)|]]
-!! result
+!! html
 [[Yes, you. (context)|Yes, you.]]
 [[Me, Myself, and I (1937 song)|Me, Myself, and I]]
 !! end
@@ -9491,9 +9298,9 @@ pst title=[[Who, me? (context)]]
 pre-save transform: context links ("pipe trick") with namespace
 !! options
 pst title=[[Ns:Somearticle]]
-!! input
+!! wikitext
 [[|Article]]
-!! result
+!! html
 [[Ns:Article|Article]]
 !! end
 
@@ -9501,9 +9308,9 @@ pst title=[[Ns:Somearticle]]
 pre-save transform: context links ("pipe trick") with namespace and parens
 !! options
 pst title=[[Ns:Somearticle (context)]]
-!! input
+!! wikitext
 [[|Article]]
-!! result
+!! html
 [[Ns:Article (context)|Article]]
 !! end
 
@@ -9511,9 +9318,9 @@ pst title=[[Ns:Somearticle (context)]]
 pre-save transform: context links ("pipe trick") with namespace and comma
 !! options
 pst title=[[Ns:Somearticle, Context, Whatever]]
-!! input
+!! wikitext
 [[|Article]]
-!! result
+!! html
 [[Ns:Article, Context, Whatever|Article]]
 !! end
 
@@ -9521,9 +9328,9 @@ pst title=[[Ns:Somearticle, Context, Whatever]]
 pre-save transform: context links ("pipe trick") with namespace, comma and parens
 !! options
 pst title=[[Ns:Somearticle, Context (context)]]
-!! input
+!! wikitext
 [[|Article]]
-!! result
+!! html
 [[Ns:Article (context)|Article]]
 !! end
 
@@ -9531,9 +9338,9 @@ pst title=[[Ns:Somearticle, Context (context)]]
 pre-save transform: context links ("pipe trick") with namespace, parens and comma
 !! options
 pst title=[[Ns:Somearticle (IGNORED), Context]]
-!! input
+!! wikitext
 [[|Article]]
-!! result
+!! html
 [[Ns:Article, Context|Article]]
 !! end
 
@@ -9541,14 +9348,14 @@ pst title=[[Ns:Somearticle (IGNORED), Context]]
 pre-save transform: context links ("pipe trick") with full-width parens and no space (Japanese and Chinese style, bug 30149)
 !! options
 pst
-!! input
+!! wikitext
 [[Article(context)|]]
 [[Bar:Article(context)|]]
 [[:Bar:Article(context)|]]
 [[|Article(context)]]
 [[Bar:X(Y)Z|]]
 [[:Bar:X(Y)Z|]]
-!! result
+!! html
 [[Article(context)|Article]]
 [[Bar:Article(context)|Article]]
 [[:Bar:Article(context)|Article]]
@@ -9561,14 +9368,14 @@ pst
 pre-save transform: context links ("pipe trick") with full-width parens and space (Japanese and Chinese style, bug 30149)
 !! options
 pst
-!! input
+!! wikitext
 [[Article (context)|]]
 [[Bar:Article (context)|]]
 [[:Bar:Article (context)|]]
 [[|Article (context)]]
 [[Bar:X (Y) Z|]]
 [[:Bar:X (Y) Z|]]
-!! result
+!! html
 [[Article (context)|Article]]
 [[Bar:Article (context)|Article]]
 [[:Bar:Article (context)|Article]]
@@ -9581,14 +9388,14 @@ pst
 pre-save transform: context links ("pipe trick") with parens and no space (Korean style, bug 30149)
 !! options
 pst
-!! input
+!! wikitext
 [[Article(context)|]]
 [[Bar:Article(context)|]]
 [[:Bar:Article(context)|]]
 [[|Article(context)]]
 [[Bar:X(Y)Z|]]
 [[:Bar:X(Y)Z|]]
-!! result
+!! html
 [[Article(context)|Article]]
 [[Bar:Article(context)|Article]]
 [[:Bar:Article(context)|Article]]
@@ -9601,14 +9408,14 @@ pst
 pre-save transform: context links ("pipe trick") with commas (bug 21660)
 !! options
 pst
-!! input
+!! wikitext
 [[Article (context), context|]]
 [[Article (context),context|]]
 [[Bar:Article (context), context|]]
 [[Bar:Article (context),context|]]
 [[:Bar:Article (context), context|]]
 [[:Bar:Article (context),context|]]
-!! result
+!! html
 [[Article (context), context|Article]]
 [[Article (context),context|Article]]
 [[Bar:Article (context), context|Article]]
@@ -9621,13 +9428,13 @@ pst
 pre-save transform: trim trailing empty lines
 !! options
 pst
-!! input
+!! wikitext
 Empty lines are trimmed
 
 
 
 
-!! result
+!! html
 Empty lines are trimmed
 !! end
 
@@ -9635,12 +9442,12 @@ Empty lines are trimmed
 pre-save transform: Signature expansion
 !! options
 pst
-!! input
+!! wikitext
 * ~~~
 * <noinclude>~~~</noinclude>
 * <includeonly>~~~</includeonly>
 * <onlyinclude>~~~</onlyinclude>
-!! result
+!! html
 * [[Special:Contributions/127.0.0.1|127.0.0.1]]
 * <noinclude>[[Special:Contributions/127.0.0.1|127.0.0.1]]</noinclude>
 * <includeonly>[[Special:Contributions/127.0.0.1|127.0.0.1]]</includeonly>
@@ -9652,7 +9459,7 @@ pst
 pre-save transform: Signature expansion in nowiki tags (bug 93)
 !! options
 pst disabled
-!! input
+!! wikitext
 Shall not expand:
 
 <nowiki>~~~~</nowiki>
@@ -9671,7 +9478,7 @@ As well as inside noinclude/onlyinclude
 
 But not inside includeonly
 <includeonly>{{subst:Foo}}</includeonly>
-!! result
+!! html
 Shall not expand:
 
 <nowiki>~~~~</nowiki>
@@ -9696,7 +9503,7 @@ But not inside includeonly
 Parsoid: Recognize nowiki with trailing space in tags
 !! options
 parsoid=wt2html
-!! input
+!! wikitext
 <nowiki ><div>[[foo]]</nowiki >
 
 a<nowiki / >b
@@ -9704,7 +9511,7 @@ a<nowiki / >b
 c<nowiki />d
 
 e<nowiki/ >f
-!! result
+!! html
 <p><span typeof="mw:Nowiki">&lt;div&gt;[[foo]]</span></p>
 <p>ab</p>
 <p>cd</p>
@@ -9715,9 +9522,9 @@ e<nowiki/ >f
 Parsoid: Recognize nowiki with odd capitalization
 !! options
 parsoid=wt2html
-!! input
+!! wikitext
 <noWikI ><div>[[foo]]</Nowiki >
-!! result
+!! html
 <p><span typeof="mw:Nowiki">&lt;div&gt;[[foo]]</span></p>
 !! end
 
@@ -9726,13 +9533,13 @@ parsoid=wt2html
 Parsoid: Escape nowiki with trailing space in tags
 !! options
 parsoid=html2wt
-!! input
+!! wikitext
 &lt;nowiki &gt; foo &lt;/nowiki &gt;
 
 a&lt;nowiki /&gt;b
 
 c&lt;nowiki/ &gt;d
-!! result
+!! html
 <p>&lt;nowiki &gt; foo &lt/nowiki ></p>
 <p>a&lt;nowiki /&gt;b</p>
 <p>c&lt;nowiki/ &gt;d</p>
@@ -9742,9 +9549,9 @@ c&lt;nowiki/ &gt;d
 Parsoid: Escape weird noWikI capitalizations
 !! options
 parsoid=html2wt
-!! input
+!! wikitext
 &lt;noWikI &gt; foo &lt;/NoWikI &gt;
-!! result
+!! html
 <p>&lt;noWikI &gt; foo &lt/NoWikI ></p>
 !! end
 
@@ -9755,9 +9562,9 @@ parsoid=html2wt
 message transform: magic variables
 !! options
 msg
-!! input
+!! wikitext
 {{SITENAME}}
-!! result
+!! html
 MediaWiki
 !! end
 
@@ -9765,9 +9572,9 @@ MediaWiki
 message transform: should not transform wiki markup
 !! options
 msg
-!! input
+!! wikitext
 ''test''
-!! result
+!! html
 ''test''
 !! end
 
@@ -9775,9 +9582,9 @@ msg
 message transform: <noinclude> in transcluded template (bug 4926)
 !! options
 msg
-!! input
+!! wikitext
 {{Includes}}
-!! result
+!! html
 Foobar
 !! end
 
@@ -9785,9 +9592,9 @@ Foobar
 message transform: <onlyinclude> in transcluded template (bug 4926)
 !! options
 msg
-!! input
+!! wikitext
 {{Includes2}}
-!! result
+!! html
 Foo
 !! end
 
@@ -9795,9 +9602,9 @@ Foo
 {{#special:}} page name, known
 !! options
 msg
-!! input
+!! wikitext
 {{#special:Recentchanges}}
-!! result
+!! html
 Special:RecentChanges
 !! end
 
@@ -9805,9 +9612,9 @@ Special:RecentChanges
 {{#special:}} page name with subpage, known
 !! options
 msg
-!! input
+!! wikitext
 {{#special:Recentchanges/param}}
-!! result
+!! html
 Special:RecentChanges/param
 !! end
 
@@ -9815,9 +9622,9 @@ Special:RecentChanges/param
 {{#special:}} page name, unknown
 !! options
 msg
-!! input
+!! wikitext
 {{#special:foobar nonexistent}}
-!! result
+!! html
 Special:Foobar nonexistent
 !! end
 
@@ -9825,9 +9632,9 @@ Special:Foobar nonexistent
 {{#speciale:}} page name, known
 !! options
 msg
-!! input
+!! wikitext
 {{#speciale:Recentchanges}}
-!! result
+!! html
 Special:RecentChanges
 !! end
 
@@ -9835,9 +9642,9 @@ Special:RecentChanges
 {{#speciale:}} page name with subpage, known
 !! options
 msg
-!! input
+!! wikitext
 {{#speciale:Recentchanges/param}}
-!! result
+!! html
 Special:RecentChanges/param
 !! end
 
@@ -9845,9 +9652,9 @@ Special:RecentChanges/param
 {{#speciale:}} page name, unknown
 !! options
 msg
-!! input
+!! wikitext
 {{#speciale:foobar nonexistent}}
-!! result
+!! html
 Special:Foobar_nonexistent
 !! end
 
@@ -9858,131 +9665,97 @@ Special:Foobar_nonexistent
 #### http://www.mediawiki.org/wiki/Parsoid/MediaWiki_DOM_spec#Images
 
 !! test
-Simple image (php)
+Simple image
 !! options
-php
-!! input
+parsoid=wt2html,wt2wt,html2html
+!! wikitext
 [[Image:foobar.jpg]]
-!! result
+!! html/php
 <p><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a>
 </p>
-!! end
-
-!! test
-Simple image (parsoid)
-!! options
-parsoid=wt2html
-!! input
-[[Image:foobar.jpg]]
-!! result
+!! html/parsoid
 <p><span class="mw-default-size" typeof="mw:Image"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"></a></span>
 </p>
 !! end
 
 !! test
-Simple image (using File: namespace, now canonical) (php)
-!! options
-php
-!! input
-[[File:foobar.jpg]]
-!! result
+Simple image (using File: namespace, now canonical)
+!! wikitext
+[[File:Foobar.jpg]]
+!! html/php
 <p><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a>
 </p>
-!! end
-
-!! test
-Simple image (using File: namespace, now canonical) (parsoid)
-!! options
-parsoid
-!! input
-[[File:Foobar.jpg]]
-!! result
+!! html/parsoid
 <p><span class="mw-default-size" typeof="mw:Image"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"></a></span>
 </p>
 !! end
 
 !! test
-Right-aligned image (php)
-!! options
-php
-!! input
-[[Image:foobar.jpg|right]]
-!! result
+Right-aligned image
+!! wikitext
+[[File:Foobar.jpg|right]]
+!! html/php
 <div class="floatright"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a></div>
 
-!! end
-
-!! test
-Right-aligned image (parsoid)
-!! options
-parsoid
-!! input
-[[File:Foobar.jpg|right]]
-!! result
+!! html/parsoid
 <figure class="mw-default-size mw-halign-right" typeof="mw:Image"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"></a></figure>
 !! end
 
 !! test
-Image with caption (php)
-!! options
-php
-!! input
+Image with caption
+!! wikitext
 [[File:Foobar.jpg|right|Caption text]]
-!! result
+!! html/php
 <div class="floatright"><a href="/wiki/File:Foobar.jpg" class="image" title="Caption text"><img alt="Caption text" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a></div>
 
-!! end
-
-!! test
-Image with caption (parsoid)
-!! options
-parsoid
-!! input
-[[File:Foobar.jpg|right|Caption text]]
-!! result
+!! html/parsoid
 <figure class="mw-default-size mw-halign-right" typeof="mw:Image"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"></a><figcaption>Caption text</figcaption></figure>
 !! end
 
 !! test
-Image with caption, bug 53312 #1 (parsoid)
-!! options
-parsoid
-!! input
+Image with caption, bug 53312 #1
+!! wikitext
 [[File:Foobar.jpg|right|Caption page stuff]]
-!! result
+!! html/php
+<div class="floatright"><a href="/wiki/File:Foobar.jpg" class="image" title="Caption page stuff"><img alt="Caption page stuff" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a></div>
+
+!! html/parsoid
 <figure class="mw-default-size mw-halign-right" typeof="mw:Image"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"></a><figcaption>Caption page stuff</figcaption></figure>
 !! end
 
 !! test
-Image with caption, bug 53312 #2 (parsoid)
-!! options
-parsoid
-!! input
+Image with caption, bug 53312 #2
+!! wikitext
 [[File:Foobar.jpg|right|Caption page=]]
-!! result
+!! html/php
+<div class="floatright"><a href="/wiki/File:Foobar.jpg" class="image" title="Caption page="><img alt="Caption page=" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a></div>
+
+!! html/parsoid
 <figure class="mw-default-size mw-halign-right" typeof="mw:Image"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"></a><figcaption>Caption page=</figcaption></figure>
 !! end
 
 !! test
-Image with caption, bug 53312 #3 (parsoid)
-!! options
-parsoid
-!! input
+Image with caption, bug 53312 #3
+!! wikitext
 [[File:Foobar.jpg|right|Caption page=stuff]]
-!! result
+!! html/php
+<div class="floatright"><a href="/wiki/File:Foobar.jpg" class="image" title="Caption page=stuff"><img alt="Caption page=stuff" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a></div>
+
+!! html/parsoid
 <figure class="mw-default-size mw-halign-right" typeof="mw:Image"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"></a><figcaption>Caption page=stuff</figcaption></figure>
 !! end
 
 !! test
-Allow empty links in image captions (Bug 60753) (parsoid)
-!! options
-parsoid
-!!input
+Allow empty links in image captions (Bug 60753)
+!! wikitext
 [[File:Foobar.jpg|thumb|Caption [[Link1]]
 [[]]
 [[Link2]]
 ]]
-!! result
+!! html/php
+<div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" width="180" height="20" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/270px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/360px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div>Caption <a href="/index.php?title=Link1&amp;action=edit&amp;redlink=1" class="new" title="Link1 (page does not exist)">Link1</a> [[]] <a href="/index.php?title=Link2&amp;action=edit&amp;redlink=1" class="new" title="Link2 (page does not exist)">Link2</a></div></div></div>
+
+!! html/parsoid
 <figure class="mw-default-size" typeof="mw:Image/Thumb" data-parsoid='{"optList":[{"ck":"thumbnail","ak":"thumb"},{"ck":"caption","ak":"Caption [[Link1]]\n[[]]\n[[Link2]]\n"}],"dsr":[0,59,2,2]}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"},"dsr":[2,null,null,null]}'><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/220px-Foobar.jpg" height="25" width="220" data-parsoid='{"a":{"resource":"./File:Foobar.jpg","height":"25","width":"220"},"sa":{"resource":"File:Foobar.jpg"}}'/></a><figcaption data-parsoid='{"dsr":[null,57,null,null]}'>Caption <a rel="mw:WikiLink" href="./Link1" data-parsoid='{"stx":"simple","a":{"href":"./Link1"},"sa":{"href":"Link1"},"dsr":[32,41,2,2]}'>Link1</a>
 [[]]
 <a rel="mw:WikiLink" href="./Link2" data-parsoid='{"stx":"simple","a":{"href":"./Link2"},"sa":{"href":"Link2"},"dsr":[47,56,2,2]}'>Link2</a>
@@ -9991,210 +9764,139 @@ parsoid
 
 !! test
 Link with empty target
-!! input
+!! wikitext
 [[]]
-!! result
+!! html
 <p>[[]]
 </p>
 !! end
 
 !! test
-Image with empty attribute (php)
+Image with empty attribute
 !! options
-php
-!! input
+parsoid=wt2html,wt2wt,html2html
+!! wikitext
 [[File:Foobar.jpg|right||Caption text]]
-!! result
+!! html/php
 <div class="floatright"><a href="/wiki/File:Foobar.jpg" class="image" title="Caption text"><img alt="Caption text" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a></div>
 
-!! end
-
-!! test
-Image with empty attribute (parsoid)
-!! options
-parsoid=wt2html
-!! input
-[[File:Foobar.jpg|right||Caption text]]
-!! result
+!! html/parsoid
 <figure class="mw-default-size mw-halign-right" typeof="mw:Image"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"></a><figcaption>Caption text</figcaption></figure>
 !! end
 
 !! test
 1. Block image with individual attributes from templates
-!! options
-parsoid
-!! input
+!! wikitext
 [[File:Foobar.jpg|thumb|{{echo|137px}}|This is a caption]]
-!! result
+!! html/php
+<div class="thumb tright"><div class="thumbinner" style="width:139px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/137px-Foobar.jpg" width="137" height="16" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/206px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/274px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div>This is a caption</div></div></div>
+
+!! html/parsoid
 <figure typeof="mw:Image/Thumb mw:ExpandedAttrs" data-mw='{"attribs":[["thumbnail",{"html":"thumb"}],["width",{"html":"&lt;span about=\"#mwt1\" typeof=\"mw:Transclusion\" data-mw=\"{&amp;quot;parts&amp;quot;:[{&amp;quot;template&amp;quot;:{&amp;quot;target&amp;quot;:{&amp;quot;wt&amp;quot;:&amp;quot;echo&amp;quot;,&amp;quot;href&amp;quot;:&amp;quot;./Template:Echo&amp;quot;},&amp;quot;params&amp;quot;:{&amp;quot;1&amp;quot;:{&amp;quot;wt&amp;quot;:&amp;quot;137px&amp;quot;}},&amp;quot;i&amp;quot;:0}}]}\" data-parsoid=\"{&amp;quot;dsr&amp;quot;:[24,38,null,null],&amp;quot;pi&amp;quot;:[[{&amp;quot;k&amp;quot;:&amp;quot;1&amp;quot;,&amp;quot;spc&amp;quot;:[&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;]}]]}\">137px&lt;/span>"}]]}'><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="16" width="137"/></a><figcaption>This is a caption</figcaption></figure>
 !! end
 
 !! test
 2. Block Image with individual attributes from templates
-!! options
-parsoid
-!! input
+!! wikitext
 [[File:Foobar.jpg|{{echo|thumb}}|{{echo|137px}}|This is a caption]]
-!! result
+!! html/php
+<div class="thumb tright"><div class="thumbinner" style="width:139px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/137px-Foobar.jpg" width="137" height="16" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/206px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/274px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div>This is a caption</div></div></div>
+
+!! html/parsoid
 <figure typeof="mw:Image/Thumb mw:ExpandedAttrs" data-mw='{"attribs":[["thumbnail",{"html":"&lt;span about=\"#mwt1\" typeof=\"mw:Transclusion\" data-mw=\"{&amp;quot;parts&amp;quot;:[{&amp;quot;template&amp;quot;:{&amp;quot;target&amp;quot;:{&amp;quot;wt&amp;quot;:&amp;quot;echo&amp;quot;,&amp;quot;href&amp;quot;:&amp;quot;./Template:Echo&amp;quot;},&amp;quot;params&amp;quot;:{&amp;quot;1&amp;quot;:{&amp;quot;wt&amp;quot;:&amp;quot;thumb&amp;quot;}},&amp;quot;i&amp;quot;:0}}]}\" data-parsoid=\"{&amp;quot;dsr&amp;quot;:[18,32,null,null],&amp;quot;pi&amp;quot;:[[{&amp;quot;k&amp;quot;:&amp;quot;1&amp;quot;,&amp;quot;spc&amp;quot;:[&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;]}]]}\">thumb&lt;/span>"}],["width",{"html":"&lt;span about=\"#mwt2\" typeof=\"mw:Transclusion\" data-mw=\"{&amp;quot;parts&amp;quot;:[{&amp;quot;template&amp;quot;:{&amp;quot;target&amp;quot;:{&amp;quot;wt&amp;quot;:&amp;quot;echo&amp;quot;,&amp;quot;href&amp;quot;:&amp;quot;./Template:Echo&amp;quot;},&amp;quot;params&amp;quot;:{&amp;quot;1&amp;quot;:{&amp;quot;wt&amp;quot;:&amp;quot;137px&amp;quot;}},&amp;quot;i&amp;quot;:0}}]}\" data-parsoid=\"{&amp;quot;dsr&amp;quot;:[33,47,null,null],&amp;quot;pi&amp;quot;:[[{&amp;quot;k&amp;quot;:&amp;quot;1&amp;quot;,&amp;quot;spc&amp;quot;:[&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;]}]]}\">137px&lt;/span>"}]]}'><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="16" width="137"/></a><figcaption>This is a caption</figcaption></figure>
 !! end
 
 !! test
 3. Inline image with individual attributes from templates
-!! options
-parsoid
-!! input
+!! wikitext
 [[File:Foobar.jpg|{{echo|50px}}]]
-!! result
+!! html/php
+<p><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/thumb/3/3a/Foobar.jpg/50px-Foobar.jpg" width="50" height="6" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/75px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/100px-Foobar.jpg 2x" /></a>
+</p>
+!! html/parsoid
 <p><span typeof="mw:Image mw:ExpandedAttrs" about="#mwt2" data-mw='{"attribs":[["width",{"html":"&lt;span about=\"#mwt1\" typeof=\"mw:Transclusion\" data-mw=\"{&amp;quot;parts&amp;quot;:[{&amp;quot;template&amp;quot;:{&amp;quot;target&amp;quot;:{&amp;quot;wt&amp;quot;:&amp;quot;echo&amp;quot;,&amp;quot;href&amp;quot;:&amp;quot;./Template:Echo&amp;quot;},&amp;quot;params&amp;quot;:{&amp;quot;1&amp;quot;:{&amp;quot;wt&amp;quot;:&amp;quot;50px&amp;quot;}},&amp;quot;i&amp;quot;:0}}]}\" data-parsoid=\"{&amp;quot;dsr&amp;quot;:[18,31,null,null],&amp;quot;pi&amp;quot;:[[{&amp;quot;k&amp;quot;:&amp;quot;1&amp;quot;,&amp;quot;spc&amp;quot;:[&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;]}]]}\">50px&lt;/span>"}]]}' data-parsoid='{"optList":[{"ck":"width","ak":"{{echo|50px}}"}]}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"}}'><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/50px-Foobar.jpg" height="6" width="50" data-parsoid='{"a":{"resource":"./File:Foobar.jpg","height":"6","width":"50"},"sa":{"resource":"File:Foobar.jpg"}}'/></a></span></p>
 !! end
 
-!! test
-Image with multiple attributes from the same template (php)
-!! options
-php
-!! input
-[[File:Foobar.jpg|{{image_attribs}}]]
-!! result
-<div class="floatright"><a href="/wiki/File:Foobar.jpg" class="image" title="Caption text"><img alt="Caption text" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a></div>
-
-!! end
-
 ## Parsoid does not provide editing support for images where templates produce multiple image attributes.
 ## To signal this, we add a 'mw:Placeholder' type to such images. This could change in the future.
 !! test
-Image with multiple attributes from the same template (parsoid)
-!! options
-parsoid
-!! input
+Image with multiple attributes from the same template
+!! wikitext
 [[File:Foobar.jpg|{{image_attribs}}]]
-!! result
+!! html/php
+<div class="floatright"><a href="/wiki/File:Foobar.jpg" class="image" title="Caption text"><img alt="Caption text" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a></div>
+
+!! html/parsoid
 <figure class="mw-default-size mw-halign-right" typeof="mw:Image mw:Placeholder"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"></a><figcaption>Caption text</figcaption></figure>
 !! end
 
 !! test
-Image with link tails (php)
-!! options
-php
-!! input
+Image with link tails
+!! wikitext
 123[[File:Foobar.jpg]]456
 123[[File:Foobar.jpg|right]]456
 123[[File:Foobar.jpg|thumb]]456
-!! result
+!! html/php
 <p>123<a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a>456
 </p>
 123<div class="floatright"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a></div>456
 123<div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" width="180" height="20" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/270px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/360px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div></div></div></div>456
 
-!! end
-
-!! test
-Image with link tails (parsoid)
-!! options
-parsoid
-!! input
-123[[File:Foobar.jpg]]456
-123[[File:Foobar.jpg|right]]456
-123[[File:Foobar.jpg|thumb]]456
-!! result
+!! html/parsoid
 <p>123<span class="mw-default-size" typeof="mw:Image"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"></a></span>456</p>
 123<figure class="mw-default-size mw-halign-right" typeof="mw:Image"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"></a></figure>456
 123<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" height="25" width="220"></a></figure>456
 !! end
 
 !! test
-Image with multiple captions -- only last one is accepted (php)
-!! options
-php
-!! input
+Image with multiple captions -- only last one is accepted
+!! wikitext
 [[File:Foobar.jpg|right|Caption1 - ignored|[[Caption2]] - ignored|Caption3 - accepted]]
-!! result
+!! html/php
 <div class="floatright"><a href="/wiki/File:Foobar.jpg" class="image" title="Caption3 - accepted"><img alt="Caption3 - accepted" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a></div>
 
-!! end
-
-!! test
-Image with multiple captions -- only last one is accepted (parsoid)
-!! options
-parsoid
-!! input
-[[File:Foobar.jpg|right|Caption1 - ignored|[[Caption2]] - ignored|Caption3 - accepted]]
-!! result
+!! html/parsoid
 <figure class="mw-default-size mw-halign-right" typeof="mw:Image"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"></a><figcaption>Caption3 - accepted</figcaption></figure>
 !! end
 
 !! test
-Image with multiple widths -- use last (php)
-!! options
-php
-!! input
+Image with multiple widths -- use last
+!! wikitext
 [[File:Foobar.jpg|200px|300px|caption]]
-!! result
+!! html/php
 <p><a href="/wiki/File:Foobar.jpg" class="image" title="caption"><img alt="caption" src="http://example.com/images/thumb/3/3a/Foobar.jpg/300px-Foobar.jpg" width="300" height="34" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/450px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/600px-Foobar.jpg 2x" /></a>
 </p>
-!! end
-
-!! test
-Image with multiple widths -- use last (parsoid)
-!! options
-parsoid
-!! input
-[[File:Foobar.jpg|200px|300px|caption]]
-!! result
+!! html/parsoid
 <p><span typeof="mw:Image" data-mw='{"caption":"caption"}'><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="34" width="300"/></a></span></p>
 !! end
 
 !! test
-Image with multiple alignments -- use first (bug 48664) (php)
-!! options
-php
-!! input
+Image with multiple alignments -- use first (bug 48664)
+!! wikitext
 [[File:Foobar.jpg|thumb|left|right|center|caption]]
 
 [[File:Foobar.jpg|middle|text-top|caption]]
-!! result
+!! html/php
 <div class="thumb tleft"><div class="thumbinner" style="width:182px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" width="180" height="20" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/270px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/360px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div>caption</div></div></div>
 <p><a href="/wiki/File:Foobar.jpg" class="image" title="caption"><img alt="caption" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" style="vertical-align: middle" /></a>
 </p>
-!! end
-
-!! test
-Image with multiple alignments -- use first (bug 48664) (parsoid)
-!! options
-parsoid
-!! input
-[[File:Foobar.jpg|thumb|left|right|center|caption]]
-
-[[File:Foobar.jpg|middle|text-top|caption]]
-!! result
+!! html/parsoid
 <figure class="mw-default-size mw-halign-left" typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="25" width="220"/></a><figcaption>caption</figcaption></figure>
 <p><span class="mw-default-size mw-valign-middle" typeof="mw:Image" data-mw='{"caption":"caption"}'><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"/></a></span></p>
 !! end
 
 !! test
-Image with width attribute at different positions (php)
-!! options
-php
-!! input
+Image with width attribute at different positions
+!! wikitext
 [[File:Foobar.jpg|200px|right|Caption]]
 [[File:Foobar.jpg|right|200px|Caption]]
 [[File:Foobar.jpg|right|Caption|200px]]
-!! result
+!! html/php
 <div class="floatright"><a href="/wiki/File:Foobar.jpg" class="image" title="Caption"><img alt="Caption" src="http://example.com/images/thumb/3/3a/Foobar.jpg/200px-Foobar.jpg" width="200" height="23" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/300px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/400px-Foobar.jpg 2x" /></a></div>
 <div class="floatright"><a href="/wiki/File:Foobar.jpg" class="image" title="Caption"><img alt="Caption" src="http://example.com/images/thumb/3/3a/Foobar.jpg/200px-Foobar.jpg" width="200" height="23" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/300px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/400px-Foobar.jpg 2x" /></a></div>
 <div class="floatright"><a href="/wiki/File:Foobar.jpg" class="image" title="Caption"><img alt="Caption" src="http://example.com/images/thumb/3/3a/Foobar.jpg/200px-Foobar.jpg" width="200" height="23" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/300px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/400px-Foobar.jpg 2x" /></a></div>
 
-!! end
-
-!! test
-Image with width attribute at different positions (parsoid)
-!! options
-parsoid
-!! input
-[[File:Foobar.jpg|200x200px|right|Caption]]
-[[File:Foobar.jpg|right|200x200px|Caption]]
-[[File:Foobar.jpg|right|Caption|200x200px]]
-!! result
+!! html/parsoid
 <figure class="mw-halign-right" typeof="mw:Image"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/200px-Foobar.jpg" height="23" width="200"></a><figcaption>Caption</figcaption></figure>
 <figure class="mw-halign-right" typeof="mw:Image"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/200px-Foobar.jpg" height="23" width="200"></a><figcaption>Caption</figcaption></figure>
 <figure class="mw-halign-right" typeof="mw:Image"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/200px-Foobar.jpg" height="23" width="200"></a><figcaption>Caption</figcaption></figure>
@@ -10202,356 +9904,433 @@ parsoid
 
 # a sad bit of backward-compatibility
 !! test
-Image with size specified with pxpx (bug 13500, 51628) (php)
+Image with size specified with pxpx (bug 13500, 51628)
 !! options
-php
-!! input
+parsoid=wt2html,wt2wt,html2html
+!! wikitext
 [[File:Foobar.jpg|20pxpx]]
 [[File:Foobar.jpg|200x20pxpx]]
-!! result
+!! html/php
 <p><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/thumb/3/3a/Foobar.jpg/20px-Foobar.jpg" width="20" height="2" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/30px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/40px-Foobar.jpg 2x" /></a>
 <a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/thumb/3/3a/Foobar.jpg/177px-Foobar.jpg" width="177" height="20" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/265px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/353px-Foobar.jpg 2x" /></a>
 </p>
-!! end
-
-!! test
-Image with size specified with pxpx (bug 13500, 51628) (parsoid)
-!! options
-parsoid=wt2html,wt2wt
-!! input
-[[File:Foobar.jpg|20pxpx]]
-[[File:Foobar.jpg|200x20pxpx]]
-!! result
+!! html/parsoid
 <p><span typeof="mw:Image"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="2" width="20"/></a></span><span typeof="mw:Image"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="20" width="177"/></a></span></p>
 !! end
 
 !! test
-Image with link parameter, wiki target (php)
-!! options
-php
-!! input
+Image with link parameter, wiki target
+!! wikitext
 [[File:Foobar.jpg|link=Main Page]]
-!! result
+!! html/php
 <p><a href="/wiki/Main_Page" title="Main Page"><img alt="Foobar.jpg" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a>
 </p>
-!! end
-
-!! test
-Image with link parameter, wiki target (parsoid)
-!! options
-parsoid
-!! input
-[[File:Foobar.jpg|link=Main Page]]
-!! result
+!! html/parsoid
 <p><span class="mw-default-size" typeof="mw:Image"><a href="Main_Page"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"></a></span></p>
 !! end
 
+# parsoid bug 49293 (part 1)
 !! test
-Image with link parameter, URL target (php)
-!! options
-php
-!! input
+Image with link parameter, URL target
+!! wikitext
 [[File:Foobar.jpg|link=http://example.com/]]
-!! result
+!! html/php
 <p><a href="http://example.com/" rel="nofollow"><img alt="Foobar.jpg" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a>
 </p>
-!! end
-
-# parsoid bug 49293 (part 1)
-!! test
-Image with link parameter, URL target (parsoid)
-!! options
-parsoid
-!! input
-[[File:Foobar.jpg|link=http://example.com/]]
-!! result
+!! html/parsoid
 <p><span class="mw-default-size" typeof="mw:Image"><a href="http://example.com/"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"></a></span></p>
 !! end
 
+# parsoid bug 49293 (part 2)
 !! test
-Image with link parameter, protocol-less URL target (php)
-!! options
-php
-!! input
+Image with link parameter, protocol-less URL target
+!! wikitext
 [[File:Foobar.jpg|link=//example.com/]]
-!! result
+!! html/php
 <p><a href="//example.com/" rel="nofollow"><img alt="Foobar.jpg" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a>
 </p>
-!! end
-
-# parsoid bug 49293 (part 2)
-!! test
-Image with link parameter, protocol-less URL target (parsoid)
-!! options
-parsoid
-!! input
-[[File:Foobar.jpg|link=//example.com/]]
-!! result
+!! html/parsoid
 <p><span class="mw-default-size" typeof="mw:Image"><a href="//example.com/"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"></a></span></p>
 !! end
 
 !! test
 Image with link parameter, wgExternalLinkTarget
-!! input
+!! wikitext
 [[Image:foobar.jpg|link=http://example.com/]]
 !! config
 wgExternalLinkTarget='foobar'
-!! result
+!! html
 <p><a href="http://example.com/" target="foobar" rel="nofollow"><img alt="Foobar.jpg" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a>
 </p>
 !! end
 
 !! test
 Image with link parameter, wgNoFollowLinks set to false
-!! input
+!! wikitext
 [[Image:foobar.jpg|link=http://example.com/]]
 !! config
 wgNoFollowLinks=false
-!! result
+!! html
 <p><a href="http://example.com/"><img alt="Foobar.jpg" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a>
 </p>
 !! end
 
 !! test
 Image with link parameter, wgNoFollowDomainExceptions
-!! input
+!! wikitext
 [[Image:foobar.jpg|link=http://example.com/]]
 !! config
 wgNoFollowDomainExceptions='example.com'
-!! result
+!! html
 <p><a href="http://example.com/"><img alt="Foobar.jpg" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a>
 </p>
 !! end
 
 !! test
 Image with link parameter, wgExternalLinkTarget, unnamed parameter
-!! input
+!! wikitext
 [[Image:foobar.jpg|link=http://example.com/|Title]]
 !! config
 wgExternalLinkTarget='foobar'
-!! result
+!! html
 <p><a href="http://example.com/" title="Title" target="foobar" rel="nofollow"><img alt="Title" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a>
 </p>
 !! end
 
 !! test
-Image with empty link parameter (php)
-!! options
-php
-!! input
+Image with empty link parameter
+!! wikitext
 [[File:Foobar.jpg|link=]]
-!! result
+!! html/php
 <p><img alt="Foobar.jpg" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" />
 </p>
-!! end
-
-!! test
-Image with empty link parameter (parsoid)
-!! options
-parsoid
-!! input
-[[File:Foobar.jpg|link=]]
-!! result
+!! html/parsoid
 <p><span class="mw-default-size" typeof="mw:Image"><span><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"></span></span></p>
 !! end
 
 !! test
-Image with link parameter (wiki target) and unnamed parameter (php)
-!! options
-php
-!! input
-[[File:Foobar.jpg|link=Main Page|Title]]
-!! result
+Image with link parameter (wiki target) and unnamed parameter
+!! wikitext
+[[File:Foobar.jpg|link=Main_Page|Title]]
+!! html/php
 <p><a href="/wiki/Main_Page" title="Title"><img alt="Title" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a>
 </p>
-!! end
-
-!! test
-Image with link parameter (wiki target) and unnamed parameter (parsoid)
-!! options
-parsoid
-!! input
-[[File:Foobar.jpg|link=Main Page|Title]]
-!! result
+!! html/parsoid
 <p><span class="mw-default-size" typeof="mw:Image" data-mw='{"caption":"Title"}'><a href="Main_Page"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"></a></span></p>
 !! end
 
 !! test
-Image with link parameter (URL target) and unnamed parameter (php)
-!! options
-php
-!! input
+Image with link parameter (URL target) and unnamed parameter
+!! wikitext
 [[File:Foobar.jpg|link=http://example.com/|Title]]
-!! result
+!! html/php
 <p><a href="http://example.com/" title="Title" rel="nofollow"><img alt="Title" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a>
 </p>
-!! end
-
-!! test
-Image with link parameter (URL target) and unnamed parameter (parsoid)
-!! options
-parsoid
-!! input
-[[File:Foobar.jpg|link=http://example.com/|Title]]
-!! result
+!! html/parsoid
 <p><span class="mw-default-size" typeof="mw:Image" data-mw='{"caption":"Title"}'><a href="http://example.com/"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"></a></span></p>
 !! end
 
 !! test
 Thumbnail image with link parameter
 !! options
-php
-!! input
-[[Image:foobar.jpg|thumb|link=http://example.com/|Title]]
-!! result
+parsoid=wt2html,wt2wt,html2html
+!! wikitext
+[[File:Foobar.jpg|thumb|link=http://example.com/|Title]]
+!! html/php
 <div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="http://example.com/"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" width="180" height="20" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/270px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/360px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div>Title</div></div></div>
 
+!! html/parsoid
+<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="http://example.com/"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="25" width="220"/></a><figcaption>Title</figcaption></figure>
 !! end
 
 !! test
 Manually-specified thumbnail image
-!! options
-php
-!! input
+!! wikitext
 [[Image:Foobar.jpg|thumb=Thumb.png|Title]]
-!! result
+!! html/php
 <div class="thumb tright"><div class="thumbinner" style="width:137px;"><a href="/wiki/File:Foobar.jpg"><img alt="" src="http://example.com/images/e/ea/Thumb.png" width="135" height="135" class="thumbimage" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div>Title</div></div></div>
 
+!! html/parsoid
+XXX NOT IMPLEMENTED XXX
 !! end
 
 !! test
 Manually-specified thumbnail image with explicit link to wiki page
-!! options
-php
-!! input
+!! wikitext
 [[Image:Foobar.jpg|thumb=Thumb.png|link=Main Page|Title]]
-!! result
+!! html/php
 <div class="thumb tright"><div class="thumbinner" style="width:137px;"><a href="/wiki/Main_Page" title="Main Page"><img alt="" src="http://example.com/images/e/ea/Thumb.png" width="135" height="135" class="thumbimage" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div>Title</div></div></div>
 
+!! html/parsoid
+XXX NOT IMPLEMENTED XXX
 !! end
 
 !! test
 Manually-specified thumbnail image with explicit link to url
-!! options
-php
-!! input
+!! wikitext
 [[Image:Foobar.jpg|thumb=Thumb.png|link=http://example.com|Title]]
-!! result
+!! html/php
 <div class="thumb tright"><div class="thumbinner" style="width:137px;"><a href="http://example.com"><img alt="" src="http://example.com/images/e/ea/Thumb.png" width="135" height="135" class="thumbimage" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div>Title</div></div></div>
 
+!! html/parsoid
+XXX NOT IMPLEMENTED XXX
 !! end
 
 !! test
 Manually-specified thumbnail image with explicit no link
-!! options
-php
-!! input
+!! wikitext
 [[Image:Foobar.jpg|thumb=Thumb.png|link=|Title]]
-!! result
+!! html/php
 <div class="thumb tright"><div class="thumbinner" style="width:137px;"><img alt="" src="http://example.com/images/e/ea/Thumb.png" width="135" height="135" class="thumbimage" />  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div>Title</div></div></div>
 
+!! html/parsoid
+XXX NOT IMPLEMENTED XXX
 !! end
 
 !! test
 Manually-specified thumbnail image with explicit link and alt text
-!! options
-php
-!! input
+!! wikitext
 [[Image:Foobar.jpg|thumb=Thumb.png|link=Main Page|alt=alttext|Title]]
-!! result
+!! html/php
 <div class="thumb tright"><div class="thumbinner" style="width:137px;"><a href="/wiki/Main_Page" title="Main Page"><img alt="alttext" src="http://example.com/images/e/ea/Thumb.png" width="135" height="135" class="thumbimage" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div>Title</div></div></div>
 
+!! html/parsoid
+XXX NOT IMPLEMENTED XXX
 !! end
 
 !! test
 Image with frame and link
-!! input
-[[Image:Foobar.jpg|frame|left|This is a test image [[Main Page]]]]
-!! result
+!! options
+parsoid=wt2html,wt2wt,html2html
+!! wikitext
+[[File:Foobar.jpg|frame|left|This is a test image [[Main Page]]]]
+!! html/php
 <div class="thumb tleft"><div class="thumbinner" style="width:1943px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" class="thumbimage" /></a>  <div class="thumbcaption">This is a test image <a href="/wiki/Main_Page" title="Main Page">Main Page</a></div></div></div>
 
+!! html/parsoid
+<figure class="mw-default-size mw-halign-left" typeof="mw:Image/Frame"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"/></a><figcaption>This is a test image <a rel="mw:WikiLink" href="Main_Page">Main Page</a></figcaption></figure>
 !! end
 
 !! test
 Image with frame and link and explicit alt
-!! input
+!! options
+parsoid=wt2html,wt2wt,html2html
+!! wikitext
 [[Image:Foobar.jpg|frame|left|This is a test image [[Main Page]]|alt=Altitude]]
-!! result
+!! html/php
 <div class="thumb tleft"><div class="thumbinner" style="width:1943px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Altitude" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" class="thumbimage" /></a>  <div class="thumbcaption">This is a test image <a href="/wiki/Main_Page" title="Main Page">Main Page</a></div></div></div>
 
+!! html/parsoid
+<figure class="mw-default-size mw-halign-left" typeof="mw:Image/Frame"><a href="File:Foobar.jpg"><img alt="Altitude" resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"/></a><figcaption>This is a test image <a rel="mw:WikiLink" href="Main_Page">Main Page</a></figcaption></figure>
 !! end
 
 !! test
 Image with wiki markup in implicit alt
-!! input
+!! options
+parsoid=wt2html,wt2wt,html2html
+!! wikitext
 [[Image:Foobar.jpg|testing '''bold''' in alt]]
-!! result
+
+[[Image:Foobar.jpg|alt=testing '''bold''' in alt]]
+!! html/php
 <p><a href="/wiki/File:Foobar.jpg" class="image" title="testing bold in alt"><img alt="testing bold in alt" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a>
+</p><p><a href="/wiki/File:Foobar.jpg" class="image"><img alt="testing bold in alt" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a>
 </p>
+!! html/parsoid
+<p><span class="mw-default-size" typeof="mw:Image" data-mw="{&quot;caption&quot;:&quot;testing '''bold''' in alt&quot;}"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"/></a></span></p>
+<p><span class="mw-default-size" typeof="mw:Image"><a href="File:Foobar.jpg"><img alt="testing bold in alt" resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"/></a></span></p>
 !! end
 
+###################
+# Image sizing.
+# See https://www.mediawiki.org/wiki/Help:Images#Size_and_frame
+# and https://bugzilla.wikimedia.org/show_bug.cgi?id=62258
+# Foobar has actual size of 1941x220
+# 1. Thumbs & frameless always reduce, can't be enlarged
+# 2. Framed images ignore width; always render at default size.
+#    If given a height, they respect height but continue to ignore width.
+# 3. "Unspecified format" and border are the only types which can be
+#    enlarged.
+
 !! test
-Image with wiki markup in explicit alt
-!! input
-[[Image:Foobar.jpg|alt=testing '''bold''' in alt]]
-!! result
-<p><a href="/wiki/File:Foobar.jpg" class="image"><img alt="testing bold in alt" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a>
+Image: "unspecified format" and border enlarge
+!! options
+parsoid=wt2html,wt2wt,html2html
+!! wikitext
+[[File:Foobar.jpg|2000px]]
+
+[[File:Foobar.jpg|border|2000px]]
+!! html/php
+<p><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/3/3a/Foobar.jpg" width="2000" height="227" /></a>
+</p><p><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/3/3a/Foobar.jpg" width="2000" height="227" class="thumbborder" /></a>
 </p>
+!! html/parsoid
+<p><span typeof="mw:Image"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="227" width="2000"/></a></span></p>
+<p><span class="mw-image-border" typeof="mw:Image"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="227" width="2000"/></a></span></p>
 !! end
 
+!! test
+Image: "unspecified format" and border reduce
+!! options
+parsoid=wt2html,wt2wt,html2html
+!! wikitext
+[[File:Foobar.jpg|1000px]]
+
+[[File:Foobar.jpg|border|1000px]]
+!! html/php
+<p><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/thumb/3/3a/Foobar.jpg/1000px-Foobar.jpg" width="1000" height="113" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/1500px-Foobar.jpg 1.5x, http://example.com/images/3/3a/Foobar.jpg 2x" /></a>
+</p><p><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/thumb/3/3a/Foobar.jpg/1000px-Foobar.jpg" width="1000" height="113" class="thumbborder" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/1500px-Foobar.jpg 1.5x, http://example.com/images/3/3a/Foobar.jpg 2x" /></a>
+</p>
+!! html/parsoid
+<p><span typeof="mw:Image"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="113" width="1000"/></a></span></p>
+<p><span class="mw-image-border" typeof="mw:Image"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="113" width="1000"/></a></span></p>
+!! end
+
+!! test
+Image: thumbs reduce
+!! options
+parsoid=wt2html,wt2wt,html2html
+!! wikitext
+[[File:Foobar.jpg|thumb|50px]]
+!! html/php
+<div class="thumb tright"><div class="thumbinner" style="width:52px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/thumb/3/3a/Foobar.jpg/50px-Foobar.jpg" width="50" height="6" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/75px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/100px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div></div></div></div>
+
+!! html/parsoid
+<figure typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="6" width="50"/></a></figure>
+!! end
+
+!! test
+Image: thumbs can't be enlarged past original size
+!! options
+parsoid=wt2html,wt2wt,html2html
+!! wikitext
+[[File:Foobar.jpg|thumb|2000px]]
+!! html/php
+<div class="thumb tright"><div class="thumbinner" style="width:1943px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" class="thumbimage" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div></div></div></div>
+
+!! html/parsoid
+<figure typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"/></a></figure>
+!! end
+
+!! test
+Image: frameless can reduce in size
+!! options
+parsoid=wt2html,wt2wt,html2html
+!! wikitext
+[[File:Foobar.jpg|frameless|50px]]
+!! html/php
+<p><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/thumb/3/3a/Foobar.jpg/50px-Foobar.jpg" width="50" height="6" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/75px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/100px-Foobar.jpg 2x" /></a>
+</p>
+!! html/parsoid
+<p><span typeof="mw:Image/Frameless"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="6" width="50"/></a></span></p>
+!! end
+
+!! test
+Image: frameless can't be enlarged past original size
+!! options
+parsoid=wt2html,wt2wt,html2html
+!! wikitext
+[[File:Foobar.jpg|frameless|2000px]]
+!! html/php
+<p><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a>
+</p>
+!! html/parsoid
+<p><span typeof="mw:Image/Frameless"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"/></a></span></p>
+!! end
+
+!! test
+Image: framed images ignore size if only width is given
+!! options
+parsoid=wt2html,wt2wt,html2html
+!! wikitext
+[[File:Foobar.jpg|frame]]
+
+[[File:Foobar.jpg|frame|50px]]
+
+[[File:Foobar.jpg|frame|2000px]]
+!! html/php
+<div class="thumb tright"><div class="thumbinner" style="width:1943px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" class="thumbimage" /></a>  <div class="thumbcaption"></div></div></div>
+<div class="thumb tright"><div class="thumbinner" style="width:1943px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" class="thumbimage" /></a>  <div class="thumbcaption"></div></div></div>
+<div class="thumb tright"><div class="thumbinner" style="width:1943px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" class="thumbimage" /></a>  <div class="thumbcaption"></div></div></div>
+
+!! html/parsoid
+<figure class="mw-default-size" typeof="mw:Image/Frame"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"/></a></figure><figure typeof="mw:Image/Frame"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"/></a></figure><figure typeof="mw:Image/Frame"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"/></a></figure>
+!! end
+
+!! test
+Image: framed images respect size if given a height, but ignore width.
+!! wikitext
+[[File:Foobar.jpg|frame|50x50px]]
+!! html/php
+<div class="thumb tright"><div class="thumbinner" style="width:444px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/thumb/3/3a/Foobar.jpg/442px-Foobar.jpg" width="442" height="50" class="thumbimage" /></a>  <div class="thumbcaption"></div></div></div>
+
+!! html/parsoid
+<figure typeof="mw:Image/Frame"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="50" width="442"/></a></figure>
+!! end
+
+###################
+
 !! test
 Link to image page- image page normally doesn't exists, hence edit link
 Add test with existing image page
 #<p><a href="/wiki/File:Test" title="Image:Test">Image:test</a>
-!! input
+!! wikitext
 [[:Image:test]]
-!! result
+!! html
 <p><a href="/index.php?title=File:Test&amp;action=edit&amp;redlink=1" class="new" title="File:Test (page does not exist)">Image:test</a>
 </p>
 !! end
 
 !! test
 bug 18784  Link to non-existent image page with caption should use caption as link text
-!! input
+!! wikitext
 [[:Image:test|caption]]
-!! result
+!! html
 <p><a href="/index.php?title=File:Test&amp;action=edit&amp;redlink=1" class="new" title="File:Test (page does not exist)">caption</a>
 </p>
 !! end
 
 !! test
 Frameless image caption with a free URL
-!! input
-[[Image:foobar.jpg|http://example.com]]
-!! result
+!! wikitext
+[[File:Foobar.jpg|http://example.com]]
+!! html/php
 <p><a href="/wiki/File:Foobar.jpg" class="image" title="http://example.com"><img alt="http://example.com" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a>
 </p>
+!! html/parsoid
+<p><span class="mw-default-size" typeof="mw:Image" data-mw='{"caption":"http://example.com"}'><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"/></a></span></p>
 !! end
 
 !! test
 Thumbnail image caption with a free URL
-!! input
-[[Image:foobar.jpg|thumb|http://example.com]]
-!! result
+!! wikitext
+[[File:Foobar.jpg|thumb|http://example.com]]
+!! html/php
 <div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" width="180" height="20" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/270px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/360px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div><a rel="nofollow" class="external free" href="http://example.com">http://example.com</a></div></div></div>
 
+!! html/parsoid
+<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="25" width="220"/></a><figcaption><a rel="mw:ExtLink" href="http://example.com">http://example.com</a></figcaption></figure>
 !! end
 
 !! test
 Thumbnail image caption with a free URL and explicit alt
-!! input
-[[Image:foobar.jpg|thumb|http://example.com|alt=Alteration]]
-!! result
+!! options
+parsoid=wt2html,wt2wt,html2html
+!! wikitext
+[[File:Foobar.jpg|thumb|http://example.com|alt=Alteration]]
+!! html/php
 <div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Alteration" src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" width="180" height="20" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/270px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/360px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div><a rel="nofollow" class="external free" href="http://example.com">http://example.com</a></div></div></div>
 
+!! html/parsoid
+<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img alt="Alteration" resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="25" width="220"/></a><figcaption><a rel="mw:ExtLink" href="http://example.com">http://example.com</a></figcaption></figure>
 !! end
 
 !! test
 SVG thumbnails with no language set
 !! options
-!! input
+!! wikitext
 [[File:Foobar.svg|thumb|caption]]
-!! result
+!! html
 <div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/File:Foobar.svg" class="image"><img alt="" src="http://example.com/images/thumb/f/ff/Foobar.svg/180px-Foobar.svg.png" width="180" height="180" class="thumbimage" srcset="http://example.com/images/thumb/f/ff/Foobar.svg/270px-Foobar.svg.png 1.5x, http://example.com/images/thumb/f/ff/Foobar.svg/360px-Foobar.svg.png 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.svg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div>caption</div></div></div>
 
 !! end
@@ -10559,9 +10338,9 @@ SVG thumbnails with no language set
 !! test
 SVG thumbnails with language de
 !! options
-!! input
+!! wikitext
 [[File:Foobar.svg|thumb|caption|lang=de]]
-!! result
+!! html
 <div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/index.php?title=File:Foobar.svg&amp;lang=de" class="image"><img alt="" src="http://example.com/images/thumb/f/ff/Foobar.svg/langde-180px-Foobar.svg.png" width="180" height="180" class="thumbimage" srcset="http://example.com/images/thumb/f/ff/Foobar.svg/langde-270px-Foobar.svg.png 1.5x, http://example.com/images/thumb/f/ff/Foobar.svg/langde-360px-Foobar.svg.png 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.svg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div>caption</div></div></div>
 
 !! end
@@ -10569,36 +10348,36 @@ SVG thumbnails with language de
 !! test
 SVG thumbnails with invalid language code
 !! options
-!! input
+!! wikitext
 [[File:Foobar.svg|thumb|caption|lang=invalid.language.code]]
-!! result
+!! html
 <div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/File:Foobar.svg" class="image"><img alt="" src="http://example.com/images/thumb/f/ff/Foobar.svg/180px-Foobar.svg.png" width="180" height="180" class="thumbimage" srcset="http://example.com/images/thumb/f/ff/Foobar.svg/270px-Foobar.svg.png 1.5x, http://example.com/images/thumb/f/ff/Foobar.svg/360px-Foobar.svg.png 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.svg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div>lang=invalid.language.code</div></div></div>
 
 !! end
 
 !! test
 BUG 1887: A ISBN with a thumbnail
-!! input
+!! wikitext
 [[Image:foobar.jpg|thumb|ISBN 1235467890]]
-!! result
+!! html
 <div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" width="180" height="20" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/270px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/360px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div><a href="/wiki/Special:BookSources/1235467890" class="internal mw-magiclink-isbn">ISBN 1235467890</a></div></div></div>
 
 !! end
 
 !! test
 BUG 1887: A RFC with a thumbnail
-!! input
+!! wikitext
 [[Image:foobar.jpg|thumb|This is RFC 12354]]
-!! result
+!! html
 <div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" width="180" height="20" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/270px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/360px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div>This is <a class="external mw-magiclink-rfc" rel="nofollow" href="//tools.ietf.org/html/rfc12354">RFC 12354</a></div></div></div>
 
 !! end
 
 !! test
 BUG 1887: A mailto link with a thumbnail
-!! input
+!! wikitext
 [[Image:foobar.jpg|thumb|Please mailto:nobody@example.com]]
-!! result
+!! html
 <div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" width="180" height="20" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/270px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/360px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div>Please <a rel="nofollow" class="external free" href="mailto:nobody@example.com">mailto:nobody@example.com</a></div></div></div>
 
 !! end
@@ -10606,82 +10385,82 @@ BUG 1887: A mailto link with a thumbnail
 # Pending resolution to bug 368
 !! test
 BUG 648: Frameless image caption with a link
-!! input
+!! wikitext
 [[Image:foobar.jpg|text with a [[link]] in it]]
-!! result
+!! html
 <p><a href="/wiki/File:Foobar.jpg" class="image" title="text with a link in it"><img alt="text with a link in it" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a>
 </p>
 !! end
 
 !! test
 BUG 648: Frameless image caption with a link (suffix)
-!! input
+!! wikitext
 [[Image:foobar.jpg|text with a [[link]]foo in it]]
-!! result
+!! html
 <p><a href="/wiki/File:Foobar.jpg" class="image" title="text with a linkfoo in it"><img alt="text with a linkfoo in it" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a>
 </p>
 !! end
 
 !! test
 BUG 648: Frameless image caption with an interwiki link
-!! input
+!! wikitext
 [[Image:foobar.jpg|text with a [[MeatBall:Link]] in it]]
-!! result
+!! html
 <p><a href="/wiki/File:Foobar.jpg" class="image" title="text with a MeatBall:Link in it"><img alt="text with a MeatBall:Link in it" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a>
 </p>
 !! end
 
 !! test
 BUG 648: Frameless image caption with a piped interwiki link
-!! input
+!! wikitext
 [[Image:foobar.jpg|text with a [[MeatBall:Link|link]] in it]]
-!! result
+!! html
 <p><a href="/wiki/File:Foobar.jpg" class="image" title="text with a link in it"><img alt="text with a link in it" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a>
 </p>
 !! end
 
 !! test
 Escape HTML special chars in image alt text
-!! input
+!! wikitext
 [[Image:foobar.jpg|& < > "]]
-!! result
+!! html
 <p><a href="/wiki/File:Foobar.jpg" class="image" title="&amp; &lt; &gt; &quot;"><img alt="&amp; &lt; &gt; &quot;" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a>
 </p>
 !! end
 
 !! test
 BUG 499: Alt text should have &#1234;, not &amp;1234;
-!! input
+!! wikitext
 [[Image:foobar.jpg|&#9792;]]
-!! result
+!! html
 <p><a href="/wiki/File:Foobar.jpg" class="image" title="♀"><img alt="♀" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a>
 </p>
 !! end
 
 !! test
 Broken image caption with link
-!! input
+!! wikitext
 [[Image:Foobar.jpg|thumb|This is a broken caption. But [[Main Page|this]] is just an ordinary link.
-!! result
+!! html
 <p>[[Image:Foobar.jpg|thumb|This is a broken caption. But <a href="/wiki/Main_Page" title="Main Page">this</a> is just an ordinary link.
 </p>
 !! end
 
 !! test
 Image caption containing another image
-!! input
+!! wikitext
 [[Image:Foobar.jpg|thumb|This is a caption with another [[Image:icon.png|image]] inside it!]]
-!! result
+!! html
 <div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" width="180" height="20" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/270px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/360px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div>This is a caption with another <a href="/index.php?title=Special:Upload&amp;wpDestFile=Icon.png" class="new" title="File:Icon.png">image</a> inside it!</div></div></div>
 
 !! end
 
 !! test
 Image caption containing a newline
-!! input
+!! wikitext
 [[Image:Foobar.jpg|This
 *is some text]]
-!! result
+!! html
 <p><a href="/wiki/File:Foobar.jpg" class="image" title="This *is some text"><img alt="This *is some text" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a>
 </p>
 !!end
@@ -10689,18 +10468,16 @@ Image caption containing a newline
 !!test
 Parsoid: Image caption containing leading space
 (The leading space should not trigger nowiki escaping in wt2wt mode)
-!! input
+!! wikitext
 [[Image:Foobar.jpg|thumb| bar]]
-!! result
+!! html
 <div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" width="180" height="20" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/270px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/360px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div>bar</div></div></div>
 
 !!end
 
 !! test
-Image caption containing a table (php)
-!! options
-php
-!! input
+Images: caption containing a table
+!! wikitext
 [[Image:Foobar.jpg|thumb|200px|This is an example image thumbnail caption with a table
 {|
 ! Foo !! Bar
@@ -10708,24 +10485,10 @@ php
 | Foo1 || Bar1
 |}
 and some more text.]]
-!! result
+!! html/php
 <div class="thumb tright"><div class="thumbinner" style="width:202px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/200px-Foobar.jpg" width="200" height="23" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/300px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/400px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div>This is an example image thumbnail caption with a table <table> <tr> <th> Foo </th> <th> Bar </th></tr> <tr> <td> Foo1 </td> <td> Bar1 </td></tr></table> and some more text.</div></div></div>
 
-!!end
-
-!! test
-Image caption containing a table (parsoid)
-!! options
-parsoid
-!! input
-[[Image:Foobar.jpg|thumb|200px|This is an example image thumbnail caption with a table
-{|
-! Foo !! Bar
-|-
-| Foo1 || Bar1
-|}
-and some more text.]]
-!! result
+!! html/parsoid
 <figure typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="23" width="200"/></a><figcaption>This is an example image thumbnail caption with a table
 <table>
 <tbody>
@@ -10737,51 +10500,87 @@ and some more text.]]
 
 !! test
 Bug 3090: External links other than http: in image captions
-!! input
-[[Image:Foobar.jpg|thumb|200px|This caption has [irc://example.net irc] and [https://example.com Secure] ext links in it.]]
-!! result
+!! wikitext
+[[File:Foobar.jpg|thumb|200x200px|This caption has [irc://example.net irc] and [https://example.com Secure] ext links in it.]]
+!! html/php
 <div class="thumb tright"><div class="thumbinner" style="width:202px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/200px-Foobar.jpg" width="200" height="23" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/300px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/400px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div>This caption has <a rel="nofollow" class="external text" href="irc://example.net">irc</a> and <a rel="nofollow" class="external text" href="https://example.com">Secure</a> ext links in it.</div></div></div>
 
+!! html/parsoid
+<figure typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="23" width="200"/></a><figcaption>This caption has <a rel="mw:ExtLink" href="irc://example.net">irc</a> and <a rel="mw:ExtLink" href="https://example.com">Secure</a> ext links in it.</figcaption></figure>
 !! end
 
 !! test
 Custom class
-!! input
+!! options
+parsoid=wt2html,wt2wt,html2html
+!! wikitext
 [[Image:foobar.jpg|a|class=b]]
-!! result
+!! html/php
 <p><a href="/wiki/File:Foobar.jpg" class="image" title="a"><img alt="a" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" class="b" /></a>
 </p>
+!! html/parsoid
+<p><span class="mw-default-size b" typeof="mw:Image" data-mw='{"caption":"a"}'><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"/></a></span></p>
 !! end
 
 !! test
 Localized image handling (1).
 !! options
+parsoid=wt2html,wt2wt,html2html
 language=es
-!! input
+!! wikitext
 [[Archivo:Foobar.jpg|izquierda|enlace=foo|caption]]
-!! result
+!! html/php
 <div class="floatleft"><a href="/wiki/Foo" title="caption"><img alt="caption" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a></div>
 
+!! html/parsoid
+<figure class="mw-default-size mw-halign-left" typeof="mw:Image"><a href="./Foo"><img resource="./Archivo:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"/></a><figcaption>caption</figcaption></figure>
 !! end
 
 !! test
 Localized image handling (2).
 !! options
+parsoid=wt2html,wt2wt,html2html
 language=es
-!! input
+!! wikitext
 [[Archivo:Foobar.jpg|miniatura|izquierda|enlace=foo|caption]]
-!! result
+!! html/php
 <div class="thumb tleft"><div class="thumbinner" style="width:182px;"><a href="/wiki/Foo" title="Foo"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" width="180" height="20" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/270px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/360px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/Archivo:Foobar.jpg" class="internal" title="Aumentar"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div>caption</div></div></div>
 
+!! html/parsoid
+<figure class="mw-default-size mw-halign-left" typeof="mw:Image/Thumb"><a href="./Foo"><img resource="./Archivo:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="25" width="220"/></a><figcaption>caption</figcaption></figure>
 !! end
 
 !! test
 "border", "frameless" and "class" attributes on an image.
-!! input
+!! options
+parsoid=wt2html,wt2wt,html2html
+!! wikitext
 [[File:Foobar.jpg|frameless|border|class=extra|caption]]
-!! result
+!! html/php
 <p><a href="/wiki/File:Foobar.jpg" class="image" title="caption"><img alt="caption" src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" width="180" height="20" class="extra thumbborder" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/270px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/360px-Foobar.jpg 2x" /></a>
 </p>
+!! html/parsoid
+<p><span class="mw-default-size mw-image-border extra" typeof="mw:Image/Frameless" data-mw='{"caption":"caption"}'><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="25" width="220"/></a></span></p>
+!! end
+
+# Note that 'right' is the default alignment, despite the misspelled 'righ' below
+!! test
+Invalid image attributes (bug 62500)
+!! options
+parsoid=wt2html,wt2wt,html2html
+!! wikitext
+[[File:Foobar.jpg|thumb|float|left|caption]]
+
+[[File:Foobar.jpg|thumb|righ|caption]]
+
+[[File:Foobar.jpg|bogus1|thumb|bogus2|left|bogus3|caption]]
+!! html/php
+<div class="thumb tleft"><div class="thumbinner" style="width:182px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" width="180" height="20" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/270px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/360px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div>caption</div></div></div>
+<div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" width="180" height="20" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/270px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/360px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div>caption</div></div></div>
+<div class="thumb tleft"><div class="thumbinner" style="width:182px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" width="180" height="20" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/270px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/360px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div>caption</div></div></div>
+
+!! html/parsoid
+<figure class="mw-default-size mw-halign-left" typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="25" width="220"/></a><figcaption>caption</figcaption></figure><figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="25" width="220"/></a><figcaption>caption</figcaption></figure><figure class="mw-default-size mw-halign-left" typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="25" width="220"/></a><figcaption>caption</figcaption></figure>
 !! end
 
 !! article
@@ -10792,9 +10591,9 @@ File:Barfoo.jpg
 
 !! test
 Redirected image
-!! input
+!! wikitext
 [[Image:Barfoo.jpg]]
-!! result
+!! html
 <p><a href="/wiki/File:Barfoo.jpg" title="File:Barfoo.jpg">File:Barfoo.jpg</a>
 </p>
 !! end
@@ -10803,9 +10602,9 @@ Redirected image
 Missing image with uploads disabled
 !! options
 wgEnableUploads=0
-!! input
+!! wikitext
 [[Image:Foobaz.jpg]]
-!! result
+!! html
 <p><a href="/wiki/File:Foobaz.jpg" title="File:Foobaz.jpg">File:Foobaz.jpg</a>
 </p>
 !! end
@@ -10819,11 +10618,9 @@ wgEnableUploads=0
 
 !! test
 Parsoid-specific image handling - simple image with size and middle alignment
-!! options
-parsoid
-!! input
+!! wikitext
 [[File:Foobar.jpg|middle|50px]]
-!! result
+!! html/parsoid
 <p><span class="mw-valign-middle" typeof="mw:Image">
 <a href="File:Foobar.jpg">
 <img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/50px-Foobar.jpg" height="6" width="50">
@@ -10837,9 +10634,9 @@ Parsoid-specific image handling - simple image with size, middle alignment,
 non-standard namespace alias
 !! options
 parsoid=wt2wt,wt2html,html2html
-!! input
+!! wikitext
 [[Image:Foobar.jpg|middle|50px]]
-!! result
+!! html/parsoid
 <p><span class="mw-valign-middle" typeof="mw:Image">
 <a href="File:Foobar.jpg">
 <img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/50px-Foobar.jpg" height="6" width="50">
@@ -10851,11 +10648,9 @@ parsoid=wt2wt,wt2html,html2html
 !! test
 Parsoid-specific image handling - simple image with size and middle alignment
 (existing content)
-!! options
-parsoid
-!! input
+!! wikitext
 [[File:Foobar.jpg|50px|middle]]
-!! result
+!! html/parsoid
 <p><span class="mw-valign-middle" typeof="mw:Image" data-parsoid='{"optList":[{"ck":"width","ak":"50px"},{"ck":"middle","ak":"middle"}]}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"}}'><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/50px-Foobar.jpg" height="6" width="50" data-parsoid='{"a":{"resource":"./File:Foobar.jpg","height":"6","width":"50"},"sa":{"resource":"File:Foobar.jpg"}}'/></a></span></p>
 !! end
 
@@ -10864,9 +10659,9 @@ Parsoid-specific image handling - simple image with size and middle alignment
 and non-standard namespace name
 !! options
 parsoid=wt2html,wt2wt,html2html
-!! input
+!! wikitext
 [[Image:Foobar.jpg|50px|middle]]
-!! result
+!! html/parsoid
 <p><span class="mw-valign-middle" typeof="mw:Image">
 <a href="File:Foobar.jpg">
 <img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/50px-Foobar.jpg" height="6" width="50">
@@ -10877,31 +10672,25 @@ parsoid=wt2html,wt2wt,html2html
 
 !! test
 Parsoid-specific image handling - simple image with both sizes, a baseline alignment, and a caption
-!! options
-parsoid
-!! input
+!! wikitext
 [[File:Foobar.jpg|500x10px|baseline|caption]]
-!! result
+!! html/parsoid
 <p><span class="mw-valign-baseline" typeof="mw:Image" data-mw='{"caption":"caption"}' data-parsoid='{"optList":[{"ck":"width","ak":"500x10px"},{"ck":"baseline","ak":"baseline"},{"ck":"caption","ak":"caption"}],"size":"500x10"}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"}}'><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/89px-Foobar.jpg" height="10" width="89" data-parsoid='{"a":{"resource":"./File:Foobar.jpg","height":"10","width":"89"},"sa":{"resource":"File:Foobar.jpg"}}'/></a></span></p>
 !! end
 
 !! test
 Parsoid-specific image handling - simple image with border and size spec
-!! options
-parsoid
-!! input
+!! wikitext
 [[File:Foobar.jpg|50px|border|caption]]
-!! result
+!! html/parsoid
 <p><span class="mw-image-border" typeof="mw:Image" data-mw='{"caption":"caption"}' data-parsoid='{"optList":[{"ck":"width","ak":"50px"},{"ck":"border","ak":"border"},{"ck":"caption","ak":"caption"}]}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"}}'><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/50px-Foobar.jpg" height="6" width="50" data-parsoid='{"a":{"resource":"./File:Foobar.jpg","height":"6","width":"50"},"sa":{"resource":"File:Foobar.jpg"}}'/></a></span></p>
 !! end
 
 !! test
 Parsoid-specific image handling - thumbnail with halign, valign, and caption
-!! options
-parsoid
-!! input
+!! wikitext
 [[File:Foobar.jpg|left|baseline|thumb|caption content]]
-!! result
+!! html/parsoid
 <figure class="mw-default-size mw-halign-left mw-valign-baseline" typeof="mw:Image/Thumb">
 <a href="File:Foobar.jpg">
 <img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" height="25" width="220" />
@@ -10913,21 +10702,17 @@ parsoid
 !! test
 Parsoid-specific image handling - thumbnail with halign, valign, and caption
 (existing content)
-!! options
-parsoid
-!! input
+!! wikitext
 [[File:Foobar.jpg|thumb|left|baseline|caption content]]
-!! result
+!! html/parsoid
 <figure class="mw-default-size mw-halign-left mw-valign-baseline" typeof="mw:Image/Thumb" data-parsoid='{"optList":[{"ck":"thumbnail","ak":"thumb"},{"ck":"left","ak":"left"},{"ck":"baseline","ak":"baseline"},{"ck":"caption","ak":"caption content"}]}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"}}'><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" height="25" width="220" data-parsoid='{"a":{"resource":"./File:Foobar.jpg","height":"25","width":"220"},"sa":{"resource":"File:Foobar.jpg"}}'/></a><figcaption>caption content</figcaption></figure>
 !! end
 
 !! test
 Parsoid-specific image handling - thumbnail with specific size, halign, valign, and caption
-!! options
-parsoid
-!! input
+!! wikitext
 [[Image:Foobar.jpg|right|middle|thumb|50x50px|caption]]
-!! result
+!! html/parsoid
 <figure class="mw-halign-right mw-valign-middle" typeof="mw:Image/Thumb">
 <a href="File:Foobar.jpg">
 <img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/50px-Foobar.jpg" height="6" width="50" />
@@ -10939,21 +10724,17 @@ parsoid
 !! test
 Parsoid-specific image handling - thumbnail with specific size, halign,
 valign, and caption (existing content)
-!! options
-parsoid
-!! input
+!! wikitext
 [[File:Foobar.jpg|thumb|50x50px|right|middle|caption]]
-!! result
+!! html/parsoid
 <figure class="mw-halign-right mw-valign-middle" typeof="mw:Image/Thumb" data-parsoid='{"optList":[{"ck":"thumbnail","ak":"thumb"},{"ck":"width","ak":"50x50px"},{"ck":"right","ak":"right"},{"ck":"middle","ak":"middle"},{"ck":"caption","ak":"caption"}],"size":"50x50"}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"}}'><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/50px-Foobar.jpg" height="6" width="50" data-parsoid='{"a":{"resource":"./File:Foobar.jpg","height":"6","width":"50"},"sa":{"resource":"File:Foobar.jpg"}}'/></a><figcaption>caption</figcaption></figure>
 !! end
 
 !! test
 Parsoid-specific image handling - framed image with specific size and caption
-!! options
-parsoid
-!! input
+!! wikitext
 [[Image:Foobar.jpg|frame|500x50px|caption]]
-!! result
+!! html/parsoid
 <figure typeof="mw:Image/Frame">
 <a href="File:Foobar.jpg">
 <img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/442px-Foobar.jpg" height="50" width="442" />
@@ -10965,21 +10746,17 @@ parsoid
 !! test
 Parsoid-specific image handling - framed image with specific size and caption
 (existing content)
-!! options
-parsoid
-!! input
+!! wikitext
 [[File:Foobar.jpg|442x50px|frame|caption]]
-!! result
+!! html/parsoid
 <figure typeof="mw:Image/Frame" data-parsoid='{"optList":[{"ck":"width","ak":"442x50px"},{"ck":"framed","ak":"frame"},{"ck":"caption","ak":"caption"}],"size":"442x50"}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"}}'><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/442px-Foobar.jpg" height="50" width="442" data-parsoid='{"a":{"resource":"./File:Foobar.jpg","height":"50","width":"442"},"sa":{"resource":"File:Foobar.jpg"}}'/></a><figcaption>caption</figcaption></figure>
 !! end
 
 !! test
 Parsoid-specific image handling - framed image with specific size, halign, valign, and caption
-!! options
-parsoid
-!! input
+!! wikitext
 [[Image:Foobar.jpg|left|baseline|frame|500x50px|caption]]
-!! result
+!! html/parsoid
 <figure class="mw-halign-left mw-valign-baseline" typeof="mw:Image/Frame">
 <a href="File:Foobar.jpg">
 <img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/442px-Foobar.jpg" height="50" width="442" />
@@ -10991,31 +10768,25 @@ parsoid
 !! test
 Parsoid-specific image handling - framed image with specific size, halign,
 valign, and caption (existing content)
-!! options
-parsoid
-!! input
+!! wikitext
 [[File:Foobar.jpg|442x50px|frame|left|baseline|caption]]
-!! result
+!! html/parsoid
 <figure class="mw-halign-left mw-valign-baseline" typeof="mw:Image/Frame" data-parsoid='{"optList":[{"ck":"width","ak":"442x50px"},{"ck":"framed","ak":"frame"},{"ck":"left","ak":"left"},{"ck":"baseline","ak":"baseline"},{"ck":"caption","ak":"caption"}],"size":"442x50"}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"}}'><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/442px-Foobar.jpg" height="50" width="442" data-parsoid='{"a":{"resource":"./File:Foobar.jpg","height":"50","width":"442"},"sa":{"resource":"File:Foobar.jpg"}}'/></a><figcaption>caption</figcaption></figure>
 !! end
 
 !! test
 Parsoid-specific image handling - frameless image with specific size, border, and caption
-!! options
-parsoid
-!! input
+!! wikitext
 [[File:Foobar.jpg|frameless|442x50px|border|caption]]
-!! result
+!! html/parsoid
 <p><span class="mw-image-border" typeof="mw:Image/Frameless" data-mw='{"caption":"caption"}' data-parsoid='{"optList":[{"ck":"frameless","ak":"frameless"},{"ck":"width","ak":"442x50px"},{"ck":"border","ak":"border"},{"ck":"caption","ak":"caption"}],"size":"442x50"}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"}}'><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/442px-Foobar.jpg" height="50" width="442" data-parsoid='{"a":{"resource":"./File:Foobar.jpg","height":"50","width":"442"},"sa":{"resource":"File:Foobar.jpg"}}'/></a></span></p>
 !! end
 
 !! test
 Parsoid-specific image handling - simple image with a formatted caption
-!! options
-parsoid
-!! input
+!! wikitext
 [[File:Foobar.jpg|<table><tr><td>a</td><td>b</td></tr><tr><td>c</td></tr></table>]]
-!! result
+!! html/parsoid
 <p><span class="mw-default-size" typeof="mw:Image" data-mw='{"caption":"&lt;table>&lt;tr>&lt;td>a&lt;/td>&lt;td>b&lt;/td>&lt;/tr>&lt;tr>&lt;td>c&lt;/td>&lt;/tr>&lt;/table>"}'>
 <a href="File:Foobar.jpg">
 <img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941">
@@ -11024,11 +10795,9 @@ parsoid
 
 !! test
 Parsoid-specific image handling - caption with a template in it
-!! options
-parsoid
-!! input
+!! wikitext
 [[File:Foobar.jpg|thumb|200x23px|This caption has a {{echo|transclusion}} in it.]]
-!! result
+!! html/parsoid
 <figure typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/200px-Foobar.jpg" height="23" width="200"></a><figcaption>This caption has a <span about="#mwt1" typeof="mw:Transclusion" data-mw="{&quot;parts&quot;:[{&quot;template&quot;:{&quot;target&quot;:{&quot;wt&quot;:&quot;echo&quot;,&quot;href&quot;:&quot;./Template:Echo&quot;},&quot;params&quot;:{&quot;1&quot;:{&quot;wt&quot;:&quot;transclusion&quot;}},&quot;i&quot;:0}}]}">transclusion</span> in it.</figcaption></figure>
 !! end
 
@@ -11036,11 +10805,11 @@ parsoid
 Parsoid-specific image handling - caption with unbalanced tags in it
 !! options
 parsoid=wt2html,wt2wt,html2html
-!! input
+!! wikitext
 foo
 [[File:Foobar.jpg|thumb|200x200px|This caption has a <center>unbalanced tag in it.]]
 bar
-!! result
+!! html/parsoid
 <p>foo</p>
 <figure typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="23" width="200"></a><figcaption>This caption has a <center>unbalanced tag in it.</center></figcaption></figure>
 <p>bar</p>
@@ -11048,33 +10817,27 @@ bar
 
 !! test
 Parsoid-specific image handling - empty caption
-!! options
-parsoid
-!! input
+!! wikitext
 [[File:Foobar.jpg|thumb|]]
-!! result
+!! html/parsoid
 <figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="25" width="220"/></a><figcaption></figcaption></figure>
 !! end
 
 !! test
 Parsoid-specific image handling - whitespace caption
-!! options
-parsoid
-!! input
+!! wikitext
 [[File:Foobar.jpg|thumb| ]]
-!! result
+!! html/parsoid
 <figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="25" width="220"/></a><figcaption> </figcaption></figure>
 !! end
 
 !! test
 Parsoid-specific image handling - lang option
-!! options
-parsoid
-!! input
+!! wikitext
 foo
 [[File:Foobar.svg|lang=de|caption]]
 bar
-!! result
+!! html/parsoid
 <p>foo
 <span class="mw-default-size" typeof="mw:Image" data-mw='{"caption":"caption"}'><a href="./File:Foobar.svg"><img resource="./File:Foobar.svg" src="//example.com/images/f/ff/Foobar.svg" lang="de" height="180" width="240"/></a></span>
 bar</p>
@@ -11094,9 +10857,9 @@ foo
 Subpage link
 !! options
 subpage title=[[Subpage test]]
-!! input
+!! wikitext
 [[/subpage]]
-!! result
+!! html
 <p><a href="/wiki/Subpage_test/subpage" title="Subpage test/subpage">/subpage</a>
 </p>
 !! end
@@ -11105,9 +10868,9 @@ subpage title=[[Subpage test]]
 Subpage noslash link
 !! options
 subpage title=[[Subpage test]]
-!!input
+!! wikitext
 [[/subpage/]]
-!! result
+!! html
 <p><a href="/wiki/Subpage_test/subpage" title="Subpage test/subpage">subpage</a>
 </p>
 !! end
@@ -11118,11 +10881,11 @@ Relative subpage noslash link
 !! options
 parsoid=wt2wt,wt2html,html2html
 subpage title=[[Subpage test/1/2/3/4]]
-!!input
+!! wikitext
 [[../../subpage/]]
 
 [[../../subpage]]
-!! result
+!! html
 <p><a rel="mw:WikiLink" href="Subpage_test/1/2/subpage/">subpage</a></p>
 <p><a rel="mw:WikiLink" href="Subpage_test/1/2/subpage">Subpage_test/1/2/subpage</a></p>
 !! end
@@ -11132,13 +10895,13 @@ subpage title=[[Subpage test/1/2/3/4]]
 Parsoid: dot-slash prefixed wikilinks
 !! options
 parsoid=wt2wt,wt2html,html2html
-!!input
+!! wikitext
 [[./foo]]
 
 [[././bar]]
 
 [[././baz/]]
-!! result
+!! html
 <p><a rel="mw:WikiLink" href="./Foo">foo</a></p>
 <p><a rel="mw:WikiLink" href="./Bar">bar</a></p>
 <p><a rel="mw:WikiLink" href="./Baz/">baz/</a></p>
@@ -11146,9 +10909,9 @@ parsoid=wt2wt,wt2html,html2html
 
 !! test
 Disabled subpages
-!! input
+!! wikitext
 [[/subpage]]
-!! result
+!! html
 <p><a href="/index.php?title=/subpage&amp;action=edit&amp;redlink=1" class="new" title="/subpage (page does not exist)">/subpage</a>
 </p>
 !! end
@@ -11157,9 +10920,9 @@ Disabled subpages
 BUG 561: {{/Subpage}}
 !! options
 subpage title=[[Page]]
-!! input
+!! wikitext
 {{/Subpage}}
-!! result
+!! html
 <p><a href="/index.php?title=Page/Subpage&amp;action=edit&amp;redlink=1" class="new" title="Page/Subpage (page does not exist)">Page/Subpage</a>
 </p>
 !! end
@@ -11175,9 +10938,9 @@ blah
 
 !! test
 Link to category
-!! input
+!! wikitext
 [[:Category:MediaWiki User's Guide]]
-!! result
+!! html
 <p><a href="/wiki/Category:MediaWiki_User%27s_Guide" title="Category:MediaWiki User's Guide">Category:MediaWiki User's Guide</a>
 </p>
 !! end
@@ -11186,17 +10949,17 @@ Link to category
 Simple category
 !! options
 cat
-!! input
+!! wikitext
 [[Category:MediaWiki User's Guide]]
-!! result
+!! html
 <a href="/wiki/Category:MediaWiki_User%27s_Guide" title="Category:MediaWiki User's Guide">MediaWiki User's Guide</a>
 !! end
 
 !! test
 PAGESINCATEGORY invalid title fatal (r33546 fix)
-!! input
+!! wikitext
 {{PAGESINCATEGORY:<bogus>}}
-!! result
+!! html
 <p>0
 </p>
 !! end
@@ -11205,9 +10968,9 @@ PAGESINCATEGORY invalid title fatal (r33546 fix)
 Category with different sort key
 !! options
 cat
-!! input
+!! wikitext
 [[Category:MediaWiki User's Guide|Foo]]
-!! result
+!! html
 <a href="/wiki/Category:MediaWiki_User%27s_Guide" title="Category:MediaWiki User's Guide">MediaWiki User's Guide</a>
 !! end
 
@@ -11215,9 +10978,9 @@ cat
 Category with identical sort key
 !! options
 cat
-!! input
+!! wikitext
 [[Category:MediaWiki User's Guide|MediaWiki User's Guide]]
-!! result
+!! html
 <a href="/wiki/Category:MediaWiki_User%27s_Guide" title="Category:MediaWiki User's Guide">MediaWiki User's Guide</a>
 !! end
 
@@ -11226,9 +10989,9 @@ Category with empty sort key
 !! options
 cat
 pst
-!! input
+!! wikitext
 [[Category:MediaWiki User's Guide|]]
-!! result
+!! html
 [[Category:MediaWiki User's Guide|MediaWiki User's Guide]]
 !! end
 
@@ -11237,9 +11000,9 @@ Category with empty sort key and parentheses
 !! options
 cat
 pst
-!! input
+!! wikitext
 [[Category:Foo (bar)|]]
-!! result
+!! html
 [[Category:Foo (bar)|Foo]]
 !! end
 
@@ -11248,9 +11011,9 @@ Category with link tail
 !! options
 cat
 pst
-!! input
+!! wikitext
 123[[Category:Foo]]456
-!! result
+!! html
 123[[Category:Foo]]456
 !! end
 
@@ -11259,9 +11022,9 @@ Category with template
 !! options
 cat
 pst
-!! input
+!! wikitext
 [[Category:{{echo|Foo}}]]
-!! result
+!! html
 [[Category:{{echo|Foo}}]]
 !! end
 
@@ -11270,9 +11033,9 @@ Category with template in sort key
 !! options
 cat
 pst
-!! input
+!! wikitext
 [[Category:Foo|{{echo|Bar}}]]
-!! result
+!! html
 [[Category:Foo|{{echo|Bar}}]]
 !! end
 
@@ -11281,15 +11044,15 @@ Category with template in sort key and title
 !! options
 cat
 pst
-!! input
+!! wikitext
 [[Category:{{echo|Foo}}|{{echo|Bar}}]]
-!! result
+!! html
 [[Category:{{echo|Foo}}|{{echo|Bar}}]]
 !! end
 
 !! test
 Category / paragraph interactions
-!! input
+!! wikitext
 Foo [[Category:Baz]] Bar
 
 Foo [[Category:Baz]]
@@ -11315,7 +11078,7 @@ Bar
 [[Category:Baz]]
  {{echo|[[Category:Baz]]}}
 [[Category:Baz]]
-!! result
+!! html
 <p>Foo Bar
 </p><p>Foo
 Bar
@@ -11331,11 +11094,11 @@ Bar
 Parsoid: Serialize link to category page with colon escape
 !! options
 parsoid
-!! input
+!! wikitext
 
 [[:Category:Foo]]
 [[:Category:Foo|Bar]]
-!! result
+!! html
 <p>
 <a rel="mw:WikiLink" href="Category:Foo">Category:Foo</a>
 <a rel="mw:WikiLink" href="Category:Foo">Bar</a>
@@ -11347,9 +11110,9 @@ Parsoid: Link prefix/suffixes aren't applied to category links
 !! options
 parsoid=wt2html,wt2wt,html2html
 language=is
-!! input
+!! wikitext
 x[[Category:Foo]]y
-!! result
+!! html
 <p>x<link rel="mw:PageProp/Category" href="Category:Foo">y</p>
 !! end
 
@@ -11357,11 +11120,11 @@ x[[Category:Foo]]y
 Parsoid: Serialize link to file page with colon escape
 !! options
 parsoid
-!! input
+!! wikitext
 
 [[:File:Foo.png]]
 [[:File:Foo.png|Bar]]
-!! result
+!! html
 <p>
 <a rel="mw:WikiLink" href="File:Foo.png">File:Foo.png</a>
 <a rel="mw:WikiLink" href="File:Foo.png">Bar</a>
@@ -11372,10 +11135,10 @@ parsoid
 Parsoid: Serialize a genuine category link without colon escape
 !! options
 parsoid
-!! input
+!! wikitext
 [[Category:Foo]]
 [[Category:Foo|Bar]]
-!! result
+!! html
 <link rel="mw:PageProp/Category" href="Category:Foo">
 <link rel="mw:PageProp/Category" href="Category:Foo#Bar">
 !! end
@@ -11384,9 +11147,9 @@ parsoid
 Parsoid: Defaultsort
 !! options
 parsoid
-!! input
+!! wikitext
 {{DEFAULTSORT:Foo}}
-!! result
+!! html
 <meta property="mw:PageProp/categorydefaultsort" content="Foo"/>
 !! end
 
@@ -11397,11 +11160,11 @@ parsoid
 Inter-language links
 !! options
 ill
-!! input
+!! wikitext
 [[es:Alimento]]
 [[fr:Nourriture]]
 [[zh:&#39135;&#21697;]]
-!! result
+!! html
 es:Alimento fr:Nourriture zh:食品
 !! end
 
@@ -11409,12 +11172,12 @@ es:Alimento fr:Nourriture zh:食品
 Duplicate interlanguage links (bug 24502)
 !! options
 ill
-!! input
+!! wikitext
 [[es:1]]
 [[es:2]]
 [[fr:1]]
 [[fr:2]]
-!! result
+!! html
 es:1 fr:1
 !! end
 
@@ -11423,7 +11186,7 @@ es:1 fr:1
 ###
 !! test
 Basic section headings
-!! input
+!! wikitext
 == Headline 1 ==
 Some text
 
@@ -11431,7 +11194,7 @@ Some text
 More
 ===Smaller headline===
 Blah blah
-!! result
+!! html
 <h2><span class="mw-headline" id="Headline_1">Headline 1</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=1" title="Edit section: Headline 1">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
 <p>Some text
 </p>
@@ -11445,7 +11208,7 @@ Blah blah
 
 !! test
 Section headings with TOC
-!! input
+!! wikitext
 == Headline 1 ==
 === Subheadline 1 ===
 ===== Skipping a level =====
@@ -11454,7 +11217,7 @@ Section headings with TOC
 == Headline 2 ==
 Some text
 ===Another headline===
-!! result
+!! html
 <div id="toc" class="toc"><div id="toctitle"><h2>Contents</h2></div>
 <ul>
 <li class="toclevel-1 tocsection-1"><a href="#Headline_1"><span class="tocnumber">1</span> <span class="toctext">Headline 1</span></a>
@@ -11492,7 +11255,7 @@ Some text
 # perl -e 'print "="x$_," Level $_ heading","="x$_,"\n" for 1..10'
 !! test
 Handling of sections up to level 6 and beyond
-!! input
+!! wikitext
 = Level 1 Heading=
 == Level 2 Heading==
 === Level 3 Heading===
@@ -11503,7 +11266,7 @@ Handling of sections up to level 6 and beyond
 ======== Level 8 Heading========
 ========= Level 9 Heading=========
 ========== Level 10 Heading==========
-!! result
+!! html
 <div id="toc" class="toc"><div id="toctitle"><h2>Contents</h2></div>
 <ul>
 <li class="toclevel-1 tocsection-1"><a href="#Level_1_Heading"><span class="tocnumber">1</span> <span class="toctext">Level 1 Heading</span></a>
@@ -11549,14 +11312,14 @@ Handling of sections up to level 6 and beyond
 
 !! test
 TOC regression (bug 9764)
-!! input
+!! wikitext
 == title 1 ==
 === title 1.1 ===
 ==== title 1.1.1 ====
 === title 1.2 ===
 == title 2 ==
 === title 2.1 ===
-!! result
+!! html
 <div id="toc" class="toc"><div id="toctitle"><h2>Contents</h2></div>
 <ul>
 <li class="toclevel-1 tocsection-1"><a href="#title_1"><span class="tocnumber">1</span> <span class="toctext">title 1</span></a>
@@ -11590,14 +11353,14 @@ TOC regression (bug 9764)
 TOC with wgMaxTocLevel=3 (bug 6204)
 !! options
 wgMaxTocLevel=3
-!! input
+!! wikitext
 == title 1 ==
 === title 1.1 ===
 ==== title 1.1.1 ====
 === title 1.2 ===
 == title 2 ==
 === title 2.1 ===
-!! result
+!! html
 <div id="toc" class="toc"><div id="toctitle"><h2>Contents</h2></div>
 <ul>
 <li class="toclevel-1 tocsection-1"><a href="#title_1"><span class="tocnumber">1</span> <span class="toctext">title 1</span></a>
@@ -11627,13 +11390,13 @@ wgMaxTocLevel=3
 TOC with wgMaxTocLevel=3 and two level four headings (bug 6204)
 !! options
 wgMaxTocLevel=3
-!! input
+!! wikitext
 ==Section 1==
 ===Section 1.1===
 ====Section 1.1.1====
 ====Section 1.1.1.1====
 ==Section 2==
-!! result
+!! html
 <div id="toc" class="toc"><div id="toctitle"><h2>Contents</h2></div>
 <ul>
 <li class="toclevel-1 tocsection-1"><a href="#Section_1"><span class="tocnumber">1</span> <span class="toctext">Section 1</span></a>
@@ -11656,10 +11419,10 @@ wgMaxTocLevel=3
 
 !! test
 Resolving duplicate section names
-!! input
+!! wikitext
 == Foo bar ==
 == Foo bar ==
-!! result
+!! html
 <h2><span class="mw-headline" id="Foo_bar">Foo bar</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=1" title="Edit section: Foo bar">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
 <h2><span class="mw-headline" id="Foo_bar_2">Foo bar</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=2" title="Edit section: Foo bar">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
 
@@ -11667,10 +11430,10 @@ Resolving duplicate section names
 
 !! test
 Resolving duplicate section names with differing case (bug 10721)
-!! input
+!! wikitext
 == Foo bar ==
 == Foo Bar ==
-!! result
+!! html
 <h2><span class="mw-headline" id="Foo_bar">Foo bar</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=1" title="Edit section: Foo bar">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
 <h2><span class="mw-headline" id="Foo_Bar_2">Foo Bar</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=2" title="Edit section: Foo Bar">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
 
@@ -11685,12 +11448,12 @@ Template:sections
 
 !! test
 Template with sections, __NOTOC__
-!! input
+!! wikitext
 __NOTOC__
 ==Section 0==
 {{sections}}
 ==Section 4==
-!! result
+!! html
 <h2><span class="mw-headline" id="Section_0">Section 0</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=1" title="Edit section: Section 0">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
 <h3><span class="mw-headline" id="Section_1">Section 1</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Template:Sections&amp;action=edit&amp;section=T-1" title="Template:Sections">edit</a><span class="mw-editsection-bracket">]</span></span></h3>
 <h2><span class="mw-headline" id="Section_2">Section 2</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Template:Sections&amp;action=edit&amp;section=T-2" title="Template:Sections">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
@@ -11700,11 +11463,11 @@ __NOTOC__
 
 !! test
 __NOEDITSECTION__ keyword
-!! input
+!! wikitext
 __NOEDITSECTION__
 ==Section 1==
 ==Section 2==
-!! result
+!! html
 <h2><span class="mw-headline" id="Section_1">Section 1</span></h2>
 <h2><span class="mw-headline" id="Section_2">Section 2</span></h2>
 
@@ -11712,21 +11475,21 @@ __NOEDITSECTION__
 
 !! test
 Link inside a section heading
-!! input
+!! wikitext
 ==Section with a [[Main Page|link]] in it==
-!! result
+!! html
 <h2><span class="mw-headline" id="Section_with_a_link_in_it">Section with a <a href="/wiki/Main_Page" title="Main Page">link</a> in it</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=1" title="Edit section: Section with a link in it">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
 
 !! end
 
 !! test
 TOC regression (bug 12077)
-!! input
+!! wikitext
 __TOC__
 == title 1 ==
 === title 1.1 ===
 == title 2 ==
-!! result
+!! html
 <div id="toc" class="toc"><div id="toctitle"><h2>Contents</h2></div>
 <ul>
 <li class="toclevel-1 tocsection-1"><a href="#title_1"><span class="tocnumber">1</span> <span class="toctext">title 1</span></a>
@@ -11746,22 +11509,22 @@ __TOC__
 
 !! test
 BUG 1219 URL next to image (good)
-!! input
+!! wikitext
 http://example.com [[Image:foobar.jpg]]
-!! result
+!! html
 <p><a rel="nofollow" class="external free" href="http://example.com">http://example.com</a> <a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a>
 </p>
 !!end
 
 !! test
 Short headings with trailing space should match behavior of Parser::doHeadings (bug 19910)
-!! input
+!! wikitext
 === 
 The line above must have a trailing space!
 === <!--
 --> <!-- -->
 But just in case it doesn't...
-!! result
+!! html
 <h1><span class="mw-headline" id=".3D">=</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=1" title="Edit section: =">edit</a><span class="mw-editsection-bracket">]</span></span></h1>
 <p>The line above must have a trailing space!
 </p>
@@ -11772,7 +11535,7 @@ But just in case it doesn't...
 
 !! test
 Header with special characters (bug 25462)
-!! input
+!! wikitext
 The tooltips shall not show entities to the user (ie. be double escaped)
 
 == text > text ==
@@ -11789,7 +11552,7 @@ section 4
 
 == text " text ==
 section 5
-!! result
+!! html
 <p>The tooltips shall not show entities to the user (ie. be double escaped)
 </p>
 <div id="toc" class="toc"><div id="toctitle"><h2>Contents</h2></div>
@@ -11822,12 +11585,12 @@ section 5
 !! test
 Headers with excess '=' characters
 (Are similar tests necessary beyond the 1st level?)
-!! input
+!! wikitext
 =foo==
 ==foo=
 =''italic'' heading==
 ==''italic'' heading=
-!! result
+!! html
 <div id="toc" class="toc"><div id="toctitle"><h2>Contents</h2></div>
 <ul>
 <li class="toclevel-1 tocsection-1"><a href="#foo.3D"><span class="tocnumber">1</span> <span class="toctext">foo=</span></a></li>
@@ -11847,7 +11610,7 @@ Headers with excess '=' characters
 !! test
 HTML headers vs TOC (bug 23393)
 (__NOEDITSECTION__ for clearer output, doesn't matter here)
-!! input
+!! wikitext
 <h1>Header 1</h1>
 == Header 1.1 ==
 == Header 1.2 ==
@@ -11857,7 +11620,7 @@ HTML headers vs TOC (bug 23393)
 == Header 2.1 ==
 == Header 2.2 ==
 __NOEDITSECTION__
-!! result
+!! html
 <div id="toc" class="toc"><div id="toctitle"><h2>Contents</h2></div>
 <ul>
 <li class="toclevel-1"><a href="#Header_1"><span class="tocnumber">1</span> <span class="toctext">Header 1</span></a>
@@ -11886,18 +11649,18 @@ __NOEDITSECTION__
 
 !! test
 BUG 1219 URL next to image (broken)
-!! input
+!! wikitext
 http://example.com[[Image:foobar.jpg]]
-!! result
+!! html
 <p><a rel="nofollow" class="external free" href="http://example.com">http://example.com</a><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a>
 </p>
 !!end
 
 !! test
 Bug 1186 news: in the middle of text
-!! input
+!! wikitext
 http://en.wikinews.org/wiki/Wikinews:Workplace
-!! result
+!! html
 <p><a rel="nofollow" class="external free" href="http://en.wikinews.org/wiki/Wikinews:Workplace">http://en.wikinews.org/wiki/Wikinews:Workplace</a>
 </p>
 !!end
@@ -11905,18 +11668,18 @@ http://en.wikinews.org/wiki/Wikinews:Workplace
 
 !! test
 Namespaced link must have a title
-!! input
+!! wikitext
 [[Project:]]
-!! result
+!! html
 <p>[[Project:]]
 </p>
 !!end
 
 !! test
 Namespaced link must have a title (bad fragment version)
-!! input
+!! wikitext
 [[Project:#fragment]]
-!! result
+!! html
 <p>[[Project:#fragment]]
 </p>
 !!end
@@ -11928,45 +11691,45 @@ Namespaced link must have a title (bad fragment version)
 
 !! test
 div with no attributes
-!! input
+!! wikitext
 <div>HTML rocks</div>
-!! result
+!! html
 <div>HTML rocks</div>
 
 !! end
 
 !! test
 div with double-quoted attribute
-!! input
+!! wikitext
 <div id="rock">HTML rocks</div>
-!! result
+!! html
 <div id="rock">HTML rocks</div>
 
 !! end
 
 !! test
 div with single-quoted attribute
-!! input
+!! wikitext
 <div id='rock'>HTML rocks</div>
-!! result
+!! html
 <div id="rock">HTML rocks</div>
 
 !! end
 
 !! test
 div with unquoted attribute
-!! input
+!! wikitext
 <div id=rock>HTML rocks</div>
-!! result
+!! html
 <div id="rock">HTML rocks</div>
 
 !! end
 
 !! test
 div with illegal double attributes
-!! input
+!! wikitext
 <div id="a" id="b">HTML rocks</div>
-!! result
+!! html
 <div id="b">HTML rocks</div>
 
 !!end
@@ -11977,9 +11740,9 @@ div with illegal double attributes
 div with empty attribute value, space before equals
 !! options
 parsoid
-!! input
+!! wikitext
 <div class =>HTML rocks</div>
-!! result
+!! html
 <div class="">HTML rocks</div>
 
 !! end
@@ -11990,9 +11753,9 @@ parsoid
 div with braces in attribute value
 !! options
 parsoid
-!! input
+!! wikitext
 <div title="{}">Foo</div>
-!! result
+!! html
 <div title="{}">Foo</div>
 !! end
 
@@ -12007,29 +11770,29 @@ parsoid
 div with empty attribute value, no space before equals
 !! options
 parsoid
-!! input
+!! wikitext
 <div class=>HTML rocks</div>
-!! result
+!! html
 <div class="">HTML rocks</div>
 
 !! end
 
 !! test
 HTML multiple attributes correction
-!! input
+!! wikitext
 <p class="error" class="awesome">Awesome!</p>
-!! result
+!! html
 <p class="awesome">Awesome!</p>
 
 !!end
 
 !! test
 Table multiple attributes correction
-!! input
+!! wikitext
 {|
 !+ class="error" class="awesome"| status
 |}
-!! result
+!! html
 <table>
 <tr>
 <th class="awesome"> status
@@ -12039,63 +11802,63 @@ Table multiple attributes correction
 
 !! test
 DIV IN UPPERCASE
-!! input
+!! wikitext
 <DIV ID="x">HTML ROCKS</DIV>
-!! result
+!! html
 <div id="x">HTML ROCKS</div>
 
 !!end
 
 !! test
 Non-ASCII pseudo-tags are rendered as text
-!! input
+!! wikitext
 <khyô>
-!! result
+!! html
 <p>&lt;khyô&gt;
 </p>
 !! end
 
 !! test
 Pseudo-tag with URL 'name' renders as url link
-!! input
+!! wikitext
 <http://example.com/>
-!! result
+!! html
 <p>&lt;<a rel="nofollow" class="external free" href="http://example.com/">http://example.com/</a>&gt;
 </p>
 !! end
 
 !! test
 text with amp in the middle of nowhere
-!! input
+!! wikitext
 Remember AT&T?
-!!result
+!! html
 <p>Remember AT&amp;T?
 </p>
 !! end
 
 !! test
 text with character entity: eacute
-!! input
+!! wikitext
 I always thought &eacute; was a cute letter.
-!! result
+!! html
 <p>I always thought &#233; was a cute letter.
 </p>
 !! end
 
 !! test
 text with entity-escaped character entity-like string: eacute
-!! input
+!! wikitext
 I always thought &amp;eacute; was a cute letter.
-!! result
+!! html
 <p>I always thought &amp;eacute; was a cute letter.
 </p>
 !! end
 
 !! test
 text with undefined character entity: xacute
-!! input
+!! wikitext
 I always thought &xacute; was a cute letter.
-!! result
+!! html
 <p>I always thought &amp;xacute; was a cute letter.
 </p>
 !! end
@@ -12105,11 +11868,11 @@ I always thought &xacute; was a cute letter.
 HTML5 tags
 !! options
 parsoid
-!! input
+!! wikitext
 <data value="5">five</data>
 <time datetime="2000-01-01T00:00Z">The new millenium started</time>
 <mark>This highlighted text</mark>
-!! result
+!! html
 <p><data value="5">five</data>
 <time datetime="2000-01-01T00:00Z">The new millenium started</time>
 <mark>This highlighted text</mark></p>
@@ -12117,9 +11880,9 @@ parsoid
 
 !! test
 HTML tag with leading space is parsed as text
-!! input
+!! wikitext
 < div>foo< /div>
-!! result
+!! html
 <p>&lt; div&gt;foo&lt; /div&gt;
 </p>
 !! end
@@ -12133,9 +11896,9 @@ HTML tag with leading space is parsed as text
 # the test case, instead of <big>
 !! test
 Ensure that HTML adoption agency algorithm is properly implemented.
-!! input
+!! wikitext
 <big>X<big>Y</big>Z</big>
-!! result
+!! html
 <p><big>X<big>Y</big>Z</big>
 </p>
 !! end
@@ -12143,9 +11906,9 @@ Ensure that HTML adoption agency algorithm is properly implemented.
 # This was bug 41545 in the PHP parser.
 !! test
 Nesting of <kbd>
-!! input
+!! wikitext
 <kbd>X<kbd>Y</kbd>Z</kbd>
-!! result
+!! html
 <p><kbd>X<kbd>Y</kbd>Z</kbd>
 </p>
 !! end
@@ -12155,45 +11918,45 @@ Nesting of <kbd>
 # not covered; see bug 51081 for discussion.
 !! test
 Nesting of <em>
-!! input
+!! wikitext
 <em>X<em>Y</em>Z</em>
-!! result
+!! html
 <p><em>X<em>Y</em>Z</em>
 </p>
 !! end
 
 !! test
 Nesting of <strong>
-!! input
+!! wikitext
 <strong>X<strong>Y</strong>Z</strong>
-!! result
+!! html
 <p><strong>X<strong>Y</strong>Z</strong>
 </p>
 !! end
 
 !! test
 Nesting of <q>
-!! input
+!! wikitext
 <q>X<q>Y</q>Z</q>
-!! result
+!! html
 <p><q>X<q>Y</q>Z</q>
 </p>
 !! end
 
 !! test
 Nesting of <ruby>
-!! input
+!! wikitext
 <ruby>X<ruby>Y</ruby>Z</ruby>
-!! result
+!! html
 <p><ruby>X<ruby>Y</ruby>Z</ruby>
 </p>
 !! end
 
 !! test
 Nesting of <bdo>
-!! input
+!! wikitext
 <bdo>X<bdo>Y</bdo>Z</bdo>
-!! result
+!! html
 <p><bdo>X<bdo>Y</bdo>Z</bdo>
 </p>
 !! end
@@ -12205,18 +11968,18 @@ Nesting of <bdo>
 
 !! test
 Media link
-!! input
+!! wikitext
 [[Media:Foobar.jpg]]
-!! result
+!! html
 <p><a href="http://example.com/images/3/3a/Foobar.jpg" class="internal" title="Foobar.jpg">Media:Foobar.jpg</a>
 </p>
 !! end
 
 !! test
 Media link with text
-!! input
+!! wikitext
 [[Media:Foobar.jpg|A neat file to look at]]
-!! result
+!! html
 <p><a href="http://example.com/images/3/3a/Foobar.jpg" class="internal" title="Foobar.jpg">A neat file to look at</a>
 </p>
 !! end
@@ -12225,36 +11988,36 @@ Media link with text
 !! test
 Media link with nasty text
 fixme: doBlockLevels won't wrap this in a paragraph because it contains a div
-!! input
+!! wikitext
 [[Media:Foobar.jpg|Safe Link<div style=display:none>" onmouseover="alert(document.cookie)" onfoo="</div>]]
-!! result
+!! html
 <a href="http://example.com/images/3/3a/Foobar.jpg" class="internal" title="Foobar.jpg">Safe Link&lt;div style="display:none"&gt;" onmouseover="alert(document.cookie)" onfoo="&lt;/div&gt;</a>
 
 !! end
 
 !! test
 Media link to nonexistent file (bug 1702)
-!! input
+!! wikitext
 [[Media:No such.jpg]]
-!! result
+!! html
 <p><a href="/index.php?title=Special:Upload&amp;wpDestFile=No_such.jpg" class="new" title="No such.jpg">Media:No such.jpg</a>
 </p>
 !! end
 
 !! test
 Image link to nonexistent file (bug 1850 - good)
-!! input
+!! wikitext
 [[Image:No such.jpg]]
-!! result
+!! html
 <p><a href="/index.php?title=Special:Upload&amp;wpDestFile=No_such.jpg" class="new" title="File:No such.jpg">File:No such.jpg</a>
 </p>
 !! end
 
 !! test
 :Image link to nonexistent file (bug 1850 - bad)
-!! input
+!! wikitext
 [[:Image:No such.jpg]]
-!! result
+!! html
 <p><a href="/index.php?title=File:No_such.jpg&amp;action=edit&amp;redlink=1" class="new" title="File:No such.jpg (page does not exist)">Image:No such.jpg</a>
 </p>
 !! end
@@ -12263,9 +12026,9 @@ Image link to nonexistent file (bug 1850 - good)
 
 !! test
 Character reference normalization in link text (bug 1938)
-!! input
+!! wikitext
 [[Main Page|this&that]]
-!! result
+!! html
 <p><a href="/wiki/Main_Page" title="Main Page">this&amp;that</a>
 </p>
 !!end
@@ -12280,13 +12043,13 @@ The page's name is U+05d0 U+05b7, with non-canonical form U+FB2E
 
 !! test
 (bug 19451) Links should refer to the normalized form.
-!! input
+!! wikitext
 [[&#xFB2E;]]
 [[&#x5d0;&#x5b7;]]
 [[&#x5d0;ַ]]
 [[א&#x5b7;]]
 [[אַ]]
-!! result
+!! html
 <p><a href="/wiki/%D7%90%D6%B7" title="אַ">&#xfb2e;</a>
 <a href="/wiki/%D7%90%D6%B7" title="אַ">&#x5d0;&#x5b7;</a>
 <a href="/wiki/%D7%90%D6%B7" title="אַ">&#x5d0;ַ</a>
@@ -12297,81 +12060,81 @@ The page's name is U+05d0 U+05b7, with non-canonical form U+FB2E
 
 !! test
 Empty attribute crash test (bug 2067)
-!! input
+!! wikitext
 <font color="">foo</font>
-!! result
+!! html
 <p><font color="">foo</font>
 </p>
 !! end
 
 !! test
 Empty attribute crash test single-quotes (bug 2067)
-!! input
+!! wikitext
 <font color=''>foo</font>
-!! result
+!! html
 <p><font color="">foo</font>
 </p>
 !! end
 
 !! test
 Attribute test: equals, then nothing
-!! input
+!! wikitext
 <font color=>foo</font>
-!! result
+!! html
 <p><font>foo</font>
 </p>
 !! end
 
 !! test
 Attribute test: unquoted value
-!! input
+!! wikitext
 <font color=x>foo</font>
-!! result
+!! html
 <p><font color="x">foo</font>
 </p>
 !! end
 
 !! test
 Attribute test: unquoted but illegal value (hash)
-!! input
+!! wikitext
 <font color=#x>foo</font>
-!! result
+!! html
 <p><font color="#x">foo</font>
 </p>
 !! end
 
 !! test
 Attribute test: no value
-!! input
+!! wikitext
 <font color>foo</font>
-!! result
+!! html
 <p><font color="color">foo</font>
 </p>
 !! end
 
 !! test
 Bug 2095: link with three closing brackets
-!! input
+!! wikitext
 [[Main Page]]]
-!! result
+!! html
 <p><a href="/wiki/Main_Page" title="Main Page">Main Page</a>]
 </p>
 !! end
 
 !! test
 Bug 2095: link with pipe and three closing brackets
-!! input
+!! wikitext
 [[Main Page|link]]]
-!! result
+!! html
 <p><a href="/wiki/Main_Page" title="Main Page">link</a>]
 </p>
 !! end
 
 !! test
 Bug 2095: link with pipe and three closing brackets, version 2
-!! input
+!! wikitext
 [[Main Page|[http://example.com/]]]
-!! result
+!! html
 <p><a href="/wiki/Main_Page" title="Main Page">[http://example.com/]</a>
 </p>
 !! end
@@ -12401,90 +12164,90 @@ Template:Div style
 
 !! test
 Bug 2304: HTML attribute safety (safe template; regression bug 2309)
-!! input
+!! wikitext
 <div title="{{test}}"></div>
-!! result
+!! html
 <div title="This is a test template"></div>
 
 !! end
 
 !! test
 Bug 2304: HTML attribute safety (dangerous template; 2309)
-!! input
+!! wikitext
 <div title="{{dangerous attribute}}"></div>
-!! result
+!! html
 <div title=""></div>
 
 !! end
 
 !! test
 Bug 2304: HTML attribute safety (dangerous style template; 2309)
-!! input
+!! wikitext
 <div style="{{dangerous style attribute}}"></div>
-!! result
+!! html
 <div style="/* insecure input */"></div>
 
 !! end
 
 !! test
 Bug 2304: HTML attribute safety (safe parameter; 2309)
-!! input
+!! wikitext
 {{div style|width: 200px}}
-!! result
+!! html
 <div style="float: right; width: 200px">Magic div</div>
 
 !! end
 
 !! test
 Bug 2304: HTML attribute safety (unsafe parameter; 2309)
-!! input
+!! wikitext
 {{div style|width: expression(alert(document.cookie))}}
-!! result
+!! html
 <div style="/* insecure input */">Magic div</div>
 
 !! end
 
 !! test
 Bug 2304: HTML attribute safety (unsafe breakout parameter; 2309)
-!! input
+!! wikitext
 {{div style|"><script>alert(document.cookie)</script>}}
-!! result
+!! html
 <div style="float: right;">&lt;script&gt;alert(document.cookie)&lt;/script&gt;"&gt;Magic div</div>
 
 !! end
 
 !! test
 Bug 2304: HTML attribute safety (unsafe breakout parameter 2; 2309)
-!! input
+!! wikitext
 {{div style|" ><script>alert(document.cookie)</script>}}
-!! result
+!! html
 <div style="float: right;">&lt;script&gt;alert(document.cookie)&lt;/script&gt;"&gt;Magic div</div>
 
 !! end
 
 !! test
 Bug 2304: HTML attribute safety (link)
-!! input
+!! wikitext
 <div title="[[Main Page]]"></div>
-!! result
+!! html
 <div title="&#91;&#91;Main Page]]"></div>
 
 !! end
 
 !! test
 Bug 2304: HTML attribute safety (italics)
-!! input
+!! wikitext
 <div title="''foobar''"></div>
-!! result
+!! html
 <div title="&#39;&#39;foobar&#39;&#39;"></div>
 
 !! end
 
 !! test
 Bug 2304: HTML attribute safety (bold)
-!! input
+!! wikitext
 <div title="'''foobar'''"></div>
-!! result
+!! html
 <div title="&#39;&#39;&#39;foobar&#39;&#39;&#39;"></div>
 
 !! end
@@ -12492,63 +12255,63 @@ Bug 2304: HTML attribute safety (bold)
 
 !! test
 Bug 2304: HTML attribute safety (ISBN)
-!! input
+!! wikitext
 <div title="ISBN 1234567890"></div>
-!! result
+!! html
 <div title="&#73;SBN 1234567890"></div>
 
 !! end
 
 !! test
 Bug 2304: HTML attribute safety (RFC)
-!! input
+!! wikitext
 <div title="RFC 1234"></div>
-!! result
+!! html
 <div title="&#82;FC 1234"></div>
 
 !! end
 
 !! test
 Bug 2304: HTML attribute safety (PMID)
-!! input
+!! wikitext
 <div title="PMID 1234567890"></div>
-!! result
+!! html
 <div title="&#80;MID 1234567890"></div>
 
 !! end
 
 !! test
 Bug 2304: HTML attribute safety (web link)
-!! input
+!! wikitext
 <div title="http://example.com/"></div>
-!! result
+!! html
 <div title="http&#58;//example.com/"></div>
 
 !! end
 
 !! test
 Bug 2304: HTML attribute safety (named web link)
-!! input
+!! wikitext
 <div title="[http://example.com/ link]"></div>
-!! result
+!! html
 <div title="&#91;http&#58;//example.com/ link]"></div>
 
 !! end
 
 !! test
 Bug 3244: HTML attribute safety (extension; safe)
-!! input
+!! wikitext
 <div style="<nowiki>background:blue</nowiki>"></div>
-!! result
+!! html
 <div style="background:blue"></div>
 
 !! end
 
 !! test
 Bug 3244: HTML attribute safety (extension; unsafe)
-!! input
+!! wikitext
 <div style="<nowiki>border-left:expression(alert(document.cookie))</nowiki>"></div>
-!! result
+!! html
 <div style="/* insecure input */"></div>
 
 !! end
@@ -12557,55 +12320,55 @@ Bug 3244: HTML attribute safety (extension; unsafe)
 
 !! test
 MSIE CSS safety test: spurious slash
-!! input
+!! wikitext
 <div style="background-image:u\rl(javascript:alert('boo'))">evil</div>
-!! result
+!! html
 <div style="/* insecure input */">evil</div>
 
 !! end
 
 !! test
 MSIE CSS safety test: hex code
-!! input
+!! wikitext
 <div style="background-image:u\72l(javascript:alert('boo'))">evil</div>
-!! result
+!! html
 <div style="/* insecure input */">evil</div>
 
 !! end
 
 !! test
 MSIE CSS safety test: comment in url
-!! input
+!! wikitext
 <div style="background-image:u/**/rl(javascript:alert('boo'))">evil</div>
-!! result
+!! html
 <div style="background-image:u rl(javascript:alert(&#39;boo&#39;))">evil</div>
 
 !! end
 
 !! test
 MSIE CSS safety test: comment in expression
-!! input
+!! wikitext
 <div style="background-image:expres/**/sion(alert('boo4'))">evil4</div>
-!! result
+!! html
 <div style="background-image:expres sion(alert(&#39;boo4&#39;))">evil4</div>
 
 !! end
 
 !! test
 CSS safety test (all browsers): vertical tab (bug 55332 / CVE-2013-4567)
-!! input
+!! wikitext
 <p style="font-size: 100px; background-image:url\b(https://www.google.com/images/srpr/logo6w.png)">A</p>
-!! result
+!! html
 <p style="/* invalid control char */">A</p>
 
 !! end
 
 !! test
 MSIE 6 CSS safety test: Fullwidth (bug 55332)
-!! input
+!! wikitext
 <p style="font-size: 100px; color: expression((title='XSSed'),'red')">A</p>
 <div style="top:EXPRESSION(alert())">B</div>
-!! result
+!! html
 <p style="/* insecure input */">A</p>
 <div style="/* insecure input */">B</div>
 
@@ -12613,10 +12376,10 @@ MSIE 6 CSS safety test: Fullwidth (bug 55332)
 
 !! test
 MSIE 6 CSS safety test: IPA extensions (bug 55332)
-!! input
+!! wikitext
 <div style="background-image:uʀʟ(javascript:alert())">A</div>
 <p style="font-size: 100px; color: expʀessɪoɴ((title='XSSed'),'red')">B</p>
-!! result
+!! html
 <div style="/* insecure input */">A</div>
 <p style="/* insecure input */">B</p>
 
@@ -12624,11 +12387,11 @@ MSIE 6 CSS safety test: IPA extensions (bug 55332)
 
 !! test
 MSIE 6 CSS safety test: sup/sub script (bug 55332)
-!! input
+!! wikitext
 <div style="background-image:url⁽javascript:alert())">A</div>
 <div style="background-image:url₍javascript:alert())">B</div>
 <p style="font-size: 100px; color: expressioⁿ((title='XSSed'),'red')">C</p>
-!! result
+!! html
 <div style="/* insecure input */">A</div>
 <div style="/* insecure input */">B</div>
 <p style="/* insecure input */">C</p>
@@ -12637,18 +12400,18 @@ MSIE 6 CSS safety test: sup/sub script (bug 55332)
 
 !! test
 Opera -o-link CSS
-!! input
+!! wikitext
 <div
 title="&#100;&#97;&#116;&#97;&#58;&#116;&#101;&#120;&#116;&#47;&#104;&#116;&#109;&#108;&#44;&#60;&#105;&#109;&#103;&#32;&#115;&#114;&#99;&#61;&#49;&#32;&#111;&#110;&#101;&#114;&#114;&#111;&#114;&#61;&#97;&#108;&#101;&#114;&#116;&#40;&#49;&#41;&#62;"
 style="-o-link:attr(title);-o-link-source:current">X</div>
-!! result
+!! html
 <div title="data:text/html,&lt;img src=1 onerror=alert(1)&gt;" style="/* insecure input */">X</div>
 
 !! end
 
 !! test
 MSIE 6 CSS safety test: Repetition markers (bug 55332)
-!! input
+!! wikitext
 <p style="font-size: 100px; color: expres〱ion((title='XSSed'),'red')">A</p>
 <p style="font-size: 100px; color: expresゝion((title='XSSed'),'red')">B</p>
 <p style="font-size: 100px; color: expresーion((title='XSSed'),'red')">C</p>
@@ -12656,7 +12419,7 @@ MSIE 6 CSS safety test: Repetition markers (bug 55332)
 <p style="font-size: 100px; color: expresﹽion((title='XSSed'),'red')">E</p>
 <p style="font-size: 100px; color: expresﹼion((title='XSSed'),'red')">F</p>
 <p style="font-size: 100px; color: expresーion((title='XSSed'),'red')">G</p>
-!! result
+!! html
 <p style="/* insecure input */">A</p>
 <p style="/* insecure input */">B</p>
 <p style="/* insecure input */">C</p>
@@ -12669,11 +12432,11 @@ MSIE 6 CSS safety test: Repetition markers (bug 55332)
 
 !! test
 Table attribute legitimate extension
-!! input
+!! wikitext
 {|
 !+ style="<nowiki>color:blue</nowiki>"| status
 |}
-!! result
+!! html
 <table>
 <tr>
 <th style="color:blue"> status
@@ -12683,11 +12446,11 @@ Table attribute legitimate extension
 
 !! test
 Table attribute safety
-!! input
+!! wikitext
 {|
 !+ style="<nowiki>border-width:expression(0+alert(document.cookie))</nowiki>"| status
 |}
-!! result
+!! html
 <table>
 <tr>
 <th style="/* insecure input */"> status
@@ -12697,18 +12460,18 @@ Table attribute safety
 
 !! test
 CSS line continuation 1
-!! input
+!! wikitext
 <div style="background-image: u\&#10;rl(test.jpg);"></div>
-!! result
+!! html
 <div style="/* insecure input */"></div>
 
 !! end
 
 !! test
 CSS line continuation 2
-!! input
+!! wikitext
 <div style="background-image: u\&#13;rl(test.jpg); "></div>
-!! result
+!! html
 <div style="/* insecure input */"></div>
 
 !! end
@@ -12721,9 +12484,9 @@ Template:Identity
 
 !! test
 Expansion of multi-line templates in attribute values (bug 6255)
-!! input
+!! wikitext
 <div style="background: {{identity|#00FF00}}">-</div>
-!! result
+!! html
 <div style="background: #00FF00">-</div>
 
 !! end
@@ -12731,19 +12494,19 @@ Expansion of multi-line templates in attribute values (bug 6255)
 
 !! test
 Expansion of multi-line templates in attribute values (bug 6255 sanity check)
-!! input
+!! wikitext
 <div style="background: 
 #00FF00">-</div>
-!! result
+!! html
 <div style="background: #00FF00">-</div>
 
 !! end
 
 !! test
 Expansion of multi-line templates in attribute values (bug 6255 sanity check 2)
-!! input
+!! wikitext
 <div style="background: &#10;#00FF00">-</div>
-!! result
+!! html
 <div style="background: &#10;#00FF00">-</div>
 
 !! end
@@ -12753,9 +12516,9 @@ Expansion of multi-line templates in attribute values (bug 6255 sanity check 2)
 ###
 !! test
 Parser hook: empty input
-!! input
+!! wikitext
 <tag></tag>
-!! result
+!! html
 <pre>
 ''
 array (
@@ -12766,9 +12529,9 @@ array (
 
 !! test
 Parser hook: empty input using terminated empty elements
-!! input
+!! wikitext
 <tag/>
-!! result
+!! html
 <pre>
 NULL
 array (
@@ -12779,9 +12542,9 @@ array (
 
 !! test
 Parser hook: empty input using terminated empty elements (space before)
-!! input
+!! wikitext
 <tag />
-!! result
+!! html
 <pre>
 NULL
 array (
@@ -12792,9 +12555,9 @@ array (
 
 !! test
 Parser hook: basic input
-!! input
+!! wikitext
 <tag>input</tag>
-!! result
+!! html
 <pre>
 'input'
 array (
@@ -12806,9 +12569,9 @@ array (
 
 !! test
 Parser hook: case insensitive
-!! input
+!! wikitext
 <TAG>input</TAG>
-!! result
+!! html
 <pre>
 'input'
 array (
@@ -12820,9 +12583,9 @@ array (
 
 !! test
 Parser hook: case insensitive, redux
-!! input
+!! wikitext
 <TaG>input</TAg>
-!! result
+!! html
 <pre>
 'input'
 array (
@@ -12835,9 +12598,9 @@ array (
 Parser hook: nested tags
 !! options
 noxml
-!! input
+!! wikitext
 <tag><tag></tag></tag>
-!! result
+!! html
 <pre>
 '<tag>'
 array (
@@ -12848,9 +12611,9 @@ array (
 
 !! test
 Parser hook: basic arguments
-!! input
+!! wikitext
 <tag width=200 height = "100" depth = '50' square></tag>
-!! result
+!! html
 <pre>
 ''
 array (
@@ -12865,9 +12628,9 @@ array (
 
 !! test
 Parser hook: argument containing a forward slash (bug 5344)
-!! input
+!! wikitext
 <tag filename='/tmp/bla'></tag>
-!! result
+!! html
 <pre>
 ''
 array (
@@ -12879,9 +12642,9 @@ array (
 
 !! test
 Parser hook: empty input using terminated empty elements (bug 2374)
-!! input
+!! wikitext
 <tag foo=bar/>text
-!! result
+!! html
 <pre>
 NULL
 array (
@@ -12894,11 +12657,11 @@ array (
 # </tag> should be output literally since there is no matching tag that begins it
 !! test
 Parser hook: basic arguments using terminated empty elements (bug 2374)
-!! input
+!! wikitext
 <tag width=200 height = "100" depth = '50' square/>
 other stuff
 </tag>
-!! result
+!! html
 <pre>
 NULL
 array (
@@ -12919,10 +12682,10 @@ array (
 
 !! test
 Parser hook: static parser hook not inside a comment
-!! input
+!! wikitext
 <statictag>hello, world</statictag>
 <statictag action=flush/>
-!! result
+!! html
 <p>hello, world
 </p>
 !! end
@@ -12930,10 +12693,10 @@ Parser hook: static parser hook not inside a comment
 
 !! test
 Parser hook: static parser hook inside a comment
-!! input
+!! wikitext
 <!-- <statictag>hello, world</statictag> -->
 <statictag action=flush/>
-!! result
+!! html
 <p><br />
 </p>
 !! end
@@ -12955,9 +12718,9 @@ Template:Map-one-parameter
 
 !! test
 Nested template calls
-!! input
+!! wikitext
 {{Map-one-parameter|One-parameter|param}}
-!! result
+!! html
 <p>(My parameter is: param)
 </p>
 !! end
@@ -12968,45 +12731,45 @@ Nested template calls
 ###
 !! test
 Sanitizer: Closing of open tags
-!! input
+!! wikitext
 <s></s><table></table>
-!! result
+!! html
 <s></s><table></table>
 
 !! end
 
 !! test
 Sanitizer: Closing of open but not closed tags
-!! input
+!! wikitext
 <s>foo
-!! result
+!! html
 <p><s>foo</s>
 </p>
 !! end
 
 !! test
 Sanitizer: Closing of closed but not open tags
-!! input
+!! wikitext
 </s>
-!! result
+!! html
 <p>&lt;/s&gt;
 </p>
 !! end
 
 !! test
 Sanitizer: Closing of closed but not open table tags
-!! input
+!! wikitext
 Table not started</td></tr></table>
-!! result
+!! html
 <p>Table not started&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
 </p>
 !! end
 
 !! test
 Sanitizer: Escaping of spaces, multibyte characters, colons & other stuff in id=""
-!! input
+!! wikitext
 <span id="æ: v">byte</span>[[#æ: v|backlink]]
-!! result
+!! html
 <p><span id=".C3.A6:_v">byte</span><a href="#.C3.A6:_v">backlink</a>
 </p>
 !! end
@@ -13015,9 +12778,9 @@ Sanitizer: Escaping of spaces, multibyte characters, colons & other stuff in id=
 Sanitizer: Validating the contents of the id attribute (bug 4515)
 !! options
 disabled
-!! input
+!! wikitext
 <br id=9 />
-!! result
+!! html
 Something, but definitely not <br id="9" />...
 !! end
 
@@ -13025,15 +12788,15 @@ Something, but definitely not <br id="9" />...
 Sanitizer: Validating id attribute uniqueness (bug 4515, bug 6301)
 !! options
 disabled
-!! input
+!! wikitext
 <br id="foo" /><br id="foo" />
-!! result
+!! html
 Something need to be done. foo-2 ? 
 !! end
 
 !! test
 Sanitizer: Validating that <meta> and <link> work, but only for Microdata
-!! input
+!! wikitext
 <div itemscope>
        <meta itemprop="hello" content="world">
        <meta http-equiv="refresh" content="5">
@@ -13042,7 +12805,7 @@ Sanitizer: Validating that <meta> and <link> work, but only for Microdata
        <link rel="stylesheet" href="{{SERVER}}">
        <link rel="stylesheet" itemprop="hello" href="{{SERVER}}">
 </div>
-!! result
+!! html
 <div itemscope="itemscope">
 <p>    <meta itemprop="hello" content="world" />
        &lt;meta http-equiv="refresh" content="5"&gt;
@@ -13059,7 +12822,7 @@ Sanitizer: Validating that <meta> and <link> work, but only for Microdata
 Language converter: output gets cut off unexpectedly (bug 5757)
 !! options
 language=zh
-!! input
+!! wikitext
 this bit is safe: }-
 
 but if we add a conversion instance: -{zh-cn:xxx;zh-tw:yyy}-
@@ -13067,7 +12830,7 @@ but if we add a conversion instance: -{zh-cn:xxx;zh-tw:yyy}-
 then we get cut off here: }-
 
 all additional text is vanished
-!! result
+!! html
 <p>this bit is safe: }-
 </p><p>but if we add a conversion instance: xxx
 </p><p>then we get cut off here: }-
@@ -13078,10 +12841,10 @@ all additional text is vanished
 !! test
 Self closed html pairs (bug 5487)
 !! options
-!! input
+!! wikitext
 <center><font id="bug" />Centered text</center>
 <div><font id="bug2" />In div text</div>
-!! result
+!! html
 <center>&lt;font id="bug" /&gt;Centered text</center>
 <div>&lt;font id="bug2" /&gt;In div text</div>
 
@@ -13093,27 +12856,27 @@ Self closed html pairs (bug 5487)
 
 !! test
 Punctuation: nbsp before exclamation
-!! input
+!! wikitext
 C'est grave !
-!! result
+!! html
 <p>C'est grave&#160;!
 </p>
 !! end
 
 !! test
 Punctuation: CSS !important (bug 11874)
-!! input
+!! wikitext
 <div style="width:50% !important">important</div>
-!! result
+!! html
 <div style="width:50% !important">important</div>
 
 !!end
 
 !! test
 Punctuation: CSS ! important (bug 11874; with space after)
-!! input
+!! wikitext
 <div style="width:50% ! important">important</div>
-!! result
+!! html
 <div style="width:50% ! important">important</div>
 
 !!end
@@ -13121,12 +12884,12 @@ Punctuation: CSS ! important (bug 11874; with space after)
 
 !! test
 HTML bullet list, closed tags (bug 5497)
-!! input
+!! wikitext
 <ul>
 <li>One</li>
 <li>Two</li>
 </ul>
-!! result
+!! html
 <ul>
 <li>One</li>
 <li>Two</li>
@@ -13138,12 +12901,12 @@ HTML bullet list, closed tags (bug 5497)
 HTML bullet list, unclosed tags (bug 5497)
 !! options
 disabled
-!! input
+!! wikitext
 <ul>
 <li>One
 <li>Two
 </ul>
-!! result
+!! html
 <ul>
 <li>One
 </li>
@@ -13155,12 +12918,12 @@ disabled
 
 !! test
 HTML ordered list, closed tags (bug 5497)
-!! input
+!! wikitext
 <ol>
 <li>One</li>
 <li>Two</li>
 </ol>
-!! result
+!! html
 <ol>
 <li>One</li>
 <li>Two</li>
@@ -13172,12 +12935,12 @@ HTML ordered list, closed tags (bug 5497)
 HTML ordered list, unclosed tags (bug 5497)
 !! options
 disabled
-!! input
+!! wikitext
 <ol>
 <li>One
 <li>Two
 </ol>
-!! result
+!! html
 <ol>
 <li>One
 </li>
@@ -13189,7 +12952,7 @@ disabled
 
 !! test
 HTML nested bullet list, closed tags (bug 5497)
-!! input
+!! wikitext
 <ul>
 <li>One</li>
 <li>Two:
@@ -13199,7 +12962,7 @@ HTML nested bullet list, closed tags (bug 5497)
 </ul>
 </li>
 </ul>
-!! result
+!! html
 <ul>
 <li>One</li>
 <li>Two:
@@ -13216,7 +12979,7 @@ HTML nested bullet list, closed tags (bug 5497)
 HTML nested bullet list, open tags (bug 5497)
 !! options
 disabled
-!! input
+!! wikitext
 <ul>
 <li>One
 <li>Two:
@@ -13225,7 +12988,7 @@ disabled
 <li>Sub-two
 </ul>
 </ul>
-!! result
+!! html
 <ul>
 <li>One
 </li>
@@ -13243,7 +13006,7 @@ disabled
 
 !! test
 HTML nested ordered list, closed tags (bug 5497)
-!! input
+!! wikitext
 <ol>
 <li>One</li>
 <li>Two:
@@ -13253,7 +13016,7 @@ HTML nested ordered list, closed tags (bug 5497)
 </ol>
 </li>
 </ol>
-!! result
+!! html
 <ol>
 <li>One</li>
 <li>Two:
@@ -13270,7 +13033,7 @@ HTML nested ordered list, closed tags (bug 5497)
 HTML nested ordered list, open tags (bug 5497)
 !! options
 disabled
-!! input
+!! wikitext
 <ol>
 <li>One
 <li>Two:
@@ -13279,7 +13042,7 @@ disabled
 <li>Sub-two
 </ol>
 </ol>
-!! result
+!! html
 <ol>
 <li>One
 </li>
@@ -13297,10 +13060,10 @@ disabled
 
 !! test
 HTML ordered list item with parameters oddity
-!! input
+!! wikitext
 <ol><li id="fragment">One</li>
 </ol>
-!! result
+!! html
 <ol><li id="fragment">One</li>
 </ol>
 
@@ -13308,7 +13071,7 @@ HTML ordered list item with parameters oddity
 
 !!test
 bug 5918: autonumbering
-!! input
+!! wikitext
 [http://first/] [http://second] [ftp://ftp]
 
 ftp://inlineftp
@@ -13318,7 +13081,7 @@ ftp://inlineftp
 [mailto:enclosed@mail.tld]
 
 mailto:inline@mail.tld
-!! result
+!! html
 <p><a rel="nofollow" class="external autonumber" href="http://first/">[1]</a> <a rel="nofollow" class="external autonumber" href="http://second">[2]</a> <a rel="nofollow" class="external autonumber" href="ftp://ftp">[3]</a>
 </p><p><a rel="nofollow" class="external free" href="ftp://inlineftp">ftp://inlineftp</a>
 </p><p><a rel="nofollow" class="external text" href="mailto:enclosed@mail.tld">With target</a>
@@ -13335,10 +13098,10 @@ mailto:inline@mail.tld
 
 !! test
 Fuzz testing: Parser13
-!! input
+!! wikitext
 {| 
 | http://a|
-!! result
+!! html
 <table>
 <tr>
 <td>
@@ -13350,10 +13113,10 @@ Fuzz testing: Parser13
 
 !! test
 Fuzz testing: Parser14
-!! input
+!! wikitext
 == onmouseover= ==
 http://__TOC__
-!! result
+!! html
 <h2><span class="mw-headline" id="onmouseover.3D">onmouseover=</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=1" title="Edit section: onmouseover=">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
 http://<div id="toc" class="toc"><div id="toctitle"><h2>Contents</h2></div>
 <ul>
@@ -13366,10 +13129,10 @@ http://<div id="toc" class="toc"><div id="toctitle"><h2>Contents</h2></div>
 
 !! test
 Fuzz testing: Parser14-table
-!! input
+!! wikitext
 ==a==
 {| STYLE=__TOC__
-!! result
+!! html
 <h2><span class="mw-headline" id="a">a</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=1" title="Edit section: a">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
 <table style="&#95;_TOC&#95;_">
 <tr><td></td></tr>
@@ -13382,10 +13145,10 @@ Fuzz testing: Parser14-table
 Fuzz testing: Parser16
 !! options
 noxml
-!! input
+!! wikitext
 {|
 !https://||||||
-!! result
+!! html
 <table>
 <tr>
 <th>https://</th>
@@ -13400,11 +13163,11 @@ noxml
 
 !! test
 Fuzz testing: Parser21
-!! input
+!! wikitext
 {|
 ! irc://{{ftp://a" onmouseover="alert('hello world');"
 |
-!! result
+!! html
 <table>
 <tr>
 <th> <a rel="nofollow" class="external free" href="irc://{{ftp://a">irc://{{ftp://a</a>" onmouseover="alert('hello world');"
@@ -13418,11 +13181,11 @@ Fuzz testing: Parser21
 
 !! test
 Fuzz testing: Parser22
-!! input
+!! wikitext
 http://===r:::https://b
 
 {|
-!!result
+!! html
 <p><a rel="nofollow" class="external free" href="http://===r:::https://b">http://===r:::https://b</a>
 </p>
 <table>
@@ -13436,7 +13199,7 @@ http://===r:::https://b
 Fuzz testing: Parser24
 !! options
 noxml
-!! input
+!! wikitext
 {|
 {{{|
 <u CLASS=
@@ -13445,7 +13208,7 @@ noxml
 
 MOVE YOUR MOUSE CURSOR OVER THIS TEXT
 |
-!! result
+!! html
 <table>
 {{{|
 <u class="&#124;">}}}} &gt;
@@ -13470,13 +13233,13 @@ MOVE YOUR MOUSE CURSOR OVER THIS TEXT
 # }}}blah" onmouseover="alert('hello world');" align="left"<b>MOVE MOUSE CURSOR OVER HERE</b>
 !!test
 Fuzz testing: Parser25 (bug 6055)
-!! input
+!! wikitext
 {{{
 | 
 <LI CLASS=||
  >
 }}}blah" onmouseover="alert('hello world');" align="left"'''MOVE MOUSE CURSOR OVER HERE
-!! result
+!! html
 <p>&lt;LI CLASS=blah" onmouseover="alert('hello world');" align="left"<b>MOVE MOUSE CURSOR OVER HERE</b>
 </p>
 !! end
@@ -13484,9 +13247,9 @@ Fuzz testing: Parser25 (bug 6055)
 !!test
 Fuzz testing: URL adjacent extension (with space, clean)
 !! options
-!! input
+!! wikitext
 http://example.com <nowiki>junk</nowiki>
-!! result
+!! html
 <p><a rel="nofollow" class="external free" href="http://example.com">http://example.com</a> junk
 </p>
 !!end
@@ -13494,9 +13257,9 @@ http://example.com <nowiki>junk</nowiki>
 !!test
 Fuzz testing: URL adjacent extension (no space, dirty; nowiki)
 !! options
-!! input
+!! wikitext
 http://example.com<nowiki>junk</nowiki>
-!! result
+!! html
 <p><a rel="nofollow" class="external free" href="http://example.com">http://example.com</a>junk
 </p>
 !!end
@@ -13504,27 +13267,27 @@ http://example.com<nowiki>junk</nowiki>
 !!test
 Fuzz testing: URL adjacent extension (no space, dirty; pre)
 !! options
-!! input
+!! wikitext
 http://example.com<pre>junk</pre>
-!! result
+!! html
 <a rel="nofollow" class="external free" href="http://example.com">http://example.com</a><pre>junk</pre>
 
 !!end
 
 !!test
 Fuzz testing: image with bogus manual thumbnail
-!!input
+!! wikitext
 [[Image:foobar.jpg|thumbnail= ]]
-!!result
+!! html
 <div class="thumb tright"><div class="thumbinner" style="width:182px;">Error creating thumbnail:   <div class="thumbcaption"></div></div></div>
 
 !!end
 
 !! test
 Fuzz testing: encoded newline in generated HTML replacements (bug 6577)
-!! input
+!! wikitext
 <pre dir="&#10;"></pre>
-!! result
+!! html
 <pre dir="&#10;"></pre>
 
 !! end
@@ -13532,7 +13295,7 @@ Fuzz testing: encoded newline in generated HTML replacements (bug 6577)
 !! test
 Parsing optional HTML elements (Bug 6171)
 !! options
-!! input
+!! wikitext
 <table>
   <tr>
     <td> Some tabular data</td>
@@ -13540,7 +13303,7 @@ Parsing optional HTML elements (Bug 6171)
     <td> And yet som tabular data</td>
   </tr>
 </table>
-!! result
+!! html
 <table>
   <tr>
     <td> Some tabular data</td>
@@ -13554,7 +13317,7 @@ Parsing optional HTML elements (Bug 6171)
 !! test
 Correct handling of <td>, <tr> (Bug 6171)
 !! options
-!! input
+!! wikitext
 <table>
   <tr>
     <td> Some tabular data</td>
@@ -13562,7 +13325,7 @@ Correct handling of <td>, <tr> (Bug 6171)
     <td> And yet som tabular data</td>
   </tr>
 </table>
-!! result
+!! html
 <table>
   <tr>
     <td> Some tabular data</td>
@@ -13576,20 +13339,20 @@ Correct handling of <td>, <tr> (Bug 6171)
 
 !! test
 Parsing crashing regression (fr:JavaScript)
-!! input
+!! wikitext
 </body></x>
-!! result
+!! html
 <p>&lt;/body&gt;&lt;/x&gt;
 </p>
 !! end
 
 !! test
 Inline wiki vs wiki block nesting
-!! input
+!! wikitext
 '''Bold paragraph
 
 New wiki paragraph
-!! result
+!! html
 <p><b>Bold paragraph</b>
 </p><p>New wiki paragraph
 </p>
@@ -13599,11 +13362,11 @@ New wiki paragraph
 Inline HTML vs wiki block nesting
 !! options
 disabled
-!! input
+!! wikitext
 <b>Bold paragraph
 
 New wiki paragraph
-!! result
+!! html
 <p><b>Bold paragraph</b>
 </p><p>New wiki paragraph
 </p>
@@ -13618,9 +13381,9 @@ New wiki paragraph
 !!test
 Mixing markup for italics and bold
 !! options
-!! input
+!! wikitext
 '''bold''''''bold''bolditalics'''''
-!! result
+!! html
 <p>'<i>bold'</i><b>bold<i>bolditalics</i></b>
 </p>
 !! end
@@ -13635,9 +13398,9 @@ Article for special page transclusion test
 !! test
 Special page transclusion
 !! options
-!! input
+!! wikitext
 {{Special:Prefixindex/Xyzzyx}}
-!! result
+!! html
 <table class="mw-prefixindex-list-table"><tr><td><a href="/wiki/Xyzzyx" title="Xyzzyx">Xyzzyx</a></td></tr></table>
 
 !! end
@@ -13645,10 +13408,10 @@ Special page transclusion
 !! test
 Special page transclusion twice (bug 5021)
 !! options
-!! input
+!! wikitext
 {{Special:Prefixindex/Xyzzyx}}
 {{Special:Prefixindex/Xyzzyx}}
-!! result
+!! html
 <table class="mw-prefixindex-list-table"><tr><td><a href="/wiki/Xyzzyx" title="Xyzzyx">Xyzzyx</a></td></tr></table>
 <table class="mw-prefixindex-list-table"><tr><td><a href="/wiki/Xyzzyx" title="Xyzzyx">Xyzzyx</a></td></tr></table>
 
@@ -13656,45 +13419,45 @@ Special page transclusion twice (bug 5021)
 
 !! test
 Transclusion of default MediaWiki message
-!! input
+!! wikitext
 {{MediaWiki:Mainpage}}
-!!result
+!! html
 <p>Main Page
 </p>
 !! end
 
 !! test
 Transclusion of nonexistent MediaWiki message
-!! input
+!! wikitext
 {{MediaWiki:Mainpagexxx}}
-!!result
+!! html
 <p><a href="/index.php?title=MediaWiki:Mainpagexxx&amp;action=edit&amp;redlink=1" class="new" title="MediaWiki:Mainpagexxx (page does not exist)">MediaWiki:Mainpagexxx</a>
 </p>
 !! end
 
 !! test
 Transclusion of MediaWiki message with underscore
-!! input
+!! wikitext
 {{MediaWiki:history_short}}
-!! result
+!! html
 <p>History
 </p>
 !! end
 
 !! test
 Transclusion of MediaWiki message with space
-!! input
+!! wikitext
 {{MediaWiki:history short}}
-!! result
+!! html
 <p>History
 </p>
 !! end
 
 !! test
 Invalid header with following text
-!! input
+!! wikitext
 = x = y
-!! result
+!! html
 <p>= x = y
 </p>
 !! end
@@ -13704,7 +13467,7 @@ Invalid header with following text
 Section extraction test (section 0)
 !! options
 section=0
-!! input
+!! wikitext
 start
 ==a==
 ===aa===
@@ -13716,7 +13479,7 @@ start
 ===bc===
 ==c==
 ===ca===
-!! result
+!! html
 start
 !! end
 
@@ -13724,7 +13487,7 @@ start
 Section extraction test (section 1)
 !! options
 section=1
-!! input
+!! wikitext
 start
 ==a==
 ===aa===
@@ -13736,7 +13499,7 @@ start
 ===bc===
 ==c==
 ===ca===
-!! result
+!! html
 ==a==
 ===aa===
 ====aaa====
@@ -13746,7 +13509,7 @@ start
 Section extraction test (section 2)
 !! options
 section=2
-!! input
+!! wikitext
 start
 ==a==
 ===aa===
@@ -13758,7 +13521,7 @@ start
 ===bc===
 ==c==
 ===ca===
-!! result
+!! html
 ===aa===
 ====aaa====
 !! end
@@ -13767,7 +13530,7 @@ start
 Section extraction test (section 3)
 !! options
 section=3
-!! input
+!! wikitext
 start
 ==a==
 ===aa===
@@ -13779,7 +13542,7 @@ start
 ===bc===
 ==c==
 ===ca===
-!! result
+!! html
 ====aaa====
 !! end
 
@@ -13787,7 +13550,7 @@ start
 Section extraction test (section 4)
 !! options
 section=4
-!! input
+!! wikitext
 start
 ==a==
 ===aa===
@@ -13799,7 +13562,7 @@ start
 ===bc===
 ==c==
 ===ca===
-!! result
+!! html
 ==b==
 ===ba===
 ===bb===
@@ -13811,7 +13574,7 @@ start
 Section extraction test (section 5)
 !! options
 section=5
-!! input
+!! wikitext
 start
 ==a==
 ===aa===
@@ -13823,7 +13586,7 @@ start
 ===bc===
 ==c==
 ===ca===
-!! result
+!! html
 ===ba===
 !! end
 
@@ -13831,7 +13594,7 @@ start
 Section extraction test (section 6)
 !! options
 section=6
-!! input
+!! wikitext
 start
 ==a==
 ===aa===
@@ -13843,7 +13606,7 @@ start
 ===bc===
 ==c==
 ===ca===
-!! result
+!! html
 ===bb===
 ====bba====
 !! end
@@ -13852,7 +13615,7 @@ start
 Section extraction test (section 7)
 !! options
 section=7
-!! input
+!! wikitext
 start
 ==a==
 ===aa===
@@ -13864,7 +13627,7 @@ start
 ===bc===
 ==c==
 ===ca===
-!! result
+!! html
 ====bba====
 !! end
 
@@ -13872,7 +13635,7 @@ start
 Section extraction test (section 8)
 !! options
 section=8
-!! input
+!! wikitext
 start
 ==a==
 ===aa===
@@ -13884,7 +13647,7 @@ start
 ===bc===
 ==c==
 ===ca===
-!! result
+!! html
 ===bc===
 !! end
 
@@ -13892,7 +13655,7 @@ start
 Section extraction test (section 9)
 !! options
 section=9
-!! input
+!! wikitext
 start
 ==a==
 ===aa===
@@ -13904,7 +13667,7 @@ start
 ===bc===
 ==c==
 ===ca===
-!! result
+!! html
 ==c==
 ===ca===
 !! end
@@ -13913,7 +13676,7 @@ start
 Section extraction test (section 10)
 !! options
 section=10
-!! input
+!! wikitext
 start
 ==a==
 ===aa===
@@ -13925,7 +13688,7 @@ start
 ===bc===
 ==c==
 ===ca===
-!! result
+!! html
 ===ca===
 !! end
 
@@ -13933,7 +13696,7 @@ start
 Section extraction test (nonexistent section 11)
 !! options
 section=11
-!! input
+!! wikitext
 start
 ==a==
 ===aa===
@@ -13945,18 +13708,18 @@ start
 ===bc===
 ==c==
 ===ca===
-!! result
+!! html
 !! end
 
 !! test
 Section extraction test with bogus heading (section 1)
 !! options
 section=1
-!! input
+!! wikitext
 ==a==
 ==bogus== not a legal section
 ==b==
-!! result
+!! html
 ==a==
 ==bogus== not a legal section
 !! end
@@ -13965,11 +13728,11 @@ section=1
 Section extraction test with bogus heading (section 2)
 !! options
 section=2
-!! input
+!! wikitext
 ==a==
 ==bogus== not a legal section
 ==b==
-!! result
+!! html
 ==b==
 !! end
 
@@ -13977,11 +13740,11 @@ section=2
 Section extraction test with comment after heading (section 1)
 !! options
 section=1
-!! input
+!! wikitext
 ==a==
 ==b== <!-- -->
 ==c==
-!! result
+!! html
 ==a==
 !! end
 
@@ -13989,11 +13752,11 @@ section=1
 Section extraction test with comment after heading (section 2)
 !! options
 section=2
-!! input
+!! wikitext
 ==a==
 ==b== <!-- -->
 ==c==
-!! result
+!! html
 ==b== <!-- -->
 !! end
 
@@ -14001,11 +13764,11 @@ section=2
 Section extraction test with bogus <nowiki> heading (section 1)
 !! options
 section=1
-!! input
+!! wikitext
 ==a==
 ==bogus== <nowiki>not a legal section</nowiki>
 ==b==
-!! result
+!! html
 ==a==
 ==bogus== <nowiki>not a legal section</nowiki>
 !! end
@@ -14014,11 +13777,11 @@ section=1
 Section extraction test with bogus <nowiki> heading (section 2)
 !! options
 section=2
-!! input
+!! wikitext
 ==a==
 ==bogus== <nowiki>not a legal section</nowiki>
 ==b==
-!! result
+!! html
 ==b==
 !! end
 
@@ -14029,10 +13792,10 @@ section=2
 Section extraction prefixed by comment (section 1)
 !! options
 section=1
-!! input
+!! wikitext
 <!-- -->==sec1==
 ==sec2==
-!!result
+!! html
 ==sec2==
 !!end
 
@@ -14040,10 +13803,10 @@ section=1
 Section extraction prefixed by comment (section 2)
 !! options
 section=2
-!! input
+!! wikitext
 <!-- -->==sec1==
 ==sec2==
-!!result
+!! html
 
 !!end
 
@@ -14054,14 +13817,14 @@ section=2
 Section extraction, mixed wiki and html (section 1)
 !! options
 section=1
-!! input
+!! wikitext
 <h2>unmarked</h2>
 unmarked
 ==1==
 one
 ==2==
 two
-!! result
+!! html
 ==1==
 one
 !! end
@@ -14070,14 +13833,14 @@ one
 Section extraction, mixed wiki and html (section 2)
 !! options
 section=2
-!! input
+!! wikitext
 <h2>unmarked</h2>
 unmarked
 ==1==
 one
 ==2==
 two
-!! result
+!! html
 ==2==
 two
 !! end
@@ -14088,10 +13851,10 @@ two
 Section extraction, heading surrounded by <noinclude>
 !! options
 section=1
-!! input
+!! wikitext
 <noinclude>==unmarked==</noinclude>
 ==marked==
-!! result
+!! html
 ==marked==
 !!end
 
@@ -14100,13 +13863,13 @@ section=1
 Sectiion with all-equals
 !! options
 section=2
-!! input
+!! wikitext
 === 
 The line above must have a trailing space
 === <!--
 --> <!-- -->
 But just in case it doesn't...
-!! result
+!! html
 === <!--
 --> <!-- -->
 But just in case it doesn't...
@@ -14116,7 +13879,7 @@ But just in case it doesn't...
 Section replacement test (section 0)
 !! options
 replace=0,"xxx"
-!! input
+!! wikitext
 start
 ==a==
 ===aa===
@@ -14128,7 +13891,7 @@ start
 ===bc===
 ==c==
 ===ca===
-!! result
+!! html
 xxx
 
 ==a==
@@ -14147,7 +13910,7 @@ xxx
 Section replacement test (section 1)
 !! options
 replace=1,"xxx"
-!! input
+!! wikitext
 start
 ==a==
 ===aa===
@@ -14159,7 +13922,7 @@ start
 ===bc===
 ==c==
 ===ca===
-!! result
+!! html
 start
 xxx
 
@@ -14176,7 +13939,7 @@ xxx
 Section replacement test (section 2)
 !! options
 replace=2,"xxx"
-!! input
+!! wikitext
 start
 ==a==
 ===aa===
@@ -14188,7 +13951,7 @@ start
 ===bc===
 ==c==
 ===ca===
-!! result
+!! html
 start
 ==a==
 xxx
@@ -14206,7 +13969,7 @@ xxx
 Section replacement test (section 3)
 !! options
 replace=3,"xxx"
-!! input
+!! wikitext
 start
 ==a==
 ===aa===
@@ -14218,7 +13981,7 @@ start
 ===bc===
 ==c==
 ===ca===
-!! result
+!! html
 start
 ==a==
 ===aa===
@@ -14237,7 +14000,7 @@ xxx
 Section replacement test (section 4)
 !! options
 replace=4,"xxx"
-!! input
+!! wikitext
 start
 ==a==
 ===aa===
@@ -14249,7 +14012,7 @@ start
 ===bc===
 ==c==
 ===ca===
-!! result
+!! html
 start
 ==a==
 ===aa===
@@ -14264,7 +14027,7 @@ xxx
 Section replacement test (section 5)
 !! options
 replace=5,"xxx"
-!! input
+!! wikitext
 start
 ==a==
 ===aa===
@@ -14276,7 +14039,7 @@ start
 ===bc===
 ==c==
 ===ca===
-!! result
+!! html
 start
 ==a==
 ===aa===
@@ -14295,7 +14058,7 @@ xxx
 Section replacement test (section 6)
 !! options
 replace=6,"xxx"
-!! input
+!! wikitext
 start
 ==a==
 ===aa===
@@ -14307,7 +14070,7 @@ start
 ===bc===
 ==c==
 ===ca===
-!! result
+!! html
 start
 ==a==
 ===aa===
@@ -14325,7 +14088,7 @@ xxx
 Section replacement test (section 7)
 !! options
 replace=7,"xxx"
-!! input
+!! wikitext
 start
 ==a==
 ===aa===
@@ -14337,7 +14100,7 @@ start
 ===bc===
 ==c==
 ===ca===
-!! result
+!! html
 start
 ==a==
 ===aa===
@@ -14356,7 +14119,7 @@ xxx
 Section replacement test (section 8)
 !! options
 replace=8,"xxx"
-!! input
+!! wikitext
 start
 ==a==
 ===aa===
@@ -14368,7 +14131,7 @@ start
 ===bc===
 ==c==
 ===ca===
-!! result
+!! html
 start
 ==a==
 ===aa===
@@ -14387,7 +14150,7 @@ xxx
 Section replacement test (section 9)
 !! options
 replace=9,"xxx"
-!! input
+!! wikitext
 start
 ==a==
 ===aa===
@@ -14399,7 +14162,7 @@ start
 ===bc===
 ==c==
 ===ca===
-!! result
+!! html
 start
 ==a==
 ===aa===
@@ -14416,7 +14179,7 @@ xxx
 Section replacement test (section 10)
 !! options
 replace=10,"xxx"
-!! input
+!! wikitext
 start
 ==a==
 ===aa===
@@ -14428,7 +14191,7 @@ start
 ===bc===
 ==c==
 ===ca===
-!! result
+!! html
 start
 ==a==
 ===aa===
@@ -14446,11 +14209,11 @@ xxx
 Section replacement test with initial whitespace (bug 13728)
 !! options
 replace=2,"xxx"
-!! input
+!! wikitext
  Preformatted initial line
 ==a==
 ===a===
-!! result
+!! html
  Preformatted initial line
 ==a==
 xxx
@@ -14461,10 +14224,10 @@ xxx
 Section extraction, heading followed by pre with 20 spaces (bug 6398)
 !! options
 section=1
-!! input
+!! wikitext
 ==a==
                     a
-!! result
+!! html
 ==a==
                     a
 !! end
@@ -14473,10 +14236,10 @@ section=1
 Section extraction, heading followed by pre with 19 spaces (bug 6398 sanity check)
 !! options
 section=1
-!! input
+!! wikitext
 ==a==
                    a
-!! result
+!! html
 ==a==
                    a
 !! end
@@ -14486,7 +14249,7 @@ section=1
 Section extraction, <pre> around bogus header (bug 10309)
 !! options
 noxml section=2
-!! input
+!! wikitext
 == Section One ==
 <pre>
 =======
@@ -14494,7 +14257,7 @@ noxml section=2
 
 == Section Two ==
 stuff
-!! result
+!! html
 == Section Two ==
 stuff
 !! end
@@ -14503,7 +14266,7 @@ stuff
 Section replacement, <pre> around bogus header (bug 10309)
 !! options
 noxml replace=2,"xxx"
-!! input
+!! wikitext
 == Section One ==
 <pre>
 =======
@@ -14511,7 +14274,7 @@ noxml replace=2,"xxx"
 
 == Section Two ==
 stuff
-!! result
+!! html
 == Section One ==
 <pre>
 =======
@@ -14524,9 +14287,9 @@ xxx
 
 !! test
 Handling of &#x0A; in URLs
-!! input
+!! wikitext
 **irc://&#x0A;a
-!! result
+!! html
 <ul>
 <li><ul>
 <li><a rel="nofollow" class="external free" href="irc://%0Aa">irc://%0Aa</a>
@@ -14537,30 +14300,21 @@ Handling of &#x0A; in URLs
 
 !!end
 
-!! test
-5 quotes, code coverage +1 line (php)
-!! options
-php
-!! input
-'''''
-!! result
-!! end
 # The PHP parser strips the empty tags out for giggles; parsoid doesn't.
 !! test
-5 quotes, code coverage +1 line (parsoid)
-!! options
-parsoid
-!! input
+5 quotes, code coverage +1 line
+!! wikitext
 '''''
-!! result
+!! html/php
+!! html/parsoid
 <p><b><i></i></b></p>
 !! end
 
 !! test
 Special:Search page linking.
-!! input
+!! wikitext
 {{Special:search}}
-!! result
+!! html
 <p><a href="/wiki/Special:Search" title="Special:Search">Special:Search</a>
 </p>
 !! end
@@ -14569,7 +14323,7 @@ Special:Search page linking.
 Say the magic word
 !! options
 title=[[Parser test]]
-!! input
+!! wikitext
 * {{PAGENAME}}
 * {{PAGENAMEE}}
 * {{FULLPAGENAME}}
@@ -14592,7 +14346,7 @@ title=[[Parser test]]
 * {{SUBJECTSPACE}}
 * {{SUBJECTSPACEE}}
 * {{Dynamic|{{NUMBEROFUSERS}}|{{NUMBEROFPAGES}}|{{CURRENTVERSION}}|{{CONTENTLANGUAGE}}|{{DIRECTIONMARK}}|{{CURRENTTIMESTAMP}}|{{NUMBEROFARTICLES}}}}
-!! result
+!! html
 <ul>
 <li> Parser test
 </li>
@@ -14645,7 +14399,7 @@ title=[[Parser test]]
 
 !! test
 Gallery
-!! input
+!! wikitext
 <gallery>
 image1.png |
 image2.gif|||||
@@ -14656,7 +14410,7 @@ image4    |300px| centre
 [[x|xx]]]]
 * image6
 </gallery>
-!! result
+!! html
 <ul class="gallery mw-gallery-traditional">
                <li class="gallerybox" style="width: 155px"><div style="width: 155px">
                        <div class="thumb" style="height: 150px;">Image1.png</div>
@@ -14700,7 +14454,7 @@ image4    |300px| centre
 
 !! test
 Gallery (with options)
-!! input
+!! wikitext
 <gallery widths='70px' heights='40px' perrow='2' caption='Foo [[Main Page]]' >
 File:Nonexistant.jpg|caption
 File:Nonexistant.jpg
@@ -14708,7 +14462,7 @@ image:foobar.jpg|some '''caption''' [[Main Page]]
 image:foobar.jpg
 image:foobar.jpg|Blabla|alt=This is a foo-bar.|blabla.
 </gallery>
-!! result
+!! html
 <ul class="gallery mw-gallery-traditional" style="max-width: 226px;_width: 226px;">
        <li class='gallerycaption'>Foo <a href="/wiki/Main_Page" title="Main Page">Main Page</a></li>
                <li class="gallerybox" style="width: 105px"><div style="width: 105px">
@@ -14748,12 +14502,12 @@ image:foobar.jpg|Blabla|alt=This is a foo-bar.|blabla.
 
 !! test
 Gallery with wikitext inside caption
-!! input
+!! wikitext
 <gallery>
 File:foobar.jpg|[[File:foobar.jpg|20px|desc|alt=inneralt]]|alt=galleryalt
 File:foobar.jpg|{{Test|unamedParam|alt=param}}|alt=galleryalt
 </gallery>
-!! result
+!! html
 <ul class="gallery mw-gallery-traditional">
                <li class="gallerybox" style="width: 155px"><div style="width: 155px">
                        <div class="thumb" style="width: 150px;"><div style="margin:68px auto;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="galleryalt" src="http://example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" width="120" height="14" /></a></div></div>
@@ -14775,14 +14529,14 @@ File:foobar.jpg|{{Test|unamedParam|alt=param}}|alt=galleryalt
 
 !! test
 gallery (with showfilename option)
-!! input
+!! wikitext
 <gallery showfilename>
 File:Nonexistant.jpg|caption
 File:Nonexistant.jpg
 image:foobar.jpg|some '''caption''' [[Main Page]]
 File:Foobar.jpg
 </gallery>
-!! result
+!! html
 <ul class="gallery mw-gallery-traditional">
                <li class="gallerybox" style="width: 155px"><div style="width: 155px">
                        <div class="thumb" style="height: 150px;">Nonexistant.jpg</div>
@@ -14820,14 +14574,14 @@ some <b>caption</b> <a href="/wiki/Main_Page" title="Main Page">Main Page</a>
 
 !! test
 Gallery (with namespace-less filenames)
-!! input
+!! wikitext
 <gallery>
 File:Nonexistant.jpg
 Nonexistant.jpg
 image:foobar.jpg
 foobar.jpg
 </gallery>
-!! result
+!! html
 <ul class="gallery mw-gallery-traditional">
                <li class="gallerybox" style="width: 155px"><div style="width: 155px">
                        <div class="thumb" style="height: 150px;">Nonexistant.jpg</div>
@@ -14855,172 +14609,172 @@ foobar.jpg
 
 !! test
 HTML Hex character encoding (spells the word "JavaScript")
-!! input
+!! wikitext
 &#x4A;&#x061;&#x0076;&#x00061;&#x000053;&#x0000063;&#114;&#x0000069;&#00000112;&#x0000000074;
-!! result
+!! html
 <p>&#x4a;&#x61;&#x76;&#x61;&#x53;&#x63;&#114;&#x69;&#112;&#x74;
 </p>
 !! end
 
 !! test
 HTML Hex character encoding bogus encoding (bug 26437 regression check)
-!! input
+!! wikitext
 &#xsee;&#XSEE;
-!! result
+!! html
 <p>&amp;#xsee;&amp;#XSEE;
 </p>
 !! end
 
 !! test
 HTML Hex character encoding mixed case
-!! input
+!! wikitext
 &#xEE;&#Xee;
-!! result
+!! html
 <p>&#xee;&#xee;
 </p>
 !! end
 
 !! test
 __FORCETOC__ override
-!! input
+!! wikitext
 __NEWSECTIONLINK__
 __FORCETOC__
-!! result
+!! html
 <p><br />
 </p>
 !! end
 
 !! test
 ISBN code coverage
-!! input
+!! wikitext
 ISBN  978-0-1234-56&#x20;789
-!! result
+!! html
 <p><a href="/wiki/Special:BookSources/9780123456" class="internal mw-magiclink-isbn">ISBN 978-0-1234-56</a>&#x20;789
 </p>
 !! end
 
 !! test
 ISBN followed by 5 spaces
-!! input
+!! wikitext
 ISBN    
-!! result
+!! html
 <p>ISBN    
 </p>
 !! end
 
 !! test
 Double ISBN
-!! input
+!! wikitext
 ISBN ISBN 1234567890
-!! result
+!! html
 <p>ISBN <a href="/wiki/Special:BookSources/1234567890" class="internal mw-magiclink-isbn">ISBN 1234567890</a>
 </p>
 !! end
 
 !! test
 ISBN with an X
-!! input
+!! wikitext
 ISBN 3-462-04561-X
-!! result
+!! html
 <p><a href="/wiki/Special:BookSources/346204561X" class="internal mw-magiclink-isbn">ISBN 3-462-04561-X</a>
 </p>
 !! end
 
 !! test
 Bug 22905: <abbr> followed by ISBN followed by </a>
-!! input
+!! wikitext
 <abbr>(fr)</abbr> ISBN 2753300917 [http://www.example.com example.com]
-!! result
+!! html
 <p><abbr>(fr)</abbr> <a href="/wiki/Special:BookSources/2753300917" class="internal mw-magiclink-isbn">ISBN 2753300917</a> <a rel="nofollow" class="external text" href="http://www.example.com">example.com</a>
 </p>
 !! end
 
 !! test
 Double RFC
-!! input
+!! wikitext
 RFC RFC 1234
-!! result
+!! html
 <p>RFC <a class="external mw-magiclink-rfc" rel="nofollow" href="//tools.ietf.org/html/rfc1234">RFC 1234</a>
 </p>
 !! end
 
 !! test
 Double RFC with a wiki link
-!! input
+!! wikitext
 RFC [[RFC 1234]]
-!! result
+!! html
 <p>RFC <a href="/index.php?title=RFC_1234&amp;action=edit&amp;redlink=1" class="new" title="RFC 1234 (page does not exist)">RFC 1234</a>
 </p>
 !! end
 
 !! test
 RFC code coverage
-!! input
+!! wikitext
 RFC   983&#x20;987
-!! result
+!! html
 <p><a class="external mw-magiclink-rfc" rel="nofollow" href="//tools.ietf.org/html/rfc983">RFC 983</a>&#x20;987
 </p>
 !! end
 
 !! test
 Centre-aligned image
-!! input
+!! wikitext
 [[Image:foobar.jpg|centre]]
-!! result
+!! html
 <div class="center"><div class="floatnone"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a></div></div>
 
 !!end
 
 !! test
 None-aligned image
-!! input
+!! wikitext
 [[Image:foobar.jpg|none]]
-!! result
+!! html
 <div class="floatnone"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a></div>
 
 !!end
 
 !! test
 Width + Height sized image (using px) (height is ignored)
-!! input
+!! wikitext
 [[Image:foobar.jpg|640x480px]]
-!! result
+!! html
 <p><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/thumb/3/3a/Foobar.jpg/640px-Foobar.jpg" width="640" height="73" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/960px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/1280px-Foobar.jpg 2x" /></a>
 </p>
 !!end
 
 !! test
 Width-sized image (using px, no following whitespace)
-!! input
+!! wikitext
 [[Image:foobar.jpg|640px]]
-!! result
+!! html
 <p><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/thumb/3/3a/Foobar.jpg/640px-Foobar.jpg" width="640" height="73" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/960px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/1280px-Foobar.jpg 2x" /></a>
 </p>
 !!end
 
 !! test
 Width-sized image (using px, with following whitespace - test regression from r39467)
-!! input
+!! wikitext
 [[Image:foobar.jpg|640px ]]
-!! result
+!! html
 <p><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/thumb/3/3a/Foobar.jpg/640px-Foobar.jpg" width="640" height="73" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/960px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/1280px-Foobar.jpg 2x" /></a>
 </p>
 !!end
 
 !! test
 Width-sized image (using px, with preceding whitespace - test regression from r39467)
-!! input
+!! wikitext
 [[Image:foobar.jpg| 640px]]
-!! result
+!! html
 <p><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/thumb/3/3a/Foobar.jpg/640px-Foobar.jpg" width="640" height="73" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/960px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/1280px-Foobar.jpg 2x" /></a>
 </p>
 !!end
 
 !! test
 Another italics / bold test
-!! input
+!! wikitext
  ''' ''x'
-!! result
+!! html
 <pre>'<i> </i>x'
 </pre>
 !!end
@@ -15032,9 +14786,9 @@ Another italics / bold test
 dt/dd/dl test
 !! options
 disabled
-!! input
+!! wikitext
 :;;;::
-!! result
+!! html
 <dl>
 <dd><dl>
 <dt><dl>
@@ -15061,18 +14815,18 @@ disabled
 # Images with the "|" character in external URLs in comment tags; Eats half the comment, leaves unmatched "</a>" tag.
 !! test
 Images with the "|" character in the comment
-!! input
+!! wikitext
 [[image:Foobar.jpg|thumb|An [http://test/?param1=|left|&param2=|x external] URL]]
-!! result
+!! html
 <div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" width="180" height="20" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/270px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/360px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div>An <a rel="nofollow" class="external text" href="http://test/?param1=%7Cleft%7C&amp;param2=%7Cx">external</a> URL</div></div></div>
 
 !!end
 
 !! test
 [Before] HTML without raw HTML enabled ($wgRawHtml==false)
-!! input
+!! wikitext
 <html><script>alert(1);</script></html>
-!! result
+!! html
 <p>&lt;html&gt;&lt;script&gt;alert(1);&lt;/script&gt;&lt;/html&gt;
 </p>
 !! end
@@ -15081,9 +14835,9 @@ Images with the "|" character in the comment
 HTML with raw HTML ($wgRawHtml==true)
 !! options
 wgRawHtml=1
-!! input
+!! wikitext
 <html><script>alert(1);</script></html>
-!! result
+!! html
 <p><script>alert(1);</script>
 </p>
 !! end
@@ -15092,9 +14846,9 @@ wgRawHtml=1
 Parents of subpages, one level up
 !! options
 subpage title=[[Subpage test/L1/L2/L3]]
-!! input
+!! wikitext
 [[../|L2]]
-!! result
+!! html
 <p><a href="/index.php?title=Subpage_test/L1/L2&amp;action=edit&amp;redlink=1" class="new" title="Subpage test/L1/L2 (page does not exist)">L2</a>
 </p>
 !! end
@@ -15104,9 +14858,9 @@ subpage title=[[Subpage test/L1/L2/L3]]
 Parents of subpages, one level up, not named
 !! options
 subpage title=[[Subpage test/L1/L2/L3]]
-!! input
+!! wikitext
 [[../]]
-!! result
+!! html
 <p><a href="/index.php?title=Subpage_test/L1/L2&amp;action=edit&amp;redlink=1" class="new" title="Subpage test/L1/L2 (page does not exist)">Subpage test/L1/L2</a>
 </p>
 !! end
@@ -15117,11 +14871,11 @@ subpage title=[[Subpage test/L1/L2/L3]]
 Parents of subpages, two levels up
 !! options
 subpage title=[[Subpage test/L1/L2/L3]]
-!! input
+!! wikitext
 [[../../|L1]]2
 
 [[../../|L1]]l
-!! result
+!! html
 <p><a href="/index.php?title=Subpage_test/L1&amp;action=edit&amp;redlink=1" class="new" title="Subpage test/L1 (page does not exist)">L1</a>2
 </p><p><a href="/index.php?title=Subpage_test/L1&amp;action=edit&amp;redlink=1" class="new" title="Subpage test/L1 (page does not exist)">L1l</a>
 </p>
@@ -15131,9 +14885,9 @@ subpage title=[[Subpage test/L1/L2/L3]]
 Parents of subpages, two levels up, without trailing slash or name.
 !! options
 subpage title=[[Subpage test/L1/L2/L3]]
-!! input
+!! wikitext
 [[../..]]
-!! result
+!! html
 <p>[[../..]]
 </p>
 !! end
@@ -15142,9 +14896,9 @@ subpage title=[[Subpage test/L1/L2/L3]]
 Parents of subpages, two levels up, with lots of extra trailing slashes.
 !! options
 subpage title=[[Subpage test/L1/L2/L3]]
-!! input
+!! wikitext
 [[../../////]]
-!! result
+!! html
 <p><a href="/index.php?title=Subpage_test/L1////&amp;action=edit&amp;redlink=1" class="new" title="Subpage test/L1//// (page does not exist)">///</a>
 </p>
 !! end
@@ -15159,9 +14913,9 @@ Sibling article
 Transclusion of a sibling page (one level up)
 !! options
 subpage title=[[Subpage test/L1/L2/L3]]
-!! input
+!! wikitext
 {{../L3Sibling}}
-!! result
+!! html
 <p>Sibling article
 </p>
 !! end
@@ -15170,9 +14924,9 @@ subpage title=[[Subpage test/L1/L2/L3]]
 Transclusion of a child page
 !! options
 subpage title=[[Subpage test/L1/L2]]
-!! input
+!! wikitext
 {{/L3Sibling}}
-!! result
+!! html
 <p>Sibling article
 </p>
 !! end
@@ -15181,20 +14935,20 @@ subpage title=[[Subpage test/L1/L2]]
 Non-transclusion because of too many up levels
 !! options
 subpage title=[[Subpage test/L1/L2/L3]]
-!! input
+!! wikitext
 {{../../../../More than parent}}
-!! result
+!! html
 <p>{{../../../../More than parent}}
 </p>
 !! end
 
 !! test
 Definition list code coverage
-!! input
+!! wikitext
 ; title   : def
 ; title : def
 ;title: def
-!! result
+!! html
 <dl>
 <dt> title  &#160;</dt>
 <dd> def
@@ -15211,27 +14965,27 @@ Definition list code coverage
 
 !! test
 Don't fall for the self-closing div
-!! input
+!! wikitext
 <div>hello world</div/>
-!! result
+!! html
 <div>hello world</div>
 
 !! end
 
 !! test
 MSGNW magic word
-!! input
+!! wikitext
 {{MSGNW:msg}}
-!! result
+!! html
 <p>&#91;&#91;:Template:Msg&#93;&#93;
 </p>
 !! end
 
 !! test
 RAW magic word
-!! input
+!! wikitext
 {{RAW:QUERTY}}
-!! result
+!! html
 <p><a href="/index.php?title=Template:QUERTY&amp;action=edit&amp;redlink=1" class="new" title="Template:QUERTY (page does not exist)">Template:QUERTY</a>
 </p>
 !! end
@@ -15239,19 +14993,19 @@ RAW magic word
 # This isn't needed for XHTML conformance, but would be handy as a fallback security measure
 !! test
 Always escape literal '>' in output, not just after '<'
-!! input
+!! wikitext
 ><>
-!! result
+!! html
 <p>&gt;&lt;&gt;
 </p>
 !! end
 
 !! test
 Template caching
-!! input
+!! wikitext
 {{Test}}
 {{Test}}
-!! result
+!! html
 <p>This is a test template
 This is a test template
 </p>
@@ -15266,9 +15020,9 @@ MediaWiki:Fake
 
 !! test
 Inclusion of !userCanEdit() content
-!! input
+!! wikitext
 {{MediaWiki:Fake}}
-!! result
+!! html
 <h2><span class="mw-headline" id="header">header</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=MediaWiki:Fake&amp;action=edit&amp;section=T-1" title="MediaWiki:Fake">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
 
 !! end
@@ -15276,14 +15030,14 @@ Inclusion of !userCanEdit() content
 
 !! test
 Out-of-order TOC heading levels
-!! input
+!! wikitext
 ==2==
 ======6======
 ===3===
 =1=
 =====5=====
 ==2==
-!! result
+!! html
 <div id="toc" class="toc"><div id="toctitle"><h2>Contents</h2></div>
 <ul>
 <li class="toclevel-1 tocsection-1"><a href="#2"><span class="tocnumber">1</span> <span class="toctext">2</span></a>
@@ -15313,9 +15067,9 @@ Out-of-order TOC heading levels
 
 !! test
 ISBN with a dummy number
-!! input
+!! wikitext
 ISBN ---
-!! result
+!! html
 <p>ISBN ---
 </p>
 !! end
@@ -15323,9 +15077,9 @@ ISBN ---
 
 !! test
 ISBN with space-delimited number
-!! input
+!! wikitext
 ISBN 92 9017 032 8
-!! result
+!! html
 <p><a href="/wiki/Special:BookSources/9290170328" class="internal mw-magiclink-isbn">ISBN 92 9017 032 8</a>
 </p>
 !! end
@@ -15333,9 +15087,9 @@ ISBN 92 9017 032 8
 
 !! test
 ISBN with multiple spaces, no number
-!! input
+!! wikitext
 ISBN  foo
-!! result
+!! html
 <p>ISBN  foo
 </p>
 !! end
@@ -15343,13 +15097,13 @@ ISBN  foo
 
 !! test
 ISBN length
-!! input
+!! wikitext
 ISBN 123456789
 
 ISBN 1234567890
 
 ISBN 12345678901
-!! result
+!! html
 <p>ISBN 123456789
 </p><p><a href="/wiki/Special:BookSources/1234567890" class="internal mw-magiclink-isbn">ISBN 1234567890</a>
 </p><p>ISBN 12345678901
@@ -15359,11 +15113,11 @@ ISBN 12345678901
 
 !! test
 ISBN with trailing year (bug 8110)
-!! input
+!! wikitext
 ISBN 1-234-56789-0 - 2006
 
 ISBN 1 234 56789 0 - 2006
-!! result
+!! html
 <p><a href="/wiki/Special:BookSources/1234567890" class="internal mw-magiclink-isbn">ISBN 1-234-56789-0</a> - 2006
 </p><p><a href="/wiki/Special:BookSources/1234567890" class="internal mw-magiclink-isbn">ISBN 1 234 56789 0</a> - 2006
 </p>
@@ -15372,47 +15126,47 @@ ISBN 1 234 56789 0 - 2006
 
 !! test
 anchorencode
-!! input
+!! wikitext
 {{anchorencode:foo bar©#%n}}
-!! result
+!! html
 <p>foo_bar.C2.A9.23.25n
 </p>
 !! end
 
 !! test
 anchorencode trims spaces
-!! input
+!! wikitext
 {{anchorencode: __pretty__please__}}
-!! result
+!! html
 <p>pretty_please
 </p>
 !! end
 
 !! test
 anchorencode deals with links
-!! input
+!! wikitext
 {{anchorencode: [[hello|world]] [[hi]]}}
-!! result
+!! html
 <p>world_hi
 </p>
 !! end
 
 !! test
 anchorencode deals with templates
-!! input
+!! wikitext
 {{anchorencode: {{Foo}} }}
-!! result
+!! html
 <p>FOO
 </p>
 !! end
 
 !! test
 anchorencode encodes like the TOC generator: (bug 18431)
-!! input
+!! wikitext
 === _ +:.3A%3A&&amp;]] ===
 {{anchorencode: _ +:.3A%3A&&amp;]] }}
 __NOEDITSECTION__
-!! result
+!! html
 <h3><span class="mw-headline" id=".2B:.3A.253A.26.26.5D.5D">_ +:.3A%3A&amp;&amp;]]</span></h3>
 <p>.2B:.3A.253A.26.26.5D.5D
 </p>
@@ -15420,7 +15174,7 @@ __NOEDITSECTION__
 
 !! test
 Bug 6200: blockquotes and paragraph formatting
-!! input
+!! wikitext
 <blockquote>
 foo
 </blockquote>
@@ -15428,7 +15182,7 @@ foo
 bar
 
  baz
-!! result
+!! html
 <blockquote>
 <p>foo
 </p>
@@ -15441,7 +15195,7 @@ bar
 
 !! test
 Bug 8293: Use of center tag ruins paragraph formatting
-!! input
+!! wikitext
 <center>
 foo
 </center>
@@ -15449,7 +15203,7 @@ foo
 bar
 
  baz
-!! result
+!! html
 <center>
 <p>foo
 </p>
@@ -15461,24 +15215,14 @@ bar
 !! end
 
 !!test
-Parsing of overlapping (improperly nested) inline html tags (PHP parser)
-!!options
-php
-!!input
+Parsing of overlapping (improperly nested) inline html tags
+!! wikitext
 <span><s>x</span></s>
-!!result
+!! html/php
 <p><span><s>x&lt;/span&gt;</s></span>
 </p>
-!!end
-
-!!test
-Parsing of overlapping (improperly nested) inline html tags (Parsoid)
-!!options
-parsoid
-!!input
-<span><s>x</span></s>
-!!result
-<p><span><s>x</s></span><s></s>
+!! html/parsoid
+<p><span><s>x</s></span>
 </p>
 !!end
 
@@ -15489,9 +15233,9 @@ parsoid
 Self-link in language variants
 !! options
 title=[[Dunav]] language=sr
-!! input
+!! wikitext
 Both [[Dunav]] and [[Дунав]] are names for this river.
-!! result
+!! html
 <p>Both <strong class="selflink">Dunav</strong> and <strong class="selflink">Дунав</strong> are names for this river.
 </p>
 !!end
@@ -15506,9 +15250,9 @@ content
 Link to another existing title shouldn't be parsed as self-link even if it's a variant of this title
 !! options
 title=[[Duna]] language=sr
-!! input
+!! wikitext
 [[Дуна]] is not a self-link while [[Duna]] and [[Dуна]] are still self-links.
-!! result
+!! html
 <p><a href="/wiki/%D0%94%D1%83%D0%BD%D0%B0" title="Дуна">Дуна</a> is not a self-link while <strong class="selflink">Duna</strong> and <strong class="selflink">Dуна</strong> are still self-links.
 </p>
 !! end
@@ -15517,9 +15261,9 @@ title=[[Duna]] language=sr
 Link to a section of a variant of this title shouldn't be parsed as self-link
 !! options
 title=[[Duna]] language=sr
-!! input
+!! wikitext
 [[Dуна]] is a self-link while [[Dunа#Foo]] and [[Dуна#Foo]] are not self-links.
-!! result
+!! html
 <p><strong class="selflink">Dуна</strong> is a self-link while <a href="/wiki/%D0%94%D1%83%D0%BD%D0%B0" title="Дуна">Dunа#Foo</a> and <a href="/wiki/%D0%94%D1%83%D0%BD%D0%B0" title="Дуна">Dуна#Foo</a> are not self-links.
 </p>
 !! end
@@ -15528,9 +15272,9 @@ title=[[Duna]] language=sr
 Link to pages in language variants
 !! options
 language=sr
-!! input
+!! wikitext
 Main Page can be written as [[Маин Паге]]
-!! result
+!! html
 <p>Main Page can be written as <a href="/wiki/Main_Page" title="Main Page">Маин Паге</a>
 </p>
 !!end
@@ -15540,9 +15284,9 @@ Main Page can be written as [[Маин Паге]]
 Multiple links to pages in language variants
 !! options
 language=sr
-!! input
+!! wikitext
 [[Main Page]] can be written as [[Маин Паге]] same as [[Маин Паге]].
-!! result
+!! html
 <p><a href="/wiki/Main_Page" title="Main Page">Main Page</a> can be written as <a href="/wiki/Main_Page" title="Main Page">Маин Паге</a> same as <a href="/wiki/Main_Page" title="Main Page">Маин Паге</a>.
 </p>
 !!end
@@ -15552,9 +15296,9 @@ language=sr
 Simple template in language variants
 !! options
 language=sr
-!! input
+!! wikitext
 {{тест}}
-!! result
+!! html
 <p>This is a test template
 </p>
 !! end
@@ -15564,9 +15308,9 @@ language=sr
 Template with explicit namespace in language variants
 !! options
 language=sr
-!! input
+!! wikitext
 {{Template:тест}}
-!! result
+!! html
 <p>This is a test template
 </p>
 !! end
@@ -15576,9 +15320,9 @@ language=sr
 Basic test for template parameter in language variants
 !! options
 language=sr
-!! input
+!! wikitext
 {{парамтест|param=foo}}
-!! result
+!! html
 <p>This is a test template with parameter foo
 </p>
 !! end
@@ -15588,9 +15332,9 @@ language=sr
 Simple category in language variants
 !! options
 language=sr cat
-!! input
+!! wikitext
 [[Category:МедиаWики Усер'с Гуиде]]
-!! result
+!! html
 <a href="/wiki/%D0%9A%D0%B0%D1%82%D0%B5%D0%B3%D0%BE%D1%80%D0%B8%D1%98%D0%B0:MediaWiki_User%27s_Guide" title="Категорија:MediaWiki User's Guide">MediaWiki User's Guide</a>
 !! end
 
@@ -15611,9 +15355,9 @@ blah
 Don't convert blue categorylinks to another variant (bug 33210)
 !! options
 language=zh cat
-!! input
+!! wikitext
 [[A]][[Category:分类]]
-!! result
+!! html
 <a href="/wiki/Category:%E5%88%86%E7%B1%BB" title="Category:分类">分类</a>
 !! end
 
@@ -15622,9 +15366,9 @@ language=zh cat
 Stripping -{}- tags (language variants)
 !! options
 language=sr
-!! input
+!! wikitext
 Latin proverb: -{Ne nuntium necare}-
-!! result
+!! html
 <p>Latin proverb: Ne nuntium necare
 </p>
 !! end
@@ -15634,9 +15378,9 @@ Latin proverb: -{Ne nuntium necare}-
 Prevent conversion with -{}- tags (language variants)
 !! options
 language=sr variant=sr-ec
-!! input
+!! wikitext
 Latinski: -{Ne nuntium necare}-
-!! result
+!! html
 <p>Латински: Ne nuntium necare
 </p>
 !! end
@@ -15646,9 +15390,9 @@ Latinski: -{Ne nuntium necare}-
 Prevent conversion of text with -{}- tags (language variants)
 !! options
 language=sr variant=sr-ec
-!! input
+!! wikitext
 Latinski: -{Ne nuntium necare}-
-!! result
+!! html
 <p>Латински: Ne nuntium necare
 </p>
 !! end
@@ -15658,9 +15402,9 @@ Latinski: -{Ne nuntium necare}-
 Prevent conversion of links with -{}- tags (language variants)
 !! options
 language=sr variant=sr-ec
-!! input
+!! wikitext
 -{[[Main Page]]}-
-!! result
+!! html
 <p><a href="/wiki/Main_Page" title="Main Page">Main Page</a>
 </p>
 !! end
@@ -15670,9 +15414,9 @@ language=sr variant=sr-ec
 -{}- tags within headlines (within html for parserConvert())
 !! options
 language=sr variant=sr-ec
-!! input
+!! wikitext
 == -{Naslov}- ==
-!! result
+!! html
 <h2><span class="mw-headline" id="-.7BNaslov.7D-">Naslov</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=1" title="Уредите одељак „Naslov“">уреди</a><span class="mw-editsection-bracket">]</span></span></h2>
 
 !! end
@@ -15682,9 +15426,9 @@ language=sr variant=sr-ec
 Explicit definition of language variant alternatives
 !! options
 language=zh variant=zh-tw
-!! input
+!! wikitext
 -{zh:China;zh-tw:Taiwan}-, not China
-!! result
+!! html
 <p>Taiwan, not China
 </p>
 !! end
@@ -15694,10 +15438,10 @@ language=zh variant=zh-tw
 Conversion around HTML tags
 !! options
 language=sr variant=sr-ec
-!! input
+!! wikitext
 -{H|span=>sr-ec:script;title=>sr-ec:src;}-
 <span title="La-{sr-el:L;sr-ec:C;}-tin">ski</span>
-!! result
+!! html
 <p>
 <span title="ЛаCтин">ски</span>
 </p>
@@ -15708,12 +15452,12 @@ language=sr variant=sr-ec
 Explicit session-wise language variant mapping (A flag and - flag)
 !! options
 language=zh variant=zh-tw
-!! input
+!! wikitext
 Taiwan is not China.
 But -{A|zh:China;zh-tw:Taiwan}- is China,
 (This-{-|zh:China;zh-tw:Taiwan}- should be stripped!)
 and -{China}- is China.
-!! result
+!! html
 <p>Taiwan is not China.
 But Taiwan is Taiwan,
 (This should be stripped!)
@@ -15725,10 +15469,10 @@ and China is China.
 Explicit session-wise language variant mapping (H flag for hide)
 !! options
 language=zh variant=zh-tw
-!! input
+!! wikitext
 (This-{H|zh:China;zh-tw:Taiwan}- should be stripped!)
 Taiwan is China.
-!! result
+!! html
 <p>(This should be stripped!)
 Taiwan is Taiwan.
 </p>
@@ -15738,9 +15482,9 @@ Taiwan is Taiwan.
 Adding explicit conversion rule for title (T flag)
 !! options
 language=zh variant=zh-tw showtitle
-!! input
+!! wikitext
 Should be stripped-{T|zh:China;zh-tw:Taiwan}-!
-!! result
+!! html
 Taiwan
 <p>Should be stripped!
 </p>
@@ -15750,9 +15494,9 @@ Taiwan
 Testing that changing the language variant here in the tests actually works
 !! options
 language=zh variant=zh showtitle
-!! input
+!! wikitext
 Should be stripped-{T|zh:China;zh-tw:Taiwan}-!
-!! result
+!! html
 China
 <p>Should be stripped!
 </p>
@@ -15762,10 +15506,10 @@ China
 Recursive conversion of alt and title attrs shouldn't clear converter state
 !! options
 language=zh variant=zh-cn showtitle
-!! input
+!! wikitext
 -{H|zh-cn:Exclamation;zh-tw:exclamation;}-
 Should be stripped-{T|zh-cn:China;zh-tw:Taiwan}-<span title="exclamation">!</span>
-!! result
+!! html
 China
 <p>
 Should be stripped<span title="Exclamation">!</span>
@@ -15776,10 +15520,10 @@ Should be stripped<span title="Exclamation">!</span>
 Bug 24072: more test on conversion rule for title
 !! options
 language=zh variant=zh-tw showtitle
-!! input
+!! wikitext
 This should be stripped-{T|zh:China;zh-tw:Taiwan}-!
 This won't take interferes with the title rule-{H|zh:Beijing;zh-tw:Taipei}-.
-!! result
+!! html
 Taiwan
 <p>This should be stripped!
 This won't take interferes with the title rule.
@@ -15790,9 +15534,9 @@ This won't take interferes with the title rule.
 Partly disable title conversion if variant == main language code
 !! options
 language=zh variant=zh title=[[ZH]] showtitle
-!! input
+!! wikitext
 -{T|zh-cn:CN;zh-tw:TW}-
-!! result
+!! html
 ZH
 <p>
 </p>
@@ -15802,9 +15546,9 @@ ZH
 Partly disable title conversion if variant == main language code, more
 !! options
 language=zh variant=zh title=[[ZH]] showtitle
-!! input
+!! wikitext
 -{T|TW}-
-!! result
+!! html
 ZH
 <p>
 </p>
@@ -15814,9 +15558,9 @@ ZH
 Raw output of variant escape tags (R flag)
 !! options
 language=zh variant=zh-tw
-!! input
+!! wikitext
 Raw: -{R|zh:China;zh-tw:Taiwan}-
-!! result
+!! html
 <p>Raw: zh:China;zh-tw:Taiwan
 </p>
 !! end
@@ -15825,9 +15569,9 @@ Raw: -{R|zh:China;zh-tw:Taiwan}-
 Nested using of manual convert syntax
 !! options
 language=zh variant=zh-hk
-!! input
+!! wikitext
 Nested: -{zh-hans:Hi -{zh-cn:China;zh-sg:Singapore;}-;zh-hant:Hello -{zh-tw:Taiwan;zh-hk:H-{ong}- K-{}-ong;}-;}-!
-!! result
+!! html
 <p>Nested: Hello Hong Kong!
 </p>
 !! end
@@ -15836,7 +15580,7 @@ Nested: -{zh-hans:Hi -{zh-cn:China;zh-sg:Singapore;}-;zh-hant:Hello -{zh-tw:Taiw
 Proper conversion of text in external links
 !! options
 language=sr variant=sr-ec
-!! input
+!! wikitext
 http://www.google.com
 gopher://www.google.com
 [http://www.google.com http://www.google.com]
@@ -15844,7 +15588,7 @@ gopher://www.google.com
 [https://www.google.com irc://www.google.com]
 [ftp://www.google.com www.google.com/ftp://dir]
 [//www.google.com www.google.com]
-!! result
+!! html
 <p><a rel="nofollow" class="external free" href="http://www.google.com">http://www.google.com</a>
 <a rel="nofollow" class="external free" href="gopher://www.google.com">gopher://www.google.com</a>
 <a rel="nofollow" class="external free" href="http://www.google.com">http://www.google.com</a>
@@ -15859,9 +15603,9 @@ gopher://www.google.com
 Do not convert roman numbers to language variants
 !! options
 language=sr variant=sr-ec
-!! input
+!! wikitext
 Fridrih IV je car.
-!! result
+!! html
 <p>Фридрих IV је цар.
 </p>
 !! end
@@ -15870,9 +15614,9 @@ Fridrih IV je car.
 Unclosed language converter markup "-{"
 !! options
 language=sr
-!! input
+!! wikitext
 -{T|hello
-!! result
+!! html
 <p>-{T|hello
 </p>
 !! end
@@ -15881,9 +15625,9 @@ language=sr
 Don't convert raw rule "-{R|=&gt;}-" to "=>"
 !! options
 language=sr
-!! input
+!! wikitext
 -{R|=&gt;}-
-!! result
+!! html
 <p>=&gt;
 </p>
 !!end
@@ -15892,9 +15636,9 @@ language=sr
 Don't break link parsing if language converter markup is in the caption.
 !! options
 language=sr variant=sr-ec
-!! input
+!! wikitext
 [[Main Page|-{R|main page}-]]
-!! result
+!! html
 <p><a href="/wiki/Main_Page" title="Маин Паге">main page</a>
 </p>
 !! end
@@ -15905,9 +15649,9 @@ Don't break image parsing if language converter markup is in the caption.
 !! options
 language=sr
 disabled
-!! input
+!! wikitext
 [[File:Foobar.jpg|-{R|caption}-]]
-!! result
+!! html
 <p><a href="/wiki/File:Foobar.jpg" class="image" title="caption"><img alt="caption" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a>
 </p>
 !! end
@@ -15918,9 +15662,9 @@ Don't break list handling if language converter markup is in the item.
 !! options
 language=zh variant=zh-cn
 disabled
-!! input
+!! wikitext
 ;-{zh-cn:AAA;zh-tw:BBB}-
-!! result
+!! html
 <dl><dt>AAA
 </dt></dl>
 
@@ -15932,12 +15676,12 @@ Don't break table handling if language converter markup is in the cell.
 !! options
 language=sr variant=sr-ec
 disabled
-!! input
+!! wikitext
 {|
 |-
 | -{R|B}-
 |}
-!! result
+!! html
 <table>
 
 <tr>
@@ -15948,9 +15692,9 @@ disabled
 
 !! test
 Bug 529: Uncovered bullet
-!! input
+!! wikitext
 * Foo {{bullet}}
-!! result
+!! html
 <ul>
 <li> Foo 
 </li>
@@ -15968,9 +15712,9 @@ Bug 529: Uncovered bullet
 # the expected output and your parser's output.
 !! test
 Bug 529: Uncovered bullet leaving empty list, normally removed by tidy
-!! input
+!! wikitext
 ******* Foo {{bullet}}
-!! result
+!! html
 <ul>
 <li><ul>
 <li><ul>
@@ -16000,12 +15744,12 @@ Bug 529: Uncovered bullet leaving empty list, normally removed by tidy
 
 !! test
 Bug 529: Uncovered table already at line-start
-!! input
+!! wikitext
 x
 
 {{table}}
 y
-!! result
+!! html
 <p>x
 </p>
 <table>
 
 !! test
 Bug 529: Uncovered bullet in parser function result
-!! input
+!! wikitext
 * Foo {{lc:{{bullet}} }}
-!! result
+!! html
 <ul>
 <li> Foo 
 </li>
@@ -16037,18 +15781,18 @@ Bug 529: Uncovered bullet in parser function result
 
 !! test
 Bug 5678: Double-parsed template argument
-!! input
+!! wikitext
 {{lc:{{{1}}}|hello}}
-!! result
+!! html
 <p>{{{1}}}
 </p>
 !! end
 
 !! test
 Bug 5678: Double-parsed template invocation
-!! input
+!! wikitext
 {{lc:{{paramtest {{!}} param = hello }} }}
-!! result
+!! html
 <p>{{paramtest | param = hello }}
 </p>
 !! end
@@ -16058,7 +15802,7 @@ Case insensitivity of parser functions for non-ASCII characters (bug 8143)
 !! options
 language=cs
 title=[[Main Page]]
-!! input
+!! wikitext
 {{PRVNÍVELKÉ:ěščř}}
 {{prvnívelké:ěščř}}
 {{PRVNÍMALÉ:ěščř}}
@@ -16067,7 +15811,7 @@ title=[[Main Page]]
 {{malá:ěščř}}
 {{VELKÁ:ěščř}}
 {{velká:ěščř}}
-!! result
+!! html
 <p>Ěščř
 Ěščř
 ěščř
@@ -16081,10 +15825,10 @@ title=[[Main Page]]
 
 !! test
 Morwen/13: Unclosed link followed by heading
-!! input
+!! wikitext
 [[link
 ==heading==
-!! result
+!! html
 <p>[[link
 </p>
 <h2><span class="mw-headline" id="heading">heading</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=1" title="Edit section: heading">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
@@ -16093,10 +15837,10 @@ Morwen/13: Unclosed link followed by heading
 
 !! test
 HHP2.1: Heuristics for headings in preprocessor parenthetical structures
-!! input
+!! wikitext
 {{foo|
 =heading=
-!! result
+!! html
 <p>{{foo|
 </p>
 <h1><span class="mw-headline" id="heading">heading</span></h1>
@@ -16105,10 +15849,10 @@ HHP2.1: Heuristics for headings in preprocessor parenthetical structures
 
 !! test
 HHP2.2: Heuristics for headings in preprocessor parenthetical structures
-!! input
+!! wikitext
 {{foo|
 ==heading==
-!! result
+!! html
 <p>{{foo|
 </p>
 <h2><span class="mw-headline" id="heading">heading</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=1" title="Edit section: heading">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
@@ -16119,19 +15863,19 @@ HHP2.2: Heuristics for headings in preprocessor parenthetical structures
 Tildes in comments
 !! options
 pst
-!! input
+!! wikitext
 <!-- ~~~~ -->
-!! result
+!! html
 <!-- ~~~~ -->
 !! end
 
 !! test
 Paragraphs inside divs (no extra line breaks)
-!! input
+!! wikitext
 <div>Line one
 
 Line two</div>
-!! result
+!! html
 <div>Line one
 Line two</div>
 
@@ -16139,12 +15883,12 @@ Line two</div>
 
 !! test
 Paragraphs inside divs (extra line break on open)
-!! input
+!! wikitext
 <div>
 Line one
 
 Line two</div>
-!! result
+!! html
 <div>
 <p>Line one
 </p>
@@ -16154,12 +15898,12 @@ Line two</div>
 
 !! test
 Paragraphs inside divs (extra line break on close)
-!! input
+!! wikitext
 <div>Line one
 
 Line two
 </div>
-!! result
+!! html
 <div>Line one
 <p>Line two
 </p>
@@ -16169,13 +15913,13 @@ Line two
 
 !! test
 Paragraphs inside divs (extra line break on open and close)
-!! input
+!! wikitext
 <div>
 Line one
 
 Line two
 </div>
-!! result
+!! html
 <div>
 <p>Line one
 </p><p>Line two
@@ -16188,10 +15932,10 @@ Line two
 Nesting tags, paragraphs on lines which begin with <div>
 !! options
 disabled
-!! input
+!! wikitext
 <div></div><strong>A
 B</strong>
-!! result
+!! html
 <div></div>
 <p><strong>A
 B</strong>
@@ -16201,11 +15945,11 @@ B</strong>
 # Bug 6200: <blockquote> should behave like <div> with respect to line breaks
 !! test
 Bug 6200: paragraphs inside blockquotes (no extra line breaks)
-!! input
+!! wikitext
 <blockquote>Line one
 
 Line two</blockquote>
-!! result
+!! html
 <blockquote>Line one
 Line two</blockquote>
 
@@ -16213,12 +15957,12 @@ Line two</blockquote>
 
 !! test
 Bug 6200: paragraphs inside blockquotes (extra line break on open)
-!! input
+!! wikitext
 <blockquote>
 Line one
 
 Line two</blockquote>
-!! result
+!! html
 <blockquote>
 <p>Line one
 </p>
@@ -16228,12 +15972,12 @@ Line two</blockquote>
 
 !! test
 Bug 6200: paragraphs inside blockquotes (extra line break on close)
-!! input
+!! wikitext
 <blockquote>Line one
 
 Line two
 </blockquote>
-!! result
+!! html
 <blockquote>Line one
 <p>Line two
 </p>
@@ -16243,13 +15987,13 @@ Line two
 
 !! test
 Bug 6200: paragraphs inside blockquotes (extra line break on open and close)
-!! input
+!! wikitext
 <blockquote>
 Line one
 
 Line two
 </blockquote>
-!! result
+!! html
 <blockquote>
 <p>Line one
 </p><p>Line two
@@ -16260,11 +16004,11 @@ Line two
 
 !! test
 Paragraphs inside blockquotes/divs (no extra line breaks)
-!! input
+!! wikitext
 <blockquote><div>Line one
 
 Line two</div></blockquote>
-!! result
+!! html
 <blockquote><div>Line one
 Line two</div></blockquote>
 
@@ -16272,12 +16016,12 @@ Line two</div></blockquote>
 
 !! test
 Paragraphs inside blockquotes/divs (extra line break on open)
-!! input
+!! wikitext
 <blockquote><div>
 Line one
 
 Line two</div></blockquote>
-!! result
+!! html
 <blockquote><div>
 <p>Line one
 </p>
@@ -16287,12 +16031,12 @@ Line two</div></blockquote>
 
 !! test
 Paragraphs inside blockquotes/divs (extra line break on close)
-!! input
+!! wikitext
 <blockquote><div>Line one
 
 Line two
 </div></blockquote>
-!! result
+!! html
 <blockquote><div>Line one
 <p>Line two
 </p>
@@ -16302,13 +16046,13 @@ Line two
 
 !! test
 Paragraphs inside blockquotes/divs (extra line break on open and close)
-!! input
+!! wikitext
 <blockquote><div>
 Line one
 
 Line two
 </div></blockquote>
-!! result
+!! html
 <blockquote><div>
 <p>Line one
 </p><p>Line two
@@ -16321,11 +16065,11 @@ Line two
 Interwiki links trounced by replaceExternalLinks after early LinkHolderArray expansion
 !! options
 wgLinkHolderBatchSize=0
-!! input
+!! wikitext
 [[meatball:1]]
 [[meatball:2]]
 [[meatball:3]]
-!! result
+!! html
 <p><a href="http://www.usemod.com/cgi-bin/mb.pl?1" class="extiw" title="meatball:1">meatball:1</a>
 <a href="http://www.usemod.com/cgi-bin/mb.pl?2" class="extiw" title="meatball:2">meatball:2</a>
 <a href="http://www.usemod.com/cgi-bin/mb.pl?3" class="extiw" title="meatball:3">meatball:3</a>
@@ -16334,9 +16078,9 @@ wgLinkHolderBatchSize=0
 
 !! test
 Free external link invading image caption
-!! input
+!! wikitext
 [[Image:Foobar.jpg|thumb|http://x|hello]]
-!! result
+!! html
 <div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" width="180" height="20" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/270px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/360px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div>hello</div></div></div>
 
 !! end
@@ -16345,54 +16089,54 @@ Free external link invading image caption
 Bug 15196: localised external link numbers
 !! options
 language=fa
-!! input
+!! wikitext
 [http://en.wikipedia.org/]
-!! result
+!! html
 <p><a rel="nofollow" class="external autonumber" href="http://en.wikipedia.org/">[۱]</a>
 </p>
 !! end
 
 !! test
 Multibyte character in padleft
-!! input
+!! wikitext
 {{padleft:-Hello|7|Æ}}
-!! result
+!! html
 <p>Æ-Hello
 </p>
 !! end
 
 !! test
 Multibyte character in padright
-!! input
+!! wikitext
 {{padright:Hello-|7|Æ}}
-!! result
+!! html
 <p>Hello-Æ
 </p>
 !! end
 
 !!test
 formatdate parser function
-!!input
+!! wikitext
 {{#formatdate:2009-03-24}}
-!! result
+!! html
 <p><span class="mw-formatted-date" title="2009-03-24">2009-03-24</span>
 </p>
 !! end
 
 !!test
 formatdate parser function, with default format
-!!input
+!! wikitext
 {{#formatdate:2009-03-24|mdy}}
-!! result
+!! html
 <p><span class="mw-formatted-date" title="2009-03-24">March 24, 2009</span>
 </p>
 !! end
 
 !! test
 Spacing of numbers in formatted dates
-!! input
+!! wikitext
 {{#formatdate:January 15}}
-!! result
+!! html
 <p><span class="mw-formatted-date" title="01-15">January 15</span>
 </p>
 !! end
@@ -16401,9 +16145,9 @@ Spacing of numbers in formatted dates
 formatdate parser function, with default format and on a page of which the content language is always English and different from the wiki content language
 !! options
 language=nl title=[[MediaWiki:Common.css]]
-!! input
+!! wikitext
 {{#formatdate:2009-03-24|dmy}}
-!! result
+!! html
 <p><span class="mw-formatted-date" title="2009-03-24">24 March 2009</span>
 </p>
 !! end
@@ -16420,9 +16164,9 @@ language=nl title=[[MediaWiki:Common.css]]
 Edit comment with link
 !! options
 comment
-!! input
+!! wikitext
 I like the [[Main Page]] a lot
-!! result
+!! html
 I like the <a href="/wiki/Main_Page" title="Main Page">Main Page</a> a lot
 !!end
 
@@ -16430,9 +16174,9 @@ I like the <a href="/wiki/Main_Page" title="Main Page">Main Page</a> a lot
 Edit comment with link and link text
 !! options
 comment
-!! input
+!! wikitext
 I like the [[Main Page|best pages]] a lot
-!! result
+!! html
 I like the <a href="/wiki/Main_Page" title="Main Page">best pages</a> a lot
 !!end
 
@@ -16440,9 +16184,9 @@ I like the <a href="/wiki/Main_Page" title="Main Page">best pages</a> a lot
 Edit comment with link and link text with suffix
 !! options
 comment
-!! input
+!! wikitext
 I like the [[Main Page|best page]]s a lot
-!! result
+!! html
 I like the <a href="/wiki/Main_Page" title="Main Page">best pages</a> a lot
 !!end
 
@@ -16450,9 +16194,9 @@ I like the <a href="/wiki/Main_Page" title="Main Page">best pages</a> a lot
 Edit comment with section link (non-local, eg in history list)
 !! options
 comment title=[[Main Page]]
-!! input
+!! wikitext
 /* External links */ removed bogus entries
-!! result
+!! html
 <a href="/wiki/Main_Page#External_links" title="Main Page">→</a>‎<span dir="auto"><span class="autocomment">External links: </span> removed bogus entries</span>
 !!end
 
@@ -16460,9 +16204,9 @@ comment title=[[Main Page]]
 Edit comment with section link and text before it (non-local, eg in history list)
 !! options
 comment title=[[Main Page]]
-!! input
+!! wikitext
 pre-comment text /* External links */ removed bogus entries
-!! result
+!! html
 pre-comment text <a href="/wiki/Main_Page#External_links" title="Main Page">→</a>‎<span dir="auto"><span class="autocomment">External links: </span> removed bogus entries</span>
 !!end
 
@@ -16470,9 +16214,9 @@ pre-comment text <a href="/wiki/Main_Page#External_links" title="Main Page">→<
 Edit comment with section link (local, eg in diff view)
 !! options
 comment local title=[[Main Page]]
-!! input
+!! wikitext
 /* External links */ removed bogus entries
-!! result
+!! html
 <a href="#External_links">→</a>‎<span dir="auto"><span class="autocomment">External links: </span> removed bogus entries</span>
 !!end
 
@@ -16482,9 +16226,9 @@ Edit comment with subpage link (bug 14080)
 comment
 subpage
 title=[[Subpage test]]
-!! input
+!! wikitext
 Poked at a [[/subpage]] here...
-!! result
+!! html
 Poked at a <a href="/wiki/Subpage_test/subpage" title="Subpage test/subpage">/subpage</a> here...
 !!end
 
@@ -16494,9 +16238,9 @@ Edit comment with subpage link and link text (bug 14080)
 comment
 subpage
 title=[[Subpage test]]
-!! input
+!! wikitext
 Poked at a [[/subpage|neat little page]] here...
-!! result
+!! html
 Poked at a <a href="/wiki/Subpage_test/subpage" title="Subpage test/subpage">neat little page</a> here...
 !!end
 
@@ -16505,9 +16249,9 @@ Edit comment with bogus subpage link in non-subpage NS (bug 14080)
 !! options
 comment
 title=[[Subpage test]]
-!! input
+!! wikitext
 Poked at a [[/subpage]] here...
-!! result
+!! html
 Poked at a <a href="/index.php?title=/subpage&amp;action=edit&amp;redlink=1" class="new" title="/subpage (page does not exist)">/subpage</a> here...
 !!end
 
@@ -16517,9 +16261,9 @@ Edit comment with bare anchor link (local, as on diff)
 comment
 local
 title=[[Main Page]]
-!!input
+!! wikitext
 [[#section]]
-!! result
+!! html
 <a href="#section">#section</a>
 !! end
 
@@ -16528,26 +16272,26 @@ Edit comment with bare anchor link (non-local, as on history)
 !! options
 comment
 title=[[Main Page]]
-!!input
+!! wikitext
 [[#section]]
-!! result
+!! html
 <a href="/wiki/Main_Page#section" title="Main Page">#section</a>
 !! end
 
 !! test
 Anchor starting with underscore
-!!input
+!! wikitext
 [[#_ref|One]]
-!! result
+!! html
 <p><a href="#_ref">One</a>
 </p>
 !! end
 
 !! test
 Id starting with underscore
-!!input
+!! wikitext
 <div id="_ref"></div>
-!! result
+!! html
 <div id="_ref"></div>
 
 !! end
@@ -16557,9 +16301,9 @@ Space normalisation on autocomment (bug 22784)
 !! options
 comment
 title=[[Main Page]]
-!!input
+!! wikitext
 /* __hello__world__ */
-!! result
+!! html
 <a href="/wiki/Main_Page#hello_world" title="Main Page">→</a>‎<span dir="auto"><span class="autocomment">__hello__world__</span></span>
 !! end
 
@@ -16567,9 +16311,9 @@ title=[[Main Page]]
 percent-encoding and + signs in comments (Bug 26410)
 !! options
 comment
-!!input
+!! wikitext
 [[ABC%33D% ++]] [[ABC%33D% ++|+%20]]
-!! result
+!! html
 <a href="/index.php?title=ABC3D%25_%2B%2B&amp;action=edit&amp;redlink=1" class="new" title="ABC3D% ++ (page does not exist)">ABC3D% ++</a> <a href="/index.php?title=ABC3D%25_%2B%2B&amp;action=edit&amp;redlink=1" class="new" title="ABC3D% ++ (page does not exist)">+%20</a>
 !! end
 
@@ -16577,20 +16321,20 @@ comment
 Bad images - basic functionality
 !! options
 disabled
-!! input
+!! wikitext
 [[File:Bad.jpg]]
-!! result
+!! html
 !! end
 
 !! test
 Bad images - bug 16039: text after bad image disappears
 !! options
 disabled
-!! input
+!! wikitext
 Foo bar
 [[File:Bad.jpg]]
 Bar foo
-!! result
+!! html
 <p>Foo bar
 </p><p>Bar foo
 </p>
@@ -16603,9 +16347,9 @@ showtitle
 !! config
 wgAllowDisplayTitle=true
 wgRestrictDisplayTitle=false
-!! input
+!! wikitext
 this is not the the title
-!! result
+!! html
 Parser test
 <p>this is not the the title
 </p>
@@ -16619,10 +16363,10 @@ title=[[Screen]]
 !! config
 wgAllowDisplayTitle=true
 wgRestrictDisplayTitle=false
-!! input
+!! wikitext
 this is not the the title
 {{DISPLAYTITLE:whatever}}
-!! result
+!! html
 whatever
 <p>this is not the the title
 </p>
@@ -16636,10 +16380,10 @@ title=[[Screen]]
 !! config
 wgAllowDisplayTitle=true
 wgRestrictDisplayTitle=true
-!! input
+!! wikitext
 this is not the the title
 {{DISPLAYTITLE:whatever}}
-!! result
+!! html
 Screen
 <p>this is not the the title
 </p>
@@ -16653,10 +16397,10 @@ title=[[Screen]]
 !! config
 wgAllowDisplayTitle=true
 wgRestrictDisplayTitle=true
-!! input
+!! wikitext
 this is not the the title
 {{DISPLAYTITLE:screen}}
-!! result
+!! html
 screen
 <p>this is not the the title
 </p>
@@ -16669,10 +16413,10 @@ showtitle
 title=[[Screen]]
 !! config
 wgAllowDisplayTitle=false
-!! input
+!! wikitext
 this is not the the title
 {{DISPLAYTITLE:screen}}
-!! result
+!! html
 Screen
 <p>this is not the the title
 <a href="/index.php?title=Template:DISPLAYTITLE:screen&amp;action=edit&amp;redlink=1" class="new" title="Template:DISPLAYTITLE:screen (page does not exist)">Template:DISPLAYTITLE:screen</a>
@@ -16686,9 +16430,9 @@ showtitle
 title=[[Screen]]
 !! config
 wgAllowDisplayTitle=false
-!! input
+!! wikitext
 this is not the the title
-!! result
+!! html
 Screen
 <p>this is not the the title
 </p>
@@ -16702,10 +16446,10 @@ title=[[Screen]]
 !! config
 wgAllowDisplayTitle=true
 wgRestrictDisplayTitle=true
-!! input
+!! wikitext
 this is not the the title
 {{DISPLAYTITLE:<span style="display: none;">s</span>creen}}
-!! result
+!! html
 <span style="/* attempt to bypass $wgRestrictDisplayTitle */">s</span>creen
 <p>this is not the the title
 </p>
@@ -16719,10 +16463,10 @@ title=[[Screen]]
 !! config
 wgAllowDisplayTitle=true
 wgRestrictDisplayTitle=true
-!! input
+!! wikitext
 this is not the the title
 {{DISPLAYTITLE:<span style="color: red;">s</span>creen}}
-!! result
+!! html
 <span style="color: red;">s</span>creen
 <p>this is not the the title
 </p>
@@ -16732,9 +16476,9 @@ this is not the the title
 preload: check <noinclude> and <includeonly>
 !! options
 preload
-!! input
+!! wikitext
 Hello <noinclude>cruel</noinclude><includeonly>kind</includeonly> world.
-!! result
+!! html
 Hello kind world.
 !! end
 
@@ -16742,9 +16486,9 @@ Hello kind world.
 preload: check <onlyinclude>
 !! options
 preload
-!! input
+!! wikitext
 Goodbye <onlyinclude>Hello world</onlyinclude>
-!! result
+!! html
 Hello world
 !! end
 
@@ -16752,9 +16496,9 @@ Hello world
 preload: can pass tags through if we want to
 !! options
 preload
-!! input
+!! wikitext
 <includeonly><</includeonly>includeonly>Hello world<includeonly><</includeonly>/includeonly>
-!! result
+!! html
 <includeonly>Hello world</includeonly>
 !! end
 
@@ -16762,9 +16506,9 @@ preload
 preload: check that it doesn't try to do tricks
 !! options
 preload
-!! input
+!! wikitext
 * <!-- Hello --> ''{{world}}'' {{<includeonly>subst:</includeonly>How are you}}{{ {{{|safesubst:}}} #if:1|2|3}}
-!! result
+!! html
 * <!-- Hello --> ''{{world}}'' {{subst:How are you}}{{ {{{|safesubst:}}} #if:1|2|3}}
 !! end
 
@@ -16772,12 +16516,12 @@ preload
 Play a bit with r67090 and bug 3158
 !! options
 disabled
-!! input
+!! wikitext
 <div style="width:50% !important">&nbsp;</div>
 <div style="width:50%&nbsp;!important">&nbsp;</div>
 <div style="width:50%&#160;!important">&nbsp;</div>
 <div style="border : solid;">&nbsp;</div>
-!! result
+!! html
 <div style="width:50% !important">&nbsp;</div>
 <div style="width:50% !important">&nbsp;</div>
 <div style="width:50% !important">&nbsp;</div>
@@ -16787,10 +16531,10 @@ disabled
 
 !! test
 HTML5 data attributes
-!! input
+!! wikitext
 <span data-foo="bar">Baz</span>
 <p data-abc-def_hij="">Quuz</p>
-!! result
+!! html
 <p><span data-foo="bar">Baz</span>
 </p>
 <p data-abc-def_hij="">Quuz</p>
@@ -16799,12 +16543,12 @@ HTML5 data attributes
 
 !! test
 percent-encoding and + signs in internal links (Bug 26410)
-!! input
+!! wikitext
 [[User:+%]] [[Page+title%]]
 [[%+]] [[%+|%20]] [[%+ ]] [[%+r]]
 [[%]] [[+]] [[image:%+abc%39|foo|[[bar]]]]
 [[%33%45]] [[%33%45+]]
-!! result
+!! html
 <p><a href="/index.php?title=User:%2B%25&amp;action=edit&amp;redlink=1" class="new" title="User:+% (page does not exist)">User:+%</a> <a href="/index.php?title=Page%2Btitle%25&amp;action=edit&amp;redlink=1" class="new" title="Page+title% (page does not exist)">Page+title%</a>
 <a href="/index.php?title=%25%2B&amp;action=edit&amp;redlink=1" class="new" title="%+ (page does not exist)">%+</a> <a href="/index.php?title=%25%2B&amp;action=edit&amp;redlink=1" class="new" title="%+ (page does not exist)">%20</a> <a href="/index.php?title=%25%2B&amp;action=edit&amp;redlink=1" class="new" title="%+ (page does not exist)">%+ </a> <a href="/index.php?title=%25%2Br&amp;action=edit&amp;redlink=1" class="new" title="%+r (page does not exist)">%+r</a>
 <a href="/index.php?title=%25&amp;action=edit&amp;redlink=1" class="new" title="% (page does not exist)">%</a> <a href="/index.php?title=%2B&amp;action=edit&amp;redlink=1" class="new" title="+ (page does not exist)">+</a> <a href="/index.php?title=Special:Upload&amp;wpDestFile=%25%2Babc9" class="new" title="File:%+abc9">bar</a>
@@ -16814,10 +16558,10 @@ percent-encoding and + signs in internal links (Bug 26410)
 
 !! test
 Special characters in embedded file links (bug 27679)
-!! input
+!! wikitext
 [[File:Contains & ampersand.jpg]]
 [[File:Does not exist.jpg|Title with & ampersand]]
-!! result
+!! html
 <p><a href="/index.php?title=Special:Upload&amp;wpDestFile=Contains_%26_ampersand.jpg" class="new" title="File:Contains &amp; ampersand.jpg">File:Contains &amp; ampersand.jpg</a>
 <a href="/index.php?title=Special:Upload&amp;wpDestFile=Does_not_exist.jpg" class="new" title="File:Does not exist.jpg">Title with &amp; ampersand</a>
 </p>
@@ -16826,36 +16570,36 @@ Special characters in embedded file links (bug 27679)
 
 !! test
 Confirm that 'apos' named character reference doesn't make it to output (not legal in HTML 4)
-!! input
+!! wikitext
 Text&apos;s been normalized?
-!! result
+!! html
 <p>Text&#39;s been normalized?
 </p>
 !! end
 
 !! test
 Bug 19052 U+3000 IDEOGRAPHIC SPACE should terminate free external links
-!! input
+!! wikitext
 http://www.example.org/ <-- U+3000 (vim: ^Vu3000)
-!! result
+!! html
 <p><a rel="nofollow" class="external free" href="http://www.example.org/">http://www.example.org/</a> &lt;-- U+3000 (vim: ^Vu3000)
 </p>
 !! end
 
 !! test
 Bug 19052 U+3000 IDEOGRAPHIC SPACE should terminate bracketed external links
-!! input
+!! wikitext
 [http://www.example.org/ ideograms]
-!! result
+!! html
 <p><a rel="nofollow" class="external text" href="http://www.example.org/">ideograms</a>
 </p>
 !! end
 
 !! test
 Bug 19052 U+3000 IDEOGRAPHIC SPACE should terminate external images links
-!! input
+!! wikitext
 http://www.example.org/pic.png <-- U+3000 (vim: ^Vu3000)
-!! result
+!! html
 <p><img src="http://www.example.org/pic.png" alt="pic.png" /> &lt;-- U+3000 (vim: ^Vu3000)
 </p>
 !! end
@@ -16881,9 +16625,9 @@ Template:Identical
 
 !! test
 Bug 31098 Template which includes system messages which includes the template
-!! input
+!! wikitext
 {{Identical}}
-!! result
+!! html
 <p><span class="error">Template loop detected: <a href="/wiki/Template:Identical" title="Template:Identical">Template:Identical</a></span>
 <span class="error">Template loop detected: <a href="/wiki/Template:Identical" title="Template:Identical">Template:Identical</a></span>
 </p>
@@ -16893,9 +16637,9 @@ Bug 31098 Template which includes system messages which includes the template
 Bug31490 Turkish: ucfirst 'blah'
 !! options
 language=tr
-!! input
+!! wikitext
 {{ucfirst:blah}}
-!! result
+!! html
 <p>Blah
 </p>
 !! end
@@ -16904,9 +16648,9 @@ language=tr
 Bug31490 Turkish: ucfirst 'ix'
 !! options
 language=tr
-!! input
+!! wikitext
 {{ucfirst:ix}}
-!! result
+!! html
 <p>İx
 </p>
 !! end
@@ -16915,9 +16659,9 @@ language=tr
 Bug31490 Turkish: lcfirst 'BLAH'
 !! options
 language=tr
-!! input
+!! wikitext
 {{lcfirst:BLAH}}
-!! result
+!! html
 <p>bLAH
 </p>
 !! end
@@ -16926,9 +16670,9 @@ language=tr
 Bug31490 Turkish: ucfırst (with a dotless i)
 !! options
 language=tr
-!! input
+!! wikitext
 {{ucfırst:blah}}
-!! result
+!! html
 <p><a href="/index.php?title=%C5%9Eablon:Ucf%C4%B1rst:blah&amp;action=edit&amp;redlink=1" class="new" title="Şablon:Ucfırst:blah (sayfa mevcut değil)">Şablon:Ucfırst:blah</a>
 </p>
 !! end
@@ -16937,9 +16681,9 @@ language=tr
 Bug31490 ucfırst (with a dotless i) with English language
 !! options
 language=en
-!! input
+!! wikitext
 {{ucfırst:blah}}
-!! result
+!! html
 <p><a href="/index.php?title=Template:Ucf%C4%B1rst:blah&amp;action=edit&amp;redlink=1" class="new" title="Template:Ucfırst:blah (page does not exist)">Template:Ucfırst:blah</a>
 </p>
 !! end
@@ -16948,10 +16692,10 @@ language=en
 Bug 26375: TOC with italics
 !! options
 title=[[Main Page]]
-!! input
+!! wikitext
 __TOC__
 == ''Lost'' episodes ==
-!! result
+!! html
 <div id="toc" class="toc"><div id="toctitle"><h2>Contents</h2></div>
 <ul>
 <li class="toclevel-1 tocsection-1"><a href="#Lost_episodes"><span class="tocnumber">1</span> <span class="toctext"><i>Lost</i> episodes</span></a></li>
@@ -16966,10 +16710,10 @@ __TOC__
 Bug 26375: TOC with bold
 !! options
 title=[[Main Page]]
-!! input
+!! wikitext
 __TOC__
 == '''should be bold''' then normal text ==
-!! result
+!! html
 <div id="toc" class="toc"><div id="toctitle"><h2>Contents</h2></div>
 <ul>
 <li class="toclevel-1 tocsection-1"><a href="#should_be_bold_then_normal_text"><span class="tocnumber">1</span> <span class="toctext"><b>should be bold</b> then normal text</span></a></li>
@@ -16984,10 +16728,10 @@ __TOC__
 Bug 33845: Headings become cursive in TOC when they contain an image
 !! options
 title=[[Main Page]]
-!! input
+!! wikitext
 __TOC__
 == Image [[Image:foobar.jpg]] ==
-!! result
+!! html
 <div id="toc" class="toc"><div id="toctitle"><h2>Contents</h2></div>
 <ul>
 <li class="toclevel-1 tocsection-1"><a href="#Image"><span class="tocnumber">1</span> <span class="toctext">Image</span></a></li>
@@ -17002,10 +16746,10 @@ __TOC__
 Bug 33845 (2): Headings become bold in TOC when they contain a blockquote
 !! options
 title=[[Main Page]]
-!! input
+!! wikitext
 __TOC__
 == <blockquote>Quote</blockquote> ==
-!! result
+!! html
 <div id="toc" class="toc"><div id="toctitle"><h2>Contents</h2></div>
 <ul>
 <li class="toclevel-1 tocsection-1"><a href="#Quote"><span class="tocnumber">1</span> <span class="toctext">Quote</span></a></li>
@@ -17020,12 +16764,12 @@ __TOC__
 Unclosed tags in TOC
 !! options
 title=[[Main Page]]
-!! input
+!! wikitext
 __TOC__
 == Proof: 2 < 3 ==
 <small>Hanc marginis exiguitas non caperet.</small>
 QED
-!! result
+!! html
 <div id="toc" class="toc"><div id="toctitle"><h2>Contents</h2></div>
 <ul>
 <li class="toclevel-1 tocsection-1"><a href="#Proof:_2_.3C_3"><span class="tocnumber">1</span> <span class="toctext">Proof: 2 &lt; 3</span></a></li>
@@ -17040,12 +16784,12 @@ QED
 
 !! test
 Multiple tags in TOC
-!! input
+!! wikitext
 __TOC__
 == <i>Foo</i> <b>Bar</b> ==
 
 == <i>Foo</i> <blockquote>Bar</blockquote> ==
-!! result
+!! html
 <div id="toc" class="toc"><div id="toctitle"><h2>Contents</h2></div>
 <ul>
 <li class="toclevel-1 tocsection-1"><a href="#Foo_Bar"><span class="tocnumber">1</span> <span class="toctext"><i>Foo</i> <b>Bar</b></span></a></li>
@@ -17060,12 +16804,12 @@ __TOC__
 
 !! test
 Tags with parameters in TOC
-!! input
+!! wikitext
 __TOC__
 == <sup class="in-h2">Hello</sup> ==
 
 == <sup class="a > b">Evilbye</sup> ==
-!! result
+!! html
 <div id="toc" class="toc"><div id="toctitle"><h2>Contents</h2></div>
 <ul>
 <li class="toclevel-1 tocsection-1"><a href="#Hello"><span class="tocnumber">1</span> <span class="toctext"><sup>Hello</sup></span></a></li>
@@ -17080,7 +16824,7 @@ __TOC__
 
 !! test
 span tags with directionality in TOC
-!! input
+!! wikitext
 __TOC__
 == <span dir="ltr">C++</span> ==
 
@@ -17091,7 +16835,7 @@ __TOC__
 == <span style="font-style: italic" dir="ltr">All attributes on these span tags must be deleted from the TOC</span> ==
 
 == <span dir="ltr" style="font-style: italic">Attributes after dir on these span tags must be deleted from the TOC</span> ==
-!! result
+!! html
 <div id="toc" class="toc"><div id="toctitle"><h2>Contents</h2></div>
 <ul>
 <li class="toclevel-1 tocsection-1"><a href="#C.2B.2B"><span class="tocnumber">1</span> <span class="toctext"><span dir="ltr">C++</span></span></a></li>
@@ -17120,20 +16864,20 @@ MediaWiki:Bug32057
 Bug 32057: Title needed when expanding <h> nodes.
 !! options
 title=[[Main Page]]
-!! input
+!! wikitext
 {{int:Bug32057}}
-!! result
+!! html
 <h2><span class="mw-headline" id="Headline_text">Headline text</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Main_Page&amp;action=edit&amp;section=1" title="Edit section: Headline text">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
 
 !! end
 
 !! test
 Strip marker in urlencode
-!! input
+!! wikitext
 {{urlencode:x<nowiki/>y}}
 {{urlencode:x<nowiki/>y|wiki}}
 {{urlencode:x<nowiki/>y|path}}
-!! result
+!! html
 <p>xy
 xy
 xy
 
 !! test
 Strip marker in lc
-!! input
+!! wikitext
 {{lc:x<nowiki/>y}}
-!! result
+!! html
 <p>xy
 </p>
 !! end
 
 !! test
 Strip marker in uc
-!! input
+!! wikitext
 {{uc:x<nowiki/>y}}
-!! result
+!! html
 <p>XY
 </p>
 !! end
 
 !! test
 Strip marker in formatNum
-!! input
+!! wikitext
 {{formatnum:1<nowiki/>2}}
 {{formatnum:1<nowiki/>2|R}}
-!! result
+!! html
 <p>12
 12
 </p>
@@ -17173,10 +16917,10 @@ Strip marker in formatNum
 Check noCommafy in formatNum
 !! options
 language=be-tarask
-!! input
+!! wikitext
 {{formatnum:123456.78}}
 {{formatnum:123456.78|NOSEP}}
-!! result
+!! html
 <p>123 456,78
 123456.78
 </p>
@@ -17184,11 +16928,11 @@ language=be-tarask
 
 !! test
 Wrong option for formatNum (bug 56199)
-!! input
+!! wikitext
 {{formatnum:1,234.56|Random}}
 {{formatnum:1,234.56|EVERYTHING}}
 {{formatnum:1234.56|any argument that has the string 'NOSEP'}}
-!! result
+!! html
 <p>1,234.56
 1,234.56
 1,234.56
@@ -17199,67 +16943,67 @@ Wrong option for formatNum (bug 56199)
 Strip marker in grammar
 !! options
 language=fi
-!! input
+!! wikitext
 {{grammar:elative|foo<nowiki/>bar}}
-!! result
+!! html
 <p>foobarista
 </p>
 !! end
 
 !! test
 Strip marker in padleft
-!! input
+!! wikitext
 {{padleft:|2|x<nowiki/>y}}
-!! result
+!! html
 <p>xy
 </p>
 !! end
 
 !! test
 Strip marker in padright
-!! input
+!! wikitext
 {{padright:|2|x<nowiki/>y}}
-!! result
+!! html
 <p>xy
 </p>
 !! end
 
 !! test
 Strip marker in anchorencode
-!! input
+!! wikitext
 {{anchorencode:x<nowiki/>y}}
-!! result
+!! html
 <p>xy
 </p>
 !! end
 
 !! test
 nowiki inside link inside heading (bug 18295)
-!! input
+!! wikitext
 ==[[foo|x<nowiki>y</nowiki>z]]==
-!! result
+!! html
 <h2><span class="mw-headline" id="xyz"><a href="/index.php?title=Foo&amp;action=edit&amp;redlink=1" class="new" title="Foo (page does not exist)">xyz</a></span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=1" title="Edit section: xyz">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
 
 !! end
 
 !! test
 new support for bdi element (bug 31817)
-!! input
+!! wikitext
 <p dir="rtl" lang="he">ולדימיר לנין (ברוסית: <bdi lang="ru">Владимир Ленин</bdi>, 24 באפריל 1870–22 בינואר 1924) הוא מנהיג פוליטי קומוניסטי רוסי.</p>
-!! result
+!! html
 <p dir="rtl" lang="he">ולדימיר לנין (ברוסית: <bdi lang="ru">Владимир Ленин</bdi>, 24 באפריל 1870–22 בינואר 1924) הוא מנהיג פוליטי קומוניסטי רוסי.</p>
 
 !!end
 
 !! test
 Ignore pipe between table row attributes
-!! input
+!! wikitext
 {|
 | quux
 |- id=foo | style='color: red'
 | bar
 |}
-!! result
+!! html
 <table>
 <tr>
 <td> quux
@@ -17272,11 +17016,11 @@ Ignore pipe between table row attributes
 
 !!test
 Gallery override link with WikiLink (bug 34852)
-!! input
+!! wikitext
 <gallery>
 File:foobar.jpg|caption|alt=galleryalt|link=InterWikiLink
 </gallery>
-!! result
+!! html
 <ul class="gallery mw-gallery-traditional">
                <li class="gallerybox" style="width: 155px"><div style="width: 155px">
                        <div class="thumb" style="width: 150px;"><div style="margin:68px auto;"><a href="/wiki/InterWikiLink"><img alt="galleryalt" src="http://example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" width="120" height="14" /></a></div></div>
@@ -17291,11 +17035,11 @@ File:foobar.jpg|caption|alt=galleryalt|link=InterWikiLink
 
 !!test
 Gallery override link with absolute external link (bug 34852)
-!! input
+!! wikitext
 <gallery>
 File:foobar.jpg|caption|alt=galleryalt|link=http://www.example.org
 </gallery>
-!! result
+!! html
 <ul class="gallery mw-gallery-traditional">
                <li class="gallerybox" style="width: 155px"><div style="width: 155px">
                        <div class="thumb" style="width: 150px;"><div style="margin:68px auto;"><a href="http://www.example.org"><img alt="galleryalt" src="http://example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" width="120" height="14" /></a></div></div>
@@ -17310,11 +17054,11 @@ File:foobar.jpg|caption|alt=galleryalt|link=http://www.example.org
 
 !!test
 Gallery override link with malicious javascript (bug 34852)
-!! input
+!! wikitext
 <gallery>
 File:foobar.jpg|caption|alt=galleryalt|link=" onclick="alert('malicious javascript code!');
 </gallery>
-!! result
+!! html
 <ul class="gallery mw-gallery-traditional">
                <li class="gallerybox" style="width: 155px"><div style="width: 155px">
                        <div class="thumb" style="width: 150px;"><div style="margin:68px auto;"><a href="/wiki/%22_onclick%3D%22alert(%27malicious_javascript_code!%27);"><img alt="galleryalt" src="http://example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" width="120" height="14" /></a></div></div>
@@ -17329,11 +17073,11 @@ File:foobar.jpg|caption|alt=galleryalt|link=" onclick="alert('malicious javascri
 
 !!test
 Gallery with invalid title as link (bug 43964)
-!! input
+!! wikitext
 <gallery>
 File:foobar.jpg|link=<
 </gallery>
-!! result
+!! html
 <ul class="gallery mw-gallery-traditional">
                <li class="gallerybox" style="width: 155px"><div style="width: 155px">
                        <div class="thumb" style="width: 150px;"><div style="margin:68px auto;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" width="120" height="14" /></a></div></div>
@@ -17346,19 +17090,19 @@ File:foobar.jpg|link=<
 
 !!test
 Language parser function
-!! input
+!! wikitext
 {{#language:ar}}
-!! result
+!! html
 <p>العربية
 </p>
 !! end
 
 !!test
 Padleft and padright as substr
-!! input
+!! wikitext
 {{padleft:|3|abcde}}
 {{padright:|3|abcde}}
-!! result
+!! html
 <p>abc
 abc
 </p>
@@ -17366,11 +17110,11 @@ abc
 
 !!test
 Special parser function
-!! input
+!! wikitext
 {{#special:RandomPage}}
 {{#special:BaDtItLe}}
 {{#special:Foobar}}
-!! result
+!! html
 <p>Special:Random
 Special:Badtitle
 Special:Foobar
@@ -17379,27 +17123,27 @@ Special:Foobar
 
 !!test
 Bug 34939 - Case insensitive link parsing ([HttP://])
-!! input
+!! wikitext
 [HttP://MediaWiki.Org/]
-!! result
+!! html
 <p><a rel="nofollow" class="external autonumber" href="HttP://MediaWiki.Org/">[1]</a>
 </p>
 !! end
 
 !!test
 Bug 34939 - Case insensitive link parsing ([HttP:// title])
-!! input
+!! wikitext
 [HttP://MediaWiki.Org/ MediaWiki]
-!! result
+!! html
 <p><a rel="nofollow" class="external text" href="HttP://MediaWiki.Org/">MediaWiki</a>
 </p>
 !! end
 
 !!test
 Bug 34939 - Case insensitive link parsing (HttP://)
-!! input
+!! wikitext
 HttP://MediaWiki.Org/
-!! result
+!! html
 <p><a rel="nofollow" class="external free" href="HttP://MediaWiki.Org/">HttP://MediaWiki.Org/</a>
 </p>
 !! end
@@ -17408,14 +17152,14 @@ HttP://MediaWiki.Org/
 Disable TOC
 !! options
 notoc
-!! input
+!! wikitext
 Lead
 == Section 1 ==
 == Section 2 ==
 == Section 3 ==
 == Section 4 ==
 == Section 5 ==
-!! result
+!! html
 <p>Lead
 </p>
 
@@ -17436,11 +17180,11 @@ Lead
 1. SOL-sensitive wikitext tokens as template-args
 !!options
 parsoid=wt2html,wt2wt
-!!input
+!! wikitext
 {{echo|*a}}
 {{echo|#a}}
 {{echo|:a}}
-!!result
+!! html
 <span about="#mwt1" typeof="mw:Transclusion">
 </span><ul about="#mwt1"><li>a</li>
 </ul>
@@ -17462,11 +17206,11 @@ parsoid=wt2html,wt2wt
 Ref: 1. ref-location should be replaced with an index span
 !!options
 parsoid
-!!input
+!! wikitext
 A <ref>foo</ref>
 B <ref name="x">foo</ref>
 C <ref name="y" />
-!!result
+!! html
 <p>A <span about="#mwt1" class="reference" data-mw='{"name":"ref","body":{"html":"foo"},"attrs":{}}' id="cite_ref-1-0" rel="dc:references" typeof="mw:Extension/ref"><a href="#cite_note-1">[1]</a></span>
 B <span about="#mwt2" class="reference" data-mw='{"name":"ref","body":{"html":"foo"},"attrs":{"name":"x"}}' id="cite_ref-x-2-0" rel="dc:references" typeof="mw:Extension/ref"><a href="#cite_note-x-2">[2]</a></span>
 C <span about="#mwt3" class="reference" data-mw='{"name":"ref","attrs":{"name":"y"}}' id="cite_ref-y-3-0" rel="dc:references" typeof="mw:Extension/ref"><a href="#cite_note-y-3">[3]</a></span></p>
@@ -17476,10 +17220,10 @@ C <span about="#mwt3" class="reference" data-mw='{"name":"ref","attrs":{"name":"
 Ref: 2. ref-tags with identical names should all get the same index
 !!options
 parsoid
-!!input
+!! wikitext
 A <ref name="x">foo</ref>
 B <ref name="x" />
-!!result
+!! html
 <p>A <span about="#mwt1" class="reference" data-mw='{"name":"ref","body":{"html":"foo"},"attrs":{"name":"x"}}' id="cite_ref-x-1-0" rel="dc:references" typeof="mw:Extension/ref"><a href="#cite_note-x-1">[1]</a></span>
 B <span about="#mwt2" class="reference" data-mw='{"name":"ref","attrs":{"name":"x"}}' id="cite_ref-x-1-1" rel="dc:references" typeof="mw:Extension/ref"><a href="#cite_note-x-1">[1]</a></span></p>
 !!end
@@ -17488,11 +17232,11 @@ B <span about="#mwt2" class="reference" data-mw='{"name":"ref","attrs":{"name":"
 Ref: 3. spaces in ref-names should be ignored
 !!options
 parsoid
-!!input
+!! wikitext
 A <ref name="x">foo</ref>
 B <ref name=" x " />
 C <ref name= x  />
-!!result
+!! html
 <p>A <span about="#mwt1" class="reference" data-mw='{"name":"ref","body":{"html":"foo"},"attrs":{"name":"x"}}' id="cite_ref-x-1-0" rel="dc:references" typeof="mw:Extension/ref"><a href="#cite_note-x-1">[1]</a></span>
 B <span about="#mwt2" class="reference" data-mw='{"name":"ref","attrs":{"name":"x"}}' id="cite_ref-x-1-1" rel="dc:references" typeof="mw:Extension/ref"><a href="#cite_note-x-1">[1]</a></span>
 C <span about="#mwt3" class="reference" data-mw='{"name":"ref","attrs":{"name":"x"}}' id="cite_ref-x-1-2" rel="dc:references" typeof="mw:Extension/ref"><a href="#cite_note-x-1">[1]</a></span></p>
@@ -17503,9 +17247,9 @@ Ref: 4. 'constructor' should be accepted as a valid ref-name
 (NOTE: constructor is a predefined property in JS and constructor as a ref-name can clash with it if not handled properly)
 !!options
 parsoid
-!!input
+!! wikitext
 A <ref name="constructor">foo</ref>
-!!result
+!! html
 <p>A <span about="#mwt1" class="reference" data-mw='{"name":"ref","body":{"html":"foo"},"attrs":{"name":"constructor"}}' id="cite_ref-constructor-1-0" rel="dc:references" typeof="mw:Extension/ref"><a href="#cite_note-constructor-1">[1]</a></span></p>
 !!end
 
@@ -17513,13 +17257,13 @@ A <ref name="constructor">foo</ref>
 Ref: 5. body should accept generic wikitext
 !!options
 parsoid
-!!input
+!! wikitext
 A <ref>
  This is a '''[[bolded link]]''' and this is a {{echo|transclusion}}
 </ref>
 
 <references />
-!!result
+!! html
 <p>A <span about="#mwt2" class="reference" data-mw='{"name":"ref","body":{"html":"This is a &lt;b data-parsoid=&#39;{\"dsr\":[19,40,3,3]}&#39;>&lt;a rel=\"mw:WikiLink\" href=\"./Bolded_link\" data-parsoid=&#39;{\"stx\":\"simple\",\"a\":{\"href\":\"./Bolded_link\"},\"sa\":{\"href\":\"bolded link\"},\"dsr\":[22,37,2,2]}&#39;>bolded link&lt;/a>&lt;/b> and this is a &lt;span about=\"#mwt3\" typeof=\"mw:Transclusion\" data-mw=&#39;{\"parts\":[{\"template\":{\"target\":{\"wt\":\"echo\",\"href\":\"./Template:Echo\"},\"params\":{\"1\":{\"wt\":\"transclusion\"}},\"i\":0}}]}&#39; data-parsoid=&#39;{\"dsr\":[55,76,null,null],\"pi\":[[{\"k\":\"1\",\"spc\":[\"\",\"\",\"\",\"\"]}]]}&#39;>transclusion&lt;/span>\n"},"attrs":{}}' id="cite_ref-1-0" rel="dc:references" typeof="mw:Extension/ref"><a href="#cite_note-1">[1]</a></span></p>
 
 <ol class="references" typeof="mw:Extension/references" about="#mwt4" data-mw='{"name":"references","attrs":{}}'>
@@ -17532,7 +17276,7 @@ A <ref>
 Ref: 6. indent-pres should not be output in ref-body
 !!options
 parsoid
-!!input
+!! wikitext
 A <ref>
  foo
  bar
@@ -17540,7 +17284,7 @@ A <ref>
 </ref>
 
 <references />
-!!result
+!! html
 <p>A <span about="#mwt1" class="reference" data-mw='{"name":"ref","body":{"html":"foo\n bar\n baz\n"},"attrs":{}}' id="cite_ref-1-0" rel="dc:references" typeof="mw:Extension/ref"><a href="#cite_note-1">[1]</a></span></p>
 
 <ol class="references" typeof="mw:Extension/references" about="#mwt3" data-mw='{"name":"references","attrs":{}}'>
@@ -17555,7 +17299,7 @@ A <ref>
 Ref: 7. No p-wrapping in ref-body
 !!options
 parsoid
-!!input
+!! wikitext
 A <ref>
 foo
 
@@ -17570,7 +17314,7 @@ booz
 </ref>
 
 <references />
-!!result
+!! html
 <p>A <span about="#mwt1" class="reference" data-mw='{"name":"ref","body":{"html":"foo\n\nbar\n\n\nbaz\n\n\n\nbooz\n"},"attrs":{}}' id="cite_ref-1-0" rel="dc:references" typeof="mw:Extension/ref"><a href="#cite_note-1">[1]</a></span></p>
 
 <ol about="#mwt2" class="references" typeof="mw:Extension/references" data-mw='{"name":"references","attrs":{}}'>
@@ -17592,11 +17336,11 @@ booz
 Ref: 8. transclusion wikitext has lower precedence
 !!options
 parsoid
-!!input
+!! wikitext
 A <ref> foo {{echo|</ref> B C}}
 
 <references />
-!!result
+!! html
 <p>A <span class="reference" data-mw="{&quot;name&quot;:&quot;ref&quot;,&quot;body&quot;:{&quot;html&quot;:&quot;foo <span typeof=\&quot;mw:Nowiki\&quot; data-parsoid='{\&quot;src\&quot;:\&quot;{{\&quot;,\&quot;dsr\&quot;:[12,14,0,0]}'>{{</span>echo|&quot;},&quot;attrs&quot;:{}}" id="cite_ref-1-0" rel="dc:references" typeof="mw:Extension/ref"><a href="#cite_note-1">[1]</a></span> B C<span typeof="mw:Nowiki">}}</span></p>
 <ol class="references" typeof="mw:Extension/references" data-mw="{&quot;name&quot;:&quot;references&quot;,&quot;attrs&quot;:{}}">
 <li id="cite_note-1"><span rel="mw:referencedBy"><a href="#cite_ref-1-0">↑</a></span> foo <span typeof="mw:Nowiki">{{</span>echo|</li>
@@ -17607,10 +17351,10 @@ A <ref> foo {{echo|</ref> B C}}
 Ref: 9. unclosed comments should not leak out of ref-body
 !!options
 parsoid
-!!input
+!! wikitext
 A <ref> foo <!--</ref> B C
 <references />
-!!result
+!! html
 <p>A <span class="reference" data-mw='{"name":"ref","body":{"html":"foo &lt;!---->"},"attrs":{}}' id="cite_ref-1-0" rel="dc:references" typeof="mw:Extension/ref"><a href="#cite_note-1">[1]</a></span> B C</p>
 <ol class="references" typeof="mw:Extension/references" data-mw='{"name":"references","attrs":{}}'>
 <li id="cite_note-1"><span rel="mw:referencedBy"><a href="#cite_ref-1-0">↑</a></span> foo </li>
@@ -17621,11 +17365,11 @@ A <ref> foo <!--</ref> B C
 Ref: 10. Unclosed HTML tags should not leak out of ref-body
 !!options
 parsoid
-!!input
+!! wikitext
 A <ref> <b> foo </ref> B C
 
 <references />
-!!result
+!! html
 <p>A <span about="#mwt2" class="reference" data-mw='{"name":"ref","body":{"html":"&lt;b data-parsoid=&#39;{\"stx\":\"html\",\"autoInsertedEnd\":true,\"dsr\":[8,16,3,0]}&#39;> foo &lt;/b>"},"attrs":{}}' id="cite_ref-1-0" rel="dc:references" typeof="mw:Extension/ref" data-parsoid='{"src":"&lt;ref> &lt;b> foo &lt;/ref>"}'><a href="#cite_note-1">[1]</a></span> B C</p>
 
 
@@ -17638,10 +17382,10 @@ A <ref> <b> foo </ref> B C
 Ref: 11. ref-tags acts like an inline element wrt P-wrapping
 !!options
 parsoid
-!!input
+!! wikitext
 A <ref>foo</ref> B
 C <ref>bar</ref> D
-!!result
+!! html
 <p>A <span about="#mwt2" class="reference" data-mw='{"name":"ref","body":{"html":"foo"},"attrs":{}}' id="cite_ref-1-0" rel="dc:references" typeof="mw:Extension/ref" data-parsoid='{"src":"&lt;ref>foo&lt;/ref>"}'><a href="#cite_note-1">[1]</a></span> B
 C <span about="#mwt4" class="reference" data-mw='{"name":"ref","body":{"html":"bar"},"attrs":{}}' id="cite_ref-2-0" rel="dc:references" typeof="mw:Extension/ref" data-parsoid='{"src":"&lt;ref>bar&lt;/ref>"}'><a href="#cite_note-2">[2]</a></span> D</p>
 !!end
@@ -17650,14 +17394,14 @@ C <span about="#mwt4" class="reference" data-mw='{"name":"ref","body":{"html":"b
 Ref: 12. ref-tags act as trailing newline migration barrier
 !!options
 parsoid
-!!input
+!! wikitext
 <!--the newline at the end of this line moves out of the p-tag-->a
 
 b<!--the newline at the end of this line stays inside the p-tag--> <ref />
 <ref />
 
 c
-!!result
+!! html
 <p><!--the newline at the end of this line moves out of the p-tag-->a</p>
 
 
 Ref: 13. ref-tags are not SOL-transparent and block indent-pres
 !!options
 parsoid
-!!input
+!! wikitext
 <ref>foo</ref> A
 <ref>bar
 </ref> B
-!!result
+!! html
 <p><span about="#mwt1" class="reference" data-mw='{"name":"ref","body":{"html":"foo"},"attrs":{}}' id="cite_ref-1-0" rel="dc:references" typeof="mw:Extension/ref"><a href="#cite_note-1">[1]</a></span> A
 <span about="#mwt2" class="reference" data-mw='{"name":"ref","body":{"html":"bar\n"},"attrs":{}}' id="cite_ref-2-0" rel="dc:references" typeof="mw:Extension/ref"><a href="#cite_note-2">[2]</a></span> B</p>
 !!end
@@ -17685,11 +17429,11 @@ parsoid
 Ref: 14. A nested ref-tag should be emitted as plain text
 !!options
 parsoid
-!!input
+!! wikitext
 <ref>foo <ref>bar</ref> baz</ref>
 
 <references />
-!!result
+!! html
 <p><span about="#mwt2" class="reference" data-mw='{"name":"ref","body":{"html":"foo &amp;lt;ref>bar&amp;lt;/ref> baz"},"attrs":{}}' id="cite_ref-1-0" rel="dc:references" typeof="mw:Extension/ref" data-parsoid='{"src":"&lt;ref>foo &lt;ref>bar&lt;/ref> baz&lt;/ref>"}'><a href="#cite_note-1">[1]</a></span></p>
 
 <ol class="references" typeof="mw:Extension/references" about="#mwt5" data-parsoid='{"src":"&lt;references />"}' data-mw='{"name":"references","attrs":{}}'>
@@ -17701,12 +17445,12 @@ parsoid
 Ref: 15. ref-tags with identical names should get identical indexes
 !!options
 parsoid
-!!input
+!! wikitext
 A1 <ref name="a">foo</ref> A2 <ref name="a" />
 B1 <ref name="b" /> B2 <ref name="b">bar</ref>
 
 <references />
-!!result
+!! html
 <p>A1 <span about="#mwt3" class="reference" data-mw='{"name":"ref","body":{"html":"foo"},"attrs":{"name":"a"}}' id="cite_ref-a-1-0" rel="dc:references" typeof="mw:Extension/ref"><a href="#cite_note-a-1">[1]</a></span> A2 <span about="#mwt4" class="reference" data-mw='{"name":"ref","attrs":{"name":"a"}}' id="cite_ref-a-1-1" rel="dc:references" typeof="mw:Extension/ref"><a href="#cite_note-a-1">[1]</a></span>
 B1 <span about="#mwt7" class="reference" data-mw='{"name":"ref","attrs":{"name":"b"}}' id="cite_ref-b-2-0" rel="dc:references" typeof="mw:Extension/ref"><a href="#cite_note-b-2">[2]</a></span> B2 <span about="#mwt8" class="reference" data-mw='{"name":"ref","body":{"html":"bar"},"attrs":{"name":"b"}}' id="cite_ref-b-2-1" rel="dc:references" typeof="mw:Extension/ref"><a href="#cite_note-b-2">[2]</a></span></p>
 
@@ -17719,11 +17463,11 @@ B1 <span about="#mwt7" class="reference" data-mw='{"name":"ref","attrs":{"name":
 Ref: 16. Tokenizer should accept non-standard whitespace in <ref> and </ref> tags
 !!options
 parsoid=wt2html
-!!input
+!! wikitext
 A <ref >foo</ref >
 
 <references />
-!!result
+!! html
 <p>A <span class="reference" data-mw='{"name":"ref","body":{"html":"foo"},"attrs":{}}' id="cite_ref-1-0" rel="dc:references" typeof="mw:Extension/ref"><a href="#cite_note-1">[1]</a></span></p>
 
 <ol class="references" typeof="mw:Extension/references" data-mw='{"name":"references","attrs":{}}'>
@@ -17734,9 +17478,9 @@ A <ref >foo</ref >
 References: 1. references tag without any refs should be handled properly
 !!options
 parsoid
-!!input
+!! wikitext
 <references />
-!!result
+!! html
 <ol about="#mwt2" class="references" typeof="mw:Extension/references" data-mw='{"name":"references","attrs":{}}'></ol>
 !!end
 
@@ -17744,12 +17488,12 @@ parsoid
 References: 2. references tag with group only outputs references from that group
 !!options
 parsoid
-!!input
+!! wikitext
 A <ref group="a">foo</ref>
 B <ref group="b">bar</ref>
 
 <references group="a" />
-!!result
+!! html
 <p>A <span about="#mwt2" class="reference" data-mw='{"name":"ref","body":{"html":"foo"},"attrs":{"group":"a"}}' id="cite_ref-1-0" rel="dc:references" typeof="mw:Extension/ref"><a href="#cite_note-1">[a 1]</a></span>
 B <span about="#mwt4" class="reference" data-mw='{"name":"ref","body":{"html":"bar"},"attrs":{"group":"b"}}' id="cite_ref-2-0" rel="dc:references" typeof="mw:Extension/ref"><a href="#cite_note-2">[b 1]</a></span></p>
 
@@ -17761,7 +17505,7 @@ B <span about="#mwt4" class="reference" data-mw='{"name":"ref","body":{"html":"b
 References: 3. ref list should be cleared after processing references
 !!options
 parsoid
-!!input
+!! wikitext
 A <ref>foo</ref>
 
 <references />
@@ -17769,7 +17513,7 @@ A <ref>foo</ref>
 B <ref>bar</ref>
 
 <references />
-!!result
+!! html
 <p>A <span about="#mwt2" class="reference" data-mw='{"name":"ref","body":{"html":"foo"},"attrs":{}}' id="cite_ref-1-0" rel="dc:references" typeof="mw:Extension/ref"><a href="#cite_note-1">[1]</a></span></p>
 
 <ol about="#mwt4" class="references" typeof="mw:Extension/references" data-mw='{"name":"references","attrs":{}}'><li about="#cite_note-1" id="cite_note-1"><span rel="mw:referencedBy"><a href="#cite_ref-1-0">↑</a></span> foo</li>
@@ -17785,7 +17529,7 @@ B <ref>bar</ref>
 References: 4. only referenced group should be cleared after processing references
 !!options
 parsoid
-!!input
+!! wikitext
 A <ref group="a">afoo</ref>
 B <ref>bfoo</ref>
 
@@ -17794,7 +17538,7 @@ B <ref>bfoo</ref>
 C <ref>cfoo</ref>
 
 <references />
-!!result
+!! html
 <p>A <span about="#mwt2" class="reference" data-mw='{"name":"ref","body":{"html":"afoo"},"attrs":{"group":"a"}}' id="cite_ref-1-0" rel="dc:references" typeof="mw:Extension/ref"><a href="#cite_note-1">[a 1]</a></span>
 B <span about="#mwt4" class="reference" data-mw='{"name":"ref","body":{"html":"bfoo"},"attrs":{}}' id="cite_ref-2-0" rel="dc:references" typeof="mw:Extension/ref" data-parsoid='{"src":"<ref>bfoo</ref>"}'><a href="#cite_note-2">[1]</a></span></p>
 
@@ -17811,7 +17555,7 @@ B <span about="#mwt4" class="reference" data-mw='{"name":"ref","body":{"html":"b
 References: 5. ref tags in references should be processed while ignoring all other content
 !!options
 parsoid
-!!input
+!! wikitext
 A <ref name="a" />
 B <ref name="b">bar</ref>
 
@@ -17819,7 +17563,7 @@ B <ref name="b">bar</ref>
 <ref name="a">foo</ref>
 This should just get lost.
 </references>
-!!result
+!! html
 <p>A <span about="#mwt2" class="reference" data-mw='{"name":"ref","attrs":{"name":"a"}}' id="cite_ref-a-1-0" rel="dc:references" typeof="mw:Extension/ref" data-parsoid='{"src":"&lt;ref name=\"a\" />"}'><a href="#cite_note-a-1">[1]</a></span>
 B <span about="#mwt4" class="reference" data-mw='{"name":"ref","body":{"html":"bar"},"attrs":{"name":"b"}}' id="cite_ref-b-2-0" rel="dc:references" typeof="mw:Extension/ref" data-parsoid='{"src":"&lt;ref name=\"b\">bar&lt;/ref>"}'><a href="#cite_note-b-2">[2]</a></span></p>
 
@@ -17834,9 +17578,9 @@ B <span about="#mwt4" class="reference" data-mw='{"name":"ref","body":{"html":"b
 References: 6. <references /> from a transclusion
 !!options
 parsoid
-!!input
+!! wikitext
 <ref>Foo</ref> {{echo|<references />}}
-!!result
+!! html
 <span about="#mwt3" class="reference" data-mw='{"name":"ref","body":{"html":"Foo"},"attrs":{}}' id="cite_ref-1-0" rel="dc:references" typeof="mw:Extension/ref"><a href="#cite_note-1">[1]</a></span> <ol class="references" typeof="mw:Extension/references mw:Transclusion" about="#mwt4" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"&lt;references />"}},"i":0}}]}'><li about="#cite_note-1" id="cite_note-1"><span rel="mw:referencedBy"><a href="#cite_ref-1-0">↑</a></span> Foo</li></ol>
 !!end
 
@@ -17844,28 +17588,22 @@ parsoid
 References: 7. Multiple references tags (one without and one with nested refs) should be correctly handled
 !! options
 parsoid
-!! input
+!! wikitext
 A <ref>foo bar for a</ref>
-B <ref name="b" />
+B <ref group="X" name="b" />
 
 <references />
 
-<references>
+<references group="X">
 <ref name="b">foo</ref>
 </references>
-!! result
-<p>A <span about="#mwt2" class="reference" data-mw='{"name":"ref","body":{"html":"foo bar for a"},"attrs":{}}' id="cite_ref-1-0" rel="dc:references" typeof="mw:Extension/ref" data-parsoid='{"src":"&lt;ref>foo bar for a&lt;/ref>"}'><a href="#cite_note-1">[1]</a></span>
-B <span about="#mwt4" class="reference" data-mw='{"name":"ref","attrs":{"name":"b"}}' id="cite_ref-b-2-0" rel="dc:references" typeof="mw:Extension/ref" data-parsoid='{"src":"&lt;ref name=\"b\" />"}'><a href="#cite_note-b-2">[2]</a></span></p>
-
-
-<ol class="references" typeof="mw:Extension/references" about="#mwt6" data-parsoid='{"src":"&lt;references />"}' data-mw='{"name":"references","attrs":{}}'>
-<li about="#cite_note-1" id="cite_note-1" data-parsoid="{}"><span rel="mw:referencedBy"><a href="#cite_ref-1-0">↑</a></span> foo bar for a</li>
-<li about="#cite_note-b-2" id="cite_note-b-2" data-parsoid="{}"><span rel="mw:referencedBy"><a href="#cite_ref-b-2-0">↑</a></span> </li></ol>
+!! html
+<p>A <span about="#mwt2" class="reference" data-mw='{"name":"ref","body":{"html":"foo bar for a"},"attrs":{}}' id="cite_ref-2-0" rel="dc:references" typeof="mw:Extension/ref" data-parsoid='{"src":"&lt;ref>foo bar for a&lt;/ref>"}'><a href="#cite_note-2" data-parsoid="{}">[2]</a></span>
+B <span about="#mwt4" class="reference" data-mw='{"name":"ref","attrs":{"group":"X","name":"b"}}' id="cite_ref-b-3-0" rel="dc:references" typeof="mw:Extension/ref" data-parsoid='{"src":"&lt;ref name=\"b\" group=\"X\" />"}'><a href="#cite_note-b-3" data-parsoid="{}">[X 1]</a></span></p>
 
+<ol class="references" typeof="mw:Extension/references" about="#mwt6" data-parsoid='{"src":"&lt;references />"}' data-mw='{"name":"references","attrs":{}}'><li about="#cite_note-b-1" id="cite_note-b-1" data-parsoid="{}"><span rel="mw:referencedBy" data-parsoid="{}">↑</span> foo</li><li about="#cite_note-2" id="cite_note-2" data-parsoid="{}"><span rel="mw:referencedBy" data-parsoid="{}"><a href="#cite_ref-2-0" data-parsoid="{}">↑</a></span> foo bar for a</li></ol>
 
-<ol class="references" typeof="mw:Extension/references" about="#mwt8" data-parsoid='{"src":"&lt;references>\n&lt;ref name=\"b\">foo&lt;/ref>\n&lt;/references>"}' data-mw='{"name":"references","body":{"extsrc":"&lt;ref name=\"b\">foo&lt;/ref>","html":"\n&lt;span about=\"#mwt10\" class=\"reference\" data-mw=&#39;{\"name\":\"ref\",\"body\":{\"html\":\"foo\"},\"attrs\":{\"name\":\"b\"}}&#39; rel=\"dc:references\" typeof=\"mw:Extension/ref\">&lt;a href=\"#cite_note-b-3\">[1]&lt;/a>&lt;/span>\n"},"attrs":{}}'>
-<li about="#cite_note-b-3" id="cite_note-b-3" data-parsoid="{}"><span rel="mw:referencedBy">↑</span> foo</li>
-</ol>
+<ol class="references" typeof="mw:Extension/references" about="#mwt8" data-parsoid='{"src":"&lt;references group=\"X\">\n&lt;ref name=\"b\">foo&lt;/ref>\n&lt;/references>","group":"X"}' data-mw='{"name":"references","body":{"extsrc":"&lt;ref name=\"b\">foo&lt;/ref>","html":"\n&lt;span about=\"#mwt10\" class=\"reference\" data-mw=&#39;{\"name\":\"ref\",\"body\":{\"html\":\"foo\"},\"attrs\":{\"name\":\"b\"}}&#39; rel=\"dc:references\" typeof=\"mw:Extension/ref\">&lt;a href=\"#cite_note-b-1\">[1]&lt;/a>&lt;/span>\n"},"attrs":{"group":"X"}}'><li about="#cite_note-b-3" id="cite_note-b-3" data-parsoid="{}"><span rel="mw:referencedBy" data-parsoid="{}"><a href="#cite_ref-b-3-0" data-parsoid="{}">↑</a></span> </li></ol>
 !! end
 
 # This test is wt2html only because we're permitting the serializer to produce
@@ -17874,11 +17612,11 @@ B <span about="#mwt4" class="reference" data-mw='{"name":"ref","attrs":{"name":"
 Generate references for unclosed references tag
 !! options
 parsoid=wt2html
-!! input
+!! wikitext
 a<ref>foo</ref>
 
 <references>
-!! result
+!! html
 <p data-parsoid='{}'>a<span about="#mwt2" class="reference" data-mw='{"name":"ref","body":{"html":"foo"},"attrs":{}}' id="cite_ref-1-0" rel="dc:references" typeof="mw:Extension/ref" data-parsoid='{"src":"&lt;ref>foo&lt;/ref>"}'><a href="#cite_note-1" data-parsoid="{}">[1]</a></span></p>
 
 
@@ -17890,10 +17628,10 @@ a<ref>foo</ref>
 New reference serializes on its own line
 !! options
 parsoid=wt2wt,html2wt
-!! input
+!! wikitext
 foo
 <references />
-!! result
+!! html
 foo<ol class="references" typeof="mw:Extension/references" about="#mwt2" data-mw='{"name":"references","attrs":{}}'></ol>
 !! end
 
@@ -17923,7 +17661,7 @@ foo<ol class="references" typeof="mw:Extension/references" about="#mwt2" data-mw
 Headings: 0. Unnested
 !! options
 parsoid
-!! input
+!! wikitext
 <nowiki>=foo=</nowiki>
 
 <nowiki> =foo= </nowiki>
@@ -17931,7 +17669,7 @@ parsoid
 <nowiki>=foo=</nowiki>
 
 =foo''a''<nowiki>=</nowiki>
-!! result
+!! html
 <p><span typeof="mw:Nowiki">=foo=</span></p>
 
 <p><span typeof="mw:Nowiki"> =foo= </span>
@@ -17946,7 +17684,7 @@ Headings: 1. Nested inside html
 (New headings and existing headings are handled differently)
 !! options
 parsoid=html2wt
-!! input
+!! wikitext
 = =foo= =
 
 == =foo= ==
@@ -17960,7 +17698,7 @@ parsoid=html2wt
 =====<nowiki>=foo=</nowiki>=====
 ======<nowiki>=foo=</nowiki>======
 
-!! result
+!! html
 <h1>=foo=</h1>
 <h2>=foo=</h2>
 <h3>=foo=</h3>
@@ -17977,7 +17715,7 @@ parsoid=html2wt
 Headings: 2. Outside heading nest on a single line <h1>foo</h1>*bar
 !! options
 parsoid=html2wt
-!! input
+!! wikitext
 = foo =
 <nowiki>*</nowiki>bar
 
@@ -17986,7 +17724,7 @@ parsoid=html2wt
 
 = foo =
 <nowiki>=bar=</nowiki>
-!! result
+!! html
 <h1>foo</h1>*bar
 <h1>foo</h1>=bar
 <h1>foo</h1>=bar=
@@ -17996,9 +17734,9 @@ parsoid=html2wt
 Headings: 3. Nested inside html with wikitext split by html tags
 !! options
 parsoid=html2wt
-!! input
+!! wikitext
 = ='''bold'''<nowiki>foo=</nowiki> =
-!! result
+!! html
 <h1>=<b>bold</b><span typeof="mw:Nowiki">foo=</span></h1>
 !!end
 
@@ -18006,7 +17744,7 @@ parsoid=html2wt
 Headings: 4a. No escaping needed (testing just h1 and h2)
 !! options
 parsoid=html2wt
-!! input
+!! wikitext
 = =foo =
 
 = foo= =
@@ -18022,7 +17760,7 @@ parsoid=html2wt
 = ''=''foo= =
 
 = <nowiki>=</nowiki> =
-!! result
+!! html
 <h1>=foo</h1>
 <h1>foo=</h1>
 <h1> =foo= </h1>
@@ -18037,11 +17775,11 @@ parsoid=html2wt
 Headings: 4b. No escaping needed (inside p-tags)
 !! options
 parsoid=html2wt
-!! input
+!! wikitext
 ===
 =foo= x
 =foo= <s></s>
-!! result
+!! html
 <p>===
 =foo= x
 =foo= <s></s>
@@ -18052,7 +17790,7 @@ parsoid=html2wt
 Headings: 5. Empty headings
 !! options
 parsoid
-!! input
+!! wikitext
 =<nowiki/>=
 
 ==<nowiki/>==
@@ -18064,7 +17802,7 @@ parsoid
 =====<nowiki/>=====
 
 ======<nowiki/>======
-!! result
+!! html
 <h1></h1>
 <h2></h2>
 <h3></h3>
@@ -18077,7 +17815,7 @@ parsoid
 Headings: 6a. Heading chars in SOL context (with trailing spaces)
 !! options
 parsoid
-!! input
+!! wikitext
 <nowiki>=a=</nowiki>
 
 <nowiki>=a=</nowiki> 
@@ -18085,7 +17823,7 @@ parsoid
 <nowiki>=a=</nowiki>   
 
 <nowiki>=a=</nowiki>   
-!! result
+!! html
 <p>=a=</p>
 <p>=a= </p>
 <p>=a= </p>
@@ -18096,7 +17834,7 @@ parsoid
 Headings: 6b. Heading chars in SOL context (with trailing newlines)
 !! options
 parsoid
-!! input
+!! wikitext
 <nowiki>=a=
 b</nowiki>
 
@@ -18108,7 +17846,7 @@ b</nowiki>
 
 <nowiki>=a=     
 b</nowiki>
-!! result
+!! html
 <p>=a=
 b</p>
 <p>=a= 
@@ -18124,10 +17862,10 @@ b</p>
 Headings: 6c. Heading chars in SOL context (leading newline break)
 !! options
 parsoid
-!! input
+!! wikitext
 a
 <nowiki>=b=</nowiki>
-!! result
+!! html
 <p>a
 =b=</p>
 !!end
 Headings: 6d. Heading chars in SOL context (with interspersed comments)
 !! options
 parsoid
-!! input
+!! wikitext
 <!--c0--><nowiki>=a=</nowiki>
 
 <!--c1--><nowiki>=a=</nowiki> <!--c2-->         <!--c3-->
-!! result
+!! html
 <p><!--c0-->=a=</p>
 <p><!--c1-->=a= <!--c2-->       <!--c3--></p>
 !!end
@@ -18149,9 +17887,9 @@ parsoid
 Headings: 6d. Heading chars in SOL context (No escaping needed)
 !! options
 parsoid=html2wt
-!! input
+!! wikitext
 =a=<div>b</div>
-!! result
+!! html
 =a=<div>b</div>
 !!end
 
@@ -18168,11 +17906,11 @@ parsoid=html2wt
 
 !! test
 Lists: 0. Outside nests
-!! input
+!! wikitext
 <nowiki>*</nowiki>foo
 
 <nowiki>#</nowiki>foo
-!! result
+!! html
 <p>*foo
 </p><p>#foo
 </p>
@@ -18180,7 +17918,7 @@ Lists: 0. Outside nests
 
 !! test
 Lists: 1. Nested inside html
-!! input
+!! wikitext
 *<nowiki>*foo</nowiki>
 
 *<nowiki>#foo</nowiki>
@@ -18196,7 +17934,7 @@ Lists: 1. Nested inside html
 #<nowiki>:foo</nowiki>
 
 #<nowiki>;foo</nowiki>
-!! result
+!! html
 <ul>
 <li>*foo
 </li>
@@ -18234,7 +17972,7 @@ Lists: 1. Nested inside html
 
 !! test
 Lists: 2. Inside definition lists
-!! input
+!! wikitext
 ;<nowiki>;foo</nowiki>
 
 ;<nowiki>:foo</nowiki>
@@ -18243,7 +17981,7 @@ Lists: 2. Inside definition lists
 :bar
 
 :<nowiki>:foo</nowiki>
-!! result
+!! html
 <dl>
 <dt>;foo
 </dt>
@@ -18267,11 +18005,11 @@ Lists: 2. Inside definition lists
 
 !! test
 Lists: 3. Only bullets at start of text should be escaped
-!! input
+!! wikitext
 *<nowiki>*foo*bar</nowiki>
 
 *<nowiki>*foo</nowiki>''it''*bar
-!! result
+!! html
 <ul>
 <li>*foo*bar
 </li>
@@ -18287,7 +18025,7 @@ Lists: 3. Only bullets at start of text should be escaped
 Lists: 4. No escapes needed
 !! options
 parsoid
-!! input
+!! wikitext
 *foo*bar
 
 *''foo''*bar
@@ -18295,7 +18033,7 @@ parsoid
 *[[Foo]]: bar
 
 *[[Foo]]*bar
-!! result
+!! html
 <ul>
 <li>foo*bar
 </li>
@@ -18316,7 +18054,7 @@ parsoid
 
 !! test
 Lists: 5. No unnecessary escapes
-!! input
+!! wikitext
 * bar <span><nowiki>[[foo]]</nowiki></span>
 
 *=bar <span><nowiki>[[foo]]</nowiki></span>
@@ -18328,7 +18066,7 @@ Lists: 5. No unnecessary escapes
 *=bar <span>foo]]</span>=
 
 * <s></s>: a
-!! result
+!! html
 <ul>
 <li> bar <span>[[foo]]</span>
 </li>
@@ -18360,18 +18098,18 @@ Lists: 5. No unnecessary escapes
 Lists: 6. Escape bullets in SOL position
 !! options
 parsoid
-!! input
+!! wikitext
 <!--cmt--><nowiki>*foo</nowiki>
-!! result
+!! html
 <p><!--cmt--><span typeof="mw:Nowiki">*foo</span></p>
 !!end
 
 !! test
 Lists: 7. Escape bullets in a multi-line context
-!! input
+!! wikitext
 a
 <nowiki>*</nowiki>b
-!! result
+!! html
 <p>a
 *b
 </p>
 HRs: 1. Single line
 !! options
 parsoid
-!! input
+!! wikitext
 ----<nowiki>----</nowiki>
 ----=foo=
 ----*foo
-!! result
+!! html
 <hr><span typeof="mw:Nowiki">----</span>
 <hr>=foo=
 <hr>*foo
@@ -18416,10 +18154,10 @@ parsoid
 
 !! test
 Tables: 1a. Simple example
-!! input
+!! wikitext
 <nowiki>{|
 |}</nowiki>
-!! result
+!! html
 <p>{|
 |}
 </p>
@@ -18427,27 +18165,27 @@ Tables: 1a. Simple example
 
 !! test
 Tables: 1b. No escaping needed
-!! input
+!! wikitext
 !foo
-!! result
+!! html
 <p>!foo
 </p>
 !! end
 
 !! test
 Tables: 1c. No escaping needed
-!! input
+!! wikitext
 |foo
-!! result
+!! html
 <p>|foo
 </p>
 !! end
 
 !! test
 Tables: 1d. No escaping needed
-!! input
+!! wikitext
 |}foo
-!! result
+!! html
 <p>|}foo
 </p>
 !! end
@@ -18456,13 +18194,13 @@ Tables: 1d. No escaping needed
 Tables: 2a. Nested in td
 !! options
 parsoid=html2wt
-!! input
+!! wikitext
 {|
 |<nowiki>foo|bar</nowiki>
 |-
 |x<div><nowiki>a|b</nowiki></div>
 |}
-!! result
+!! html
 <table><tbody><tr>
 <td>foo|bar</td></tr>
 <tr><td>x<div>a|b</div></td>
@@ -18473,12 +18211,12 @@ parsoid=html2wt
 Tables: 2b. Nested in td
 !! options
 parsoid
-!! input
+!! wikitext
 {|
 |<nowiki>foo||bar</nowiki>
 |''it''<nowiki>foo||bar</nowiki>
 |}
-!! result
+!! html
 <table><tbody><tr>
 <td><span typeof="mw:Nowiki">foo||bar</span></td>
 <td><i>it</i><span typeof="mw:Nowiki">foo||bar</span></td></tr></tbody></table>
@@ -18488,11 +18226,11 @@ parsoid
 Tables: 2c. Nested in td -- no escaping needed
 !! options
 parsoid
-!! input
+!! wikitext
 {|
 |foo!!bar
 |}
-!! result
+!! html
 <table><tbody><tr><td>foo!!bar
 </td></tr></tbody></table>
 
@@ -18502,11 +18240,11 @@ parsoid
 Tables: 3a. Nested in th
 !! options
 parsoid
-!! input
+!! wikitext
 {|
 !foo!bar
 |}
-!! result
+!! html
 <table><tbody><tr><th>foo!bar
 </th></tr></tbody></table>
 
@@ -18516,11 +18254,11 @@ parsoid
 Tables: 3b. Nested in th
 !! options
 parsoid
-!! input
+!! wikitext
 {|
 !<nowiki>foo!!bar</nowiki>
 |}
-!! result
+!! html
 <table>
 <tbody><tr><th><span typeof="mw:Nowiki">foo!!bar</span></th></tr>
 </tbody></table>
@@ -18530,11 +18268,11 @@ parsoid
 Tables: 3c. Nested in th -- no escaping needed
 !! options
 parsoid
-!! input
+!! wikitext
 {|
 !<nowiki>foo||bar</nowiki>
 |}
-!! result
+!! html
 <table><tbody><tr>
 <th><span typeof="mw:Nowiki">foo||bar</span></th></tr></tbody></table>
 !! end
@@ -18543,13 +18281,13 @@ parsoid
 Tables: 4a. Escape -
 !! options
 parsoid
-!! input
+!! wikitext
 {|
 !-bar
 |-
 |<nowiki>-bar</nowiki>
 |}
-!! result
+!! html
 <table><tbody>
 <tr><th>-bar</th></tr>
 <tr>
@@ -18560,13 +18298,13 @@ parsoid
 Tables: 4b. Escape +
 !! options
 parsoid
-!! input
+!! wikitext
 {|
 !+bar
 |-
 |<nowiki>+bar</nowiki>
 |}
-!! result
+!! html
 <table><tbody>
 <tr><th>+bar</th></tr>
 <tr>
@@ -18577,7 +18315,7 @@ parsoid
 Tables: 4c. No escaping needed
 !! options
 parsoid
-!! input
+!! wikitext
 {|
 |foo-bar
 |foo+bar
@@ -18593,7 +18331,7 @@ bar|baz
 |x
 <div>a|b</div>
 |}
-!! result
+!! html
 <table><tbody>
 <tr><td>foo-bar</td><td>foo+bar</td></tr>
 <tr><td><i>foo</i>-bar</td><td><i>foo</i>+bar</td></tr>
@@ -18610,13 +18348,13 @@ bar|baz
 Tables: 4d. No escaping needed
 !! options
 parsoid
-!! input
+!! wikitext
 {|
 |[[Foo]]-bar
 ||+1
 ||-2
 |}
-!! result
+!! html
 <table>
 <tbody><tr><td><a rel="mw:WikiLink" href="./Foo">Foo</a>-bar</td>
 <td data-parsoid='{"startTagSrc":"|","attrSepSrc":"|"}'>+1</td>
@@ -18628,14 +18366,16 @@ parsoid
 Tables: Digest broken attributes on table and tr tag
 !! options
 parsoid=wt2html
-!! input
+!! wikitext
 {| || |} ++
 |- || || ++ --
+|- > [
 |}
-!! result
+!! html
 <table>
 <tbody>
 <tr></tr>
+<tr></tr>
 </tbody></table>
 !! end
 
@@ -18650,9 +18390,9 @@ parsoid=wt2html
 Links 1. Quote marks in link text
 !! options
 parsoid
-!! input
+!! wikitext
 [[Foo|Foo<nowiki>''boo''</nowiki>]]
-!! result
+!! html
 <a rel="mw:WikiLink" href="Foo">Foo''boo''</a>
 !! end
 
@@ -18660,7 +18400,7 @@ parsoid
 Links 2. WikiLinks: Escapes needed
 !! options
 parsoid
-!! input
+!! wikitext
 [[Foo|[Foobar]]]
 [[Foo|<nowiki>Foobar]</nowiki>]]
 [[Foo|x [Foobar] x]]
@@ -18673,7 +18413,7 @@ parsoid
 [[Foo|<nowiki>x [[ y</nowiki>]]
 [[Foo|<nowiki>x ]] y</nowiki>]]
 [[Foo|<nowiki>x ]] y [[ z</nowiki>]]
-!! result
+!! html
 <a href="Foo" rel="mw:WikiLink">[Foobar]</a>
 <a href="Foo" rel="mw:WikiLink">Foobar]</a>
 <a href="Foo" rel="mw:WikiLink">x [Foobar] x</a>
@@ -18692,10 +18432,10 @@ parsoid
 Links 3. WikiLinks: No escapes needed
 !! options
 parsoid
-!! input
+!! wikitext
 [[Foo|[Foobar]]
 [[Foo|foo|bar]]
-!! result
+!! html
 <a href="Foo" rel="mw:WikiLink">[Foobar</a>
 <a href="Foo" rel="mw:WikiLink">foo|bar</a>
 !! end
@@ -18704,7 +18444,7 @@ parsoid
 Links 4. ExtLinks: Escapes needed
 !! options
 parsoid
-!! input
+!! wikitext
 [http://google.com <nowiki>[google]</nowiki>]
 [http://google.com <nowiki>google]</nowiki>]
 
@@ -18712,7 +18452,7 @@ parsoid
 
 <nowiki>[http://google.com google]</nowiki>
 
-!! result
+!! html
 <p><a href="http://google.com" rel="mw:ExtLink">[google]</a>
 <a href="http://google.com" rel="mw:ExtLink">google]</a></p>
 <p>[http://google.com]</p>
@@ -18723,9 +18463,9 @@ parsoid
 Links 5. ExtLinks: No escapes needed
 !! options
 parsoid
-!! input
+!! wikitext
 [http://google.com [google]
-!! result
+!! html
 <a href="http://google.com" rel="mw:ExtLink">[google</a>
 !! end
 
@@ -18739,7 +18479,7 @@ parsoid
 1. Quotes inside <b> and <i>
 !! options
 parsoid=html2wt,wt2wt
-!! input
+!! wikitext
 ''<nowiki>'foo'</nowiki>''
 ''<nowiki>''foo''</nowiki>''
 ''<nowiki>'''foo'''</nowiki>''
@@ -18757,7 +18497,7 @@ parsoid=html2wt,wt2wt
 '<nowiki/>'''foo'''<nowiki/>'
 ''fools'<span> errand</span>''
 ''<span>fool</span>'s errand''
-!! result
+!! html
 <p><i>'foo'</i>
 <i>''foo''</i>
 <i>'''foo'''</i>
@@ -18779,11 +18519,11 @@ parsoid=html2wt,wt2wt
 
 !! test
 2. Link fragments separated by <i> and <b> tags
-!! input
+!! wikitext
 [[''foo''<nowiki>hello]]</nowiki>
 
 [['''foo'''<nowiki>hello]]</nowiki>
-!! result
+!! html
 <p>[[<i>foo</i>hello]]
 </p><p>[[<b>foo</b>hello]]
 </p>
@@ -18793,11 +18533,11 @@ parsoid=html2wt,wt2wt
 3. Link fragments inside <i> and <b>
 (FIXME: Escaping one or both of [[ and ]] is also acceptable --
  this is one of the shortcomings of this format)
-!! input
+!! wikitext
 ''[[foo''<nowiki>]]</nowiki>
 
 '''[[foo'''<nowiki>]]</nowiki>
-!! result
+!! html
 <p><i>[[foo</i>]]
 </p><p><b>[[foo</b>]]
 </p>
@@ -18805,10 +18545,10 @@ parsoid=html2wt,wt2wt
 
 !! test
 4. No escaping needed
-!! input
+!! wikitext
 '<span>''bar''</span>'
 '<span>'''bar'''</span>'
-!! result
+!! html
 <p>'<span><i>bar</i></span>'
 '<span><b>bar</b></span>'
 </p>
@@ -18820,7 +18560,7 @@ parsoid=html2wt,wt2wt
 
 !! test
 1. No unnecessary escapes
-!! input
+!! wikitext
 bar <span><nowiki>[[foo]]</nowiki></span>
 
 =bar <span><nowiki>[[foo]]</nowiki></span>
@@ -18830,7 +18570,7 @@ bar <span><nowiki>[[foo]]</nowiki></span>
 ]]bar <span><nowiki>[[foo]]</nowiki></span>
 
 =bar <span>foo]]</span><nowiki>=</nowiki>
-!! result
+!! html
 <p>bar <span>[[foo]]</span>
 </p><p>=bar <span>[[foo]]</span>
 </p><p>[[bar <span>[[foo]]</span>
@@ -18846,7 +18586,7 @@ bar <span><nowiki>[[foo]]</nowiki></span>
 1. Leading whitespace in SOL context should be escaped
 !! options
 parsoid
-!! input
+!! wikitext
 <nowiki> </nowiki>a
 
 <nowiki> </nowiki> a
 
 a
 <nowiki>       </nowiki> b
-!! result
+!! html
 <p> a</p>
 <p>  a</p>
 <p>    a(tab)</p>
 1. Valid behavior switches should be escaped
 !! options
 parsoid=html2wt
-!! input
+!! wikitext
 <nowiki>__TOC__</nowiki>
-!! result
+!! html
 __TOC__
 !! end
 
@@ -18894,10 +18634,10 @@ __TOC__
 2. Invalid behavior switches should not be escaped
 !! options
 parsoid=html2wt
-!! input
+!! wikitext
 __TOO__
 __|__
-!! result
+!! html
 __TOO__
 __|__
 !! end
@@ -18912,18 +18652,18 @@ __|__
 1. a tags
 !! options
 parsoid
-!! input
+!! wikitext
 <a href="http://google.com">google</a>
-!! result
+!! html
 &lt;a href=&quot;http://google.com&quot;&gt;google&lt;/a&gt;
 !! end
 
 !! test
 2. other tags
-!! input
+!! wikitext
 <nowiki><div>foo</div>
 <div style="color:red">foo</div></nowiki>
-!! result
+!! html
 <p>&lt;div&gt;foo&lt;/div&gt;
 &lt;div style=&quot;color:red&quot;&gt;foo&lt;/div&gt;
 </p>
@@ -18931,11 +18671,11 @@ parsoid
 
 !! test
 3. multi-line html tag
-!! input
+!! wikitext
 <nowiki><div
 >foo</div
 ></nowiki>
-!! result
+!! html
 <p>&lt;div
 &gt;foo&lt;/div
 &gt;
@@ -18944,13 +18684,13 @@ parsoid
 
 !! test
 4. extension tags
-!! input
+!! wikitext
 <nowiki><ref>foo</ref></nowiki>
 
 <nowiki><ref>bar</nowiki>
 
 baz<nowiki></ref></nowiki>
-!! result
+!! html
 <p>&lt;ref&gt;foo&lt;/ref&gt;
 </p><p>&lt;ref&gt;bar
 </p><p>baz&lt;/ref&gt;
@@ -18960,9 +18700,9 @@ baz<nowiki></ref></nowiki>
 #### --------------- Others ---------------
 !! test
 Escaping nowikis
-!! input
+!! wikitext
 &lt;nowiki&gt;foo&lt;/nowiki&gt;
-!! result
+!! html
 <p>&lt;nowiki&gt;foo&lt;/nowiki&gt;
 </p>
 !! end
@@ -18972,16 +18712,16 @@ Escaping nowikis
 (Bug 52035) Nowiki-escaping should not get tripped by " :" in text
 !! options
 parsoid=wt2wt,html2wt
-!! input
+!! wikitext
 foo's bar :
-!! result
+!! html
 <p>foo's bar :</p>
 !! end
 
 !! test
 
 Tag-like HTML structures are passed through as text
-!! input
+!! wikitext
 <x y>
 
 <x.y>
@@ -18995,7 +18735,7 @@ x<y
 a>b
 
 1<d e>f
-!! result
+!! html
 <p>&lt;x y&gt;
 </p><p>&lt;x.y&gt;
 </p><p>&lt;x-y&gt;
@@ -19011,36 +18751,36 @@ a>b
 # https://bugzilla.wikimedia.org/show_bug.cgi?id=17663)
 !! test
 Tag names followed by punctuation should not be recognized as tags
-!! input
+!! wikitext
 <s.ome> text
-!! result
+!! html
 <p>&lt;s.ome&gt; text
 </p>
 !! end
 
 !! test
 HTML tag with necessary entities in attributes
-!! input
+!! wikitext
 <span title="&amp;amp;">foo</span>
-!! result
+!! html
 <p><span title="&amp;amp;">foo</span>
 </p>
 !! end
 
 !! test
 HTML tag with 'unnecessary' entity encoding in attributes
-!! input
+!! wikitext
 <span title="&amp;">foo</span>
-!! result
+!! html
 <p><span title="&amp;">foo</span>
 </p>
 !! end
 
 !! test
 HTML tag with broken attribute value quoting
-!! input
+!! wikitext
 <span title="Hello world>Foo</span>
-!! result
+!! html
 <p><span>Foo</span>
 </p>
 !! end
@@ -19049,20 +18789,20 @@ HTML tag with broken attribute value quoting
 Parsoid-only: HTML tag with broken attribute value quoting
 !! options
 parsoid
-!! input
+!! wikitext
 <span title="Hello world>Foo</span>
-!! result
+!! html
 <p><span title="Hello world">Foo</span>
 </p>
 !! end
 
 !! test
 Table with broken attribute value quoting
-!! input
+!! wikitext
 {|
 | title="Hello world|Foo
 |}
-!! result
+!! html
 <table>
 <tr>
 <td>Foo
@@ -19072,12 +18812,12 @@ Table with broken attribute value quoting
 
 !! test
 Table with broken attribute value quoting on consecutive lines
-!! input
+!! wikitext
 {|
 | title="Hello world|Foo
 | style="color:red|Bar
 |}
-!! result
+!! html
 <table>
 <tr>
 <td>Foo
@@ -19091,12 +18831,12 @@ Table with broken attribute value quoting on consecutive lines
 Parsoid-only: Table with broken attribute value quoting on consecutive lines
 !! options
 parsoid
-!! input
+!! wikitext
 {|
 | title="Hello world|Foo
 | style="color:red|Bar
 |}
-!! result
+!! html
 <table><tbody>
 <tr>
 <td title="Hello world">Foo
@@ -19109,9 +18849,9 @@ parsoid
 Parsoid-only: Don't wrap broken template tags in <nowiki> on wt2wt (Bug 42353)
 !! options
 parsoid
-!! input
+!! wikitext
 {{}}
-!! result
+!! html
 {{}}
 !! end
 
@@ -19119,19 +18859,19 @@ parsoid
 Parsoid-only: Don't wrap broken template tags in <nowiki> on wt2wt (Bug 42353)
 !! options
 parsoid
-!! input
+!! wikitext
 }}{{
-!! result
+!! html
 }}{{
 !! end
 
 !!test
 Accept empty td cell attribute
-!!input
+!! wikitext
 {|
 | align="center" | foo ||  |
 |}
-!!result
+!! html
 <table>
 <tr>
 <td align="center"> foo </td>
@@ -19142,11 +18882,11 @@ Accept empty td cell attribute
 
 !!test
 Non-empty attributes in th-cells
-!!input
+!! wikitext
 {|
 ! Foo !! style="color: red" | Bar
 |}
-!!result
+!! html
 <table>
 <tr>
 <th> Foo </th>
@@ -19157,11 +18897,11 @@ Non-empty attributes in th-cells
 
 !!test
 Accept empty attributes in th-cells
-!!input
+!! wikitext
 {|
 !| foo !!| bar
 |}
-!!result
+!! html
 <table>
 <tr>
 <th> foo </th>
@@ -19172,14 +18912,14 @@ Accept empty attributes in th-cells
 
 !!test
 Empty table rows go away
-!!input
+!! wikitext
 {|
 | Hello
 | there
 |- class="foo"
 |-
 |}
-!! result
+!! html
 <table>
 <tr>
 <td> Hello
@@ -19199,11 +18939,11 @@ Empty table rows go away
 
 !!test
 RT-ed inter-element separators should be valid separators
-!!input
+!! wikitext
 {|
 |- [[foo]]
 |}
-!!result
+!! html
 <table>
 
 </table>
@@ -19215,7 +18955,7 @@ Trailing newlines in a deep dom-subtree that ends a wikitext line should be migr
 (Parsoid-only since PHP parser relies on Tidy for correct output)
 !!options
 parsoid
-!!input
+!! wikitext
 {|
 |<small>foo
 bar
@@ -19224,18 +18964,18 @@ bar
 {|
 |<small>foo<small>
 |}
-!!result
+!! html
 !!end
 
 !!test
 Empty TD followed by TD with tpl-generated attribute
-!!input
+!! wikitext
 {|
 |-
 |
 |{{echo|style='color:red'}}|foo
 |}
-!!result
+!! html
 <table>
 
 <tr>
@@ -19248,13 +18988,13 @@ Empty TD followed by TD with tpl-generated attribute
 
 !!test
 Indented table with an empty td
-!!input
+!! wikitext
  {|
  |-
  |
  |foo
  |}
-!!result
+!! html
 <table>
 
 <tr>
@@ -19270,12 +19010,12 @@ Empty TR followed by a template-generated TR
 (Parsoid-specific since PHP parser doesn't handle this mixed tbl-wikitext)
 !!options
 parsoid
-!!input
+!! wikitext
 {|
 |-
 {{echo|<tr><td>foo</td></tr>}}
 |}
-!!result
+!! html
 <table>
 <tbody>
 <tr></tr>
@@ -19290,14 +19030,14 @@ parsoid
 Empty TR followed by mixed-ws-comment line should RT correctly
 !!options
 parsoid
-!!input
+!! wikitext
 {|
 |-
  <!--c-->
 |-
 <!--c--> <!--d-->
 |}
-!!result
+!! html
 <table>
 <tbody>
 <tr></tr>
@@ -19312,10 +19052,10 @@ parsoid
 Multi-line image caption generated by templates with/without trailing newlines
 !!options
 parsoid
-!!input
+!! wikitext
 [[File:foo.jpg|thumb|300px|foo\n{{echo|A}}\n{{echo|B}}\n{{echo|C}}]]
 [[File:foo.jpg|thumb|300px|foo\n{{echo|A}}\n{{echo|B}}\n{{echo|C}}\n\n]]
-!!result
+!! html
 <div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/index.php?title=Special:Upload&amp;wpDestFile=Foo.jpg" class="new" title="File:Foo.jpg">File:Foo.jpg</a>  <div class="thumbcaption">foo\nA\nB\nC</div></div></div>
 <div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/index.php?title=Special:Upload&amp;wpDestFile=Foo.jpg" class="new" title="File:Foo.jpg">File:Foo.jpg</a>  <div class="thumbcaption">foo\nA\nB\nC\n\n</div></div></div>
 
@@ -19327,10 +19067,10 @@ parsoid
 Improperly nested inline or quotes tags with whitespace in between
 !!options
 parsoid
-!!input
+!! wikitext
 <span> <s>x</span> </s>
 ''' ''x''' ''
-!!result
+!! html
 <p><span> <s>x</s></span><s> </s>
 <b> <i>x</i></b><i> </i>
 </p>
@@ -19340,9 +19080,9 @@ parsoid
 Encapsulate protected attributes from wt
 !!options
 parsoid
-!!input
+!! wikitext
 <div typeof="mw:placeholder stuff" data-parsoid="weird" data-parsoid-other="no" about="time" rel="mw:true">foo</div>
-!!result
+!! html
 <body><div data-x-typeof="mw:placeholder stuff" data-x-data-parsoid="weird" data-x-data-parsoid-other="no" data-x-about="time" data-x-rel="mw:true">foo</div>
 </body>
 !!end
@@ -19354,9 +19094,9 @@ parsoid
 Ensure ParagraphWrapper can deal with stray closing pre tags
 !!options
 parsoid=wt2html
-!!input
+!! wikitext
 plain text</pre>
-!!result
+!! html
 plain text
 !!end
 
@@ -19364,9 +19104,9 @@ plain text
 1. Ensure fostered text content is wrapped in spans
 !!options
 parsoid=wt2html
-!!input
+!! wikitext
 <table>hi</table><table>ho</table>
-!!result
+!! html
 <span>hi</span>
 <table></table>
 <span>ho</span>
@@ -19377,12 +19117,12 @@ parsoid=wt2html
 2. Ensure fostered text content is wrapped in spans (traps regressions around fostered marker on the span getting lost)
 !!options
 parsoid=wt2html,wt2wt
-!!input
+!! wikitext
 <table>
 <tr> || ||
 <td> a
 </table>
-!!result
+!! html
 <span> || ||</span>
 <table>
 <tbody>
@@ -19395,9 +19135,9 @@ parsoid=wt2html,wt2wt
 Encapsulation properly handles null DSR information from foster box
 !!options
 parsoid=wt2html,wt2wt
-!!input
+!! wikitext
 {{echo|<table>foo<tr><td>bar</td></tr></table>}}
-!!result
+!! html
 <span typeof="mw:Transclusion" data-mw="{&quot;parts&quot;:[{&quot;template&quot;:{&quot;target&quot;:{&quot;wt&quot;:&quot;echo&quot;,&quot;href&quot;:&quot;./Template:Echo&quot;},&quot;params&quot;:{&quot;1&quot;:{&quot;wt&quot;:&quot;
 <table>foo
 <tr>
@@ -19412,9 +19152,9 @@ parsoid=wt2html,wt2wt
 1. Encapsulate foster-parented transclusion content
 !!options
 parsoid=wt2wt,wt2html
-!!input
+!! wikitext
 <table>{{echo|foo<tr><td>bar</td></tr>}}</table>
-!!result
+!! html
 <span typeof="mw:Transclusion" data-mw="{&quot;parts&quot;:[&quot;
 <table>&quot;,{&quot;template&quot;:{&quot;target&quot;:{&quot;wt&quot;:&quot;echo&quot;,&quot;href&quot;:&quot;./Template:Echo&quot;},&quot;params&quot;:{&quot;1&quot;:{&quot;wt&quot;:&quot;foo
 <tr>
@@ -19429,9 +19169,9 @@ parsoid=wt2wt,wt2html
 2. Encapsulate foster-parented transclusion content
 !!options
 parsoid=wt2wt,wt2html
-!!input
+!! wikitext
 <table><div>{{echo|foo}}</div><tr><td>bar</td></tr></table>
-!!result
+!! html
 <div typeof="mw:Transclusion" data-mw="{&quot;parts&quot;:[&quot;
 <table>
 <div>&quot;,{&quot;template&quot;:{&quot;target&quot;:{&quot;wt&quot;:&quot;echo&quot;,&quot;href&quot;:&quot;./Template:Echo&quot;},&quot;params&quot;:{&quot;1&quot;:{&quot;wt&quot;:&quot;foo&quot;}},&quot;i&quot;:0}},&quot;</div>
@@ -19447,9 +19187,9 @@ parsoid=wt2wt,wt2html
 3. Encapsulate foster-parented transclusion content
 !!options
 parsoid=wt2wt,wt2html
-!!input
+!! wikitext
 <table><div><p>{{echo|foo</p></div><tr><td>}}bar</td></tr></table>
-!!result
+!! html
 <div typeof="mw:Transclusion" data-mw="{&quot;parts&quot;:[&quot;
 <table>
 <div>
@@ -19467,9 +19207,9 @@ parsoid=wt2wt,wt2html
 4. Encapsulate foster-parented transclusion content
 !!options
 parsoid=wt2wt,wt2html
-!!input
+!! wikitext
 <table><div><p>{{echo|foo</p></div><tr><td>}}bar</td></tr></table>
-!!result
+!! html
 <div typeof="mw:Transclusion" data-mw="{&quot;parts&quot;:[&quot;
 <table>
 <div>
@@ -19487,9 +19227,9 @@ parsoid=wt2wt,wt2html
 5. Encapsulate foster-parented transclusion content
 !!options
 parsoid=wt2wt,wt2html
-!!input
+!! wikitext
 <table><tr><td><div><p>{{echo|foo</p></div></td>foo}}</tr></table>
-!!result
+!! html
 <span typeof="mw:Transclusion" data-mw="{&quot;parts&quot;:[&quot;
 <table>
 <tr>
@@ -19508,9 +19248,9 @@ parsoid=wt2wt,wt2html
 6. Encapsulate foster-parented transclusion content
 !!options
 parsoid=wt2wt,wt2html
-!!input
+!! wikitext
 <table><tr><td><div><p>{{echo|foo</p></div></td>foo</tr></table>}}<p>ok</p>
-!!result
+!! html
 <span typeof="mw:Transclusion" data-mw="{&quot;parts&quot;:[&quot;
 <table>
 <tr>
@@ -19530,9 +19270,9 @@ parsoid=wt2wt,wt2html
 7. Encapsulate foster-parented transclusion content
 !!options
 parsoid=wt2wt,wt2html
-!!input
+!! wikitext
 <table>{{echo|<p>foo</p>}}<td>bar</td></table>
-!!result
+!! html
 <p typeof="mw:Transclusion" data-mw="{&quot;parts&quot;:[&quot;
 <table>&quot;,{&quot;template&quot;:{&quot;target&quot;:{&quot;wt&quot;:&quot;echo&quot;,&quot;href&quot;:&quot;./Template:Echo&quot;},&quot;params&quot;:{&quot;1&quot;:{&quot;wt&quot;:&quot;
 <p>foo</p>&quot;}},&quot;i&quot;:0}},&quot;
@@ -19547,13 +19287,13 @@ parsoid=wt2wt,wt2html
 8. Encapsulate foster-parented transclusion content
 !!options
 parsoid=wt2wt,wt2html
-!!input
+!! wikitext
 {{echo|a
 }}{|{{echo|style='color:red'}}
 |-
 |b
 |}
-!!result
+!! html
 <p typeof="mw:Transclusion" data-mw="{&quot;parts&quot;:[{&quot;template&quot;:{&quot;target&quot;:{&quot;wt&quot;:&quot;echo&quot;,&quot;href&quot;:&quot;./Template:Echo&quot;},&quot;params&quot;:{&quot;1&quot;:{&quot;wt&quot;:&quot;a\n&quot;}},&quot;i&quot;:0}}]}">a</p><span typeof="mw:Transclusion" data-mw="{&quot;parts&quot;:[&quot;{|&quot;,{&quot;template&quot;:{&quot;target&quot;:{&quot;wt&quot;:&quot;echo&quot;,&quot;href&quot;:&quot;./Template:Echo&quot;},&quot;params&quot;:{&quot;style&quot;:{&quot;wt&quot;:&quot;'color:red'&quot;}},&quot;i&quot;:0}},&quot;\n|-\n|b\n|}&quot;]}">{{{1}}}</span>
 <table>
 <tbody>
@@ -19565,14 +19305,14 @@ parsoid=wt2wt,wt2html
 Table in fosterable position
 !!options
 parsoid=wt2html,wt2wt
-!!input
+!! wikitext
 {{OpenTable}}
 <div>
 {|
 |}
 </div>
 |}
-!!result
+!! html
 <div about="#mwt1" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"OpenTable","href":"./Template:OpenTable"},"params":{},"i":0}},"\n&lt;div>"]}' data-parsoid='{"stx":"html","autoInsertedEnd":true,"pi":[[]]}'></div><span about="#mwt1" data-parsoid="{}">
 </span>
 <table about="#mwt1" data-parsoid='{"autoInsertedEnd":true}'></table>
@@ -19585,9 +19325,9 @@ parsoid=wt2html,wt2wt
 Support <object> element with .data attribute
 !!options
 parsoid=html2wt
-!!input
+!! wikitext
 <object data="test.swf"></object>
-!!result
+!! html
 <object data="test.swf"></object>
 !!end
 
@@ -19602,9 +19342,9 @@ parsoid=html2wt
 Image: Modifying size of an image (1)
 !! options
 parsoid=html2wt
-!! input
+!! wikitext
 [[Image:Foobar.jpg|200x200px]]
-!! result
+!! html
 <p><span typeof="mw:Image" data-parsoid='{"optList":[{"ck":"width","ak":"230x230px"}]}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"}}'><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/230px-Foobar.jpg" height="22" width="200" data-parsoid='{"a":{"resource":"./File:Foobar.jpg","height":"26","width":"230"},"sa":{"resource":"Image:Foobar.jpg"}}'/></a></span></p>
 !!end
 
@@ -19612,9 +19352,9 @@ parsoid=html2wt
 Image: Modifying size of an image (2)
 !! options
 parsoid=html2wt
-!! input
+!! wikitext
 [[Image:Foobar.jpg|500x500px]]
-!! result
+!! html
 <p><span typeof="mw:Image" data-parsoid='{"optList":[{"ck":"width","ak":"230x230px"}]}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"}}'><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/230px-Foobar.jpg" height="100" width="500" data-parsoid='{"a":{"resource":"./File:Foobar.jpg","height":"26","width":"230"},"sa":{"resource":"Image:Foobar.jpg"}}'/></a></span></p>
 !!end
 
@@ -19623,9 +19363,9 @@ parsoid=html2wt
 Image: Modifying alignment of an image (bug 48665)
 !! options
 parsoid=html2wt
-!! input
+!! wikitext
 [[Image:Foobar.jpg|thumb|caption|left]]
-!! result
+!! html
 <figure class="mw-default-size mw-halign-left" typeof="mw:Image/Thumb" data-parsoid='{"optList":[{"ck":"thumbnail","ak":"thumb"},{"ck":"caption","ak":"caption"},{"ck":"right","ak":"right"}]}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"}}'><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" height="20" width="180" data-parsoid='{"a":{"resource":"./File:Foobar.jpg","height":"20","width":"180"},"sa":{"resource":"Image:Foobar.jpg"}}'/></a><figcaption>caption</figcaption></figure>
 !! end
 
@@ -19633,9 +19373,9 @@ parsoid=html2wt
 Image: Modifying valign of an image (bug 49221)
 !! options
 parsoid=html2wt
-!! input
+!! wikitext
 [[File:Foobar.jpg|20px|text-top]]
-!! result
+!! html
 <p><span class="mw-valign-text-top" typeof="mw:Image" data-parsoid='{"optList":[{"ck":"width","ak":"20px"},{"ck":"text_top","ak":"text-top"}]}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"}}'><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/20px-Foobar.jpg" height="2" width="20" data-parsoid='{"a":{"resource":"./File:Foobar.jpg","height":"2","width":"20"},"sa":{"resource":"File:Foobar.jpg"}}'/></a></span></p>
 !! end
 
@@ -19643,9 +19383,9 @@ parsoid=html2wt
 Image: Modifying alt attribute of an image (bug 56400)
 !! options
 parsoid=html2wt
-!! input
+!! wikitext
 [[File:Foobar.jpg|thumb|some caption|alt=some alternate edited text]]
-!! result
+!! html
 <figure class="mw-default-size" typeof="mw:Image/Thumb" data-parsoid='{"optList":[{"ck":"thumbnail","ak":"thumb"},{"ck":"caption","ak":"some caption"},{"ck":"alt","ak":"alt=some alternate text"}]}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"}}'><img alt="some alternate edited text" resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" height="20" width="180" data-parsoid='{"a":{"alt":"some alternate edited text","resource":"./File:Foobar.jpg","height":"20","width":"180"},"sa":{"alt":"alt=some alternate edited text","resource":"File:Foobar.jpg"}}'/></a><figcaption>some caption</figcaption></figure>
 !!end
 
@@ -19653,9 +19393,9 @@ parsoid=html2wt
 Image: Modifying caption of an image
 !! options
 parsoid=html2wt
-!! input
+!! wikitext
 [[Image:Foobar.jpg|thumb|new caption]]
-!! result
+!! html
 <figure class="mw-default-size" typeof="mw:Image/Thumb" data-parsoid='{"optList":[{"ck":"thumbnail","ak":"thumb"},{"ck":"caption","ak":"original caption"}]}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"}}'><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" height="20" width="180" data-parsoid='{"a":{"resource":"./File:Foobar.jpg","height":"20","width":"180"},"sa":{"resource":"Image:Foobar.jpg"}}'/></a><figcaption>new caption</figcaption></figure>
 !!end
 
@@ -19663,9 +19403,9 @@ parsoid=html2wt
 Image: empty alt attribute (bug 48924)
 !! options
 parsoid
-!! input
+!! wikitext
 [[File:Foobar.jpg|thumb|alt=|bar]]
-!! result
+!! html
 <figure class="mw-default-size" typeof="mw:Image/Thumb" data-parsoid='{"optList":[{"ck":"thumbnail","ak":"thumb"},{"ck":"alt","ak":"alt="},{"ck":"caption","ak":"bar"}]}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"}}'><img alt="" resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/220px-Foobar.jpg" height="25" width="220" data-parsoid='{"a":{"alt":"","resource":"./File:Foobar.jpg","height":"25","width":"220"},"sa":{"alt":"alt=","resource":"File:Foobar.jpg"}}'/></a><figcaption>bar</figcaption></figure>
 !! end
 
@@ -19684,11 +19424,11 @@ parsoid
 Image: Block level image should have \n before and after
 !! options
 parsoid
-!! input
+!! wikitext
 123
 [[File:Foobar.jpg|right|thumb|150x150px]]
 456
-!! result
+!! html
 <p>123</p><figure typeof="mw:Image/Thumb" class="mw-halign-right"><a href="./File:Foobar.png"><img src="http://192.168.142.128/mw/images/thumb/b/bc/Foobar.png/131px-Foobar.png" width="131" height="150" resource="./File:Foobar.png" data-parsoid='{"a":{"resource":"./File:Foobar.png","width":"131"},"sa":{"resource":"File:Foobar.png","width":"150"}}'></a></figure><p>456</p>
 !!end
 
@@ -19697,11 +19437,11 @@ Image: New block level image should have \n before and after (existing
 content)
 !! options
 parsoid
-!! input
+!! wikitext
 123
 [[File:Foobar.jpg|right|thumb|150x150px]]
 456
-!! result
+!! html
 <p data-parsoid='{"dsr":[0,3,0,0]}'>123</p>
 <figure class="mw-halign-right" typeof="mw:Image/Thumb" data-parsoid='{"optList":[{"ck":"right","ak":"right"},{"ck":"thumbnail","ak":"thumb"},{"ck":"width","ak":"150x150px"}],"dsr":[4,45,2,2]}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"},"dsr":[6,43,null,null]}'><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/150px-Foobar.jpg" height="17" width="150" data-parsoid='{"a":{"resource":"./File:Foobar.jpg","height":"17","width":"150"},"sa":{"resource":"File:Foobar.jpg"}}'/></a></figure>
 <p data-parsoid='{"dsr":[46,49,0,0]}'>456</p>
@@ -19711,11 +19451,11 @@ parsoid
 Images: upright option (parsoid)
 !! options
 parsoid
-!! input
+!! wikitext
 [[File:Foobar.jpg|thumb|upright|caption]]
 [[File:Foobar.jpg|thumb|upright=0.5|caption]]
 [[File:Foobar.jpg|thumb|500x500px|upright=0.5|caption]]
-!! result
+!! html
 <figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="19" width="170"/></a><figcaption>caption</figcaption></figure><figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="19" width="170"/></a><figcaption>caption</figcaption></figure><figure typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="57" width="500"/></a><figcaption>caption</figcaption></figure>
 !!end
 
@@ -19723,9 +19463,9 @@ parsoid
 Images: upright option is ignored on inline and frame images (parsoid)
 !! options
 parsoid
-!! input
+!! wikitext
 [[File:Foobar.jpg|500x500px|upright=0.5|caption]]
-!! result
+!! html
 <p><span typeof="mw:Image" data-mw='{"caption":"caption"}'><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="57" width="500"/></a></span></p>
 !!end
 
@@ -19733,9 +19473,9 @@ parsoid
 Lists: Serialize correctly even when list content is wrapped in p-tags (like VE does)
 !! options
 parsoid=html2wt
-!! input
+!! wikitext
 * foo
-!! result
+!! html
 <ul>
 <li><p>foo</p></li>
 </ul>
@@ -19745,9 +19485,9 @@ parsoid=html2wt
 Lists: Serialize correctly even when list tags has unneeded whitespace between tags
 !! options
 parsoid=html2wt
-!! input
+!! wikitext
 * foo
-!! result
+!! html
 <ul> <li>foo</li></ul>
 !! end
 
@@ -19755,7 +19495,7 @@ parsoid=html2wt
 Don't strip leading whitespace when handling indent-pre suppressing tags
 !! options
 parsoid=html2wt
-!! input
+!! wikitext
 {|
   | indented row
 |}
@@ -19769,7 +19509,7 @@ parsoid=html2wt
 </blockquote>
 foo
  <div>bar</div>
-!! result
+!! html
 <table>
   <tr><td> indented row</td></tr>
 </table>
@@ -19788,7 +19528,7 @@ foo
 Strip leading whitespace when handling indent-pre inducing tags
 !! options
 parsoid=html2wt
-!! input
+!! wikitext
 foo
 <span>bar</span>
 
@@ -19801,7 +19541,7 @@ foo
 <div>
 <span>foo</span>
 </div>
-!! result
+!! html
 <p>foo</p>
  <span>bar</span>
 
@@ -19820,11 +19560,11 @@ foo
 Lists: Add space after bullets
 !! options
 parsoid=html2wt
-!! input
+!! wikitext
 * foo
 * bar
 * <span> baz</span>
-!! result
+!! html
 <ul>
 <li>foo</li>
 <li> bar</li>
@@ -19832,11 +19572,22 @@ parsoid=html2wt
 </ul>
 !! end
 
+!! test
+Lists: Dont insert newlines in a serialized list item.
+!! options
+parsoid=html2wt
+!! wikitext
+* a<br>b
+* c
+!! html
+<ul><li>a<br>b</li><li>c</li></ul>
+!! end
+
 !! test
 Headings: Add space before/after == (Bug 51744)
 !! options
 parsoid=html2wt
-!! input
+!! wikitext
 == foo ==
 
 == bar ==
@@ -19844,7 +19595,7 @@ parsoid=html2wt
 == baz ==
 
 == <span> baz</span> ==
-!! result
+!! html
 <h2>foo</h2>
 <h2> bar</h2>
 <h2>baz </h2>
@@ -19855,7 +19606,7 @@ parsoid=html2wt
 Parsoid: Serialize positional parameters with = in them as named parameter
 !! options
 parsoid=html2wt
-!! input
+!! wikitext
 {{echo|1 = f=oo}}
 
 {{echo|1 = f=oo|2 = bar}}
@@ -19863,7 +19614,7 @@ parsoid=html2wt
 <!--Orig params with data-parsoid has heuristics for handling = chars-->
 <!--FIXME: But maybe the heuristic needs fixing to apply to new params as well-->
 {{echo|<nowiki>f=oo</nowiki>|bar}}
-!! result
+!! html
 <p about="#mwt1" typeof="mw:Transclusion"
 data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"f=oo"}},"i":0}}]}'>foo</p>
 
@@ -19879,7 +19630,7 @@ data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},
 Parsoid: Correctly serialize block-node children when they are a combination of text and p-nodes
 !! options
 parsoid=html2wt
-!! input
+!! wikitext
 <div>a
 b
 </div>
 
 b
 </div>
-!! result
+!! html
 <div>a<p>b</p></div>
 <div>a
 <p>b</p></div>
 1. I/B quote minimization: wikitext-only tags should be combined
 !! options
 parsoid=html2wt
-!! input
+!! wikitext
 ''AB''
 
 '''AB'''
@@ -19924,7 +19675,7 @@ parsoid=html2wt
 '''''AB'''''
 
 '''''AB'''''
-!! result
+!! html
 <p><i>A</i><i>B</i></p>
 <p><b>A</b><b>B</b></p>
 <p><i>A</i><b><i>B</i></b></p>
@@ -19939,11 +19690,11 @@ parsoid=html2wt
 2. I/B quote minimization: wikitext and html tags should not be combined
 !! options
 parsoid=html2wt
-!! input
+!! wikitext
 ''A''<i>B</i>
 
 ''A'''''<i>B</i>'''
-!! result
+!! html
 <p><i>A</i><i data-parsoid='{"stx":"html"}'>B</i></p>
 <p><i>A</i><b><i data-parsoid='{"stx":"html"}'>B</i></b></p>
 !! end
@@ -19952,11 +19703,11 @@ parsoid=html2wt
 3. I/B quote minimization: templated content stops minimization
 !! options
 parsoid=html2wt
-!! input
+!! wikitext
 ''A''{{echo|''B''}}
 
 ''A''{{echo|'''''B'''''}}
-!! result
+!! html
 <p><i>A</i><i about="#mwt1" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"&#39;&#39;B&#39;&#39;"}},"i":0}}]}'>B</i>
 <p><i>A</i><b about="#mwt1" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"&#39;&#39;&#39;&#39;&#39;B&#39;&#39;&#39;&#39;&#39;"}},"i":0}}]}'><i>B</i></b>
 !! end
@@ -19965,13 +19716,13 @@ parsoid=html2wt
 4. I/B quote minimization: new content should be mimimized with adjacent old content
 !! options
 parsoid=html2wt
-!! input
+!! wikitext
 ''AB''
 
 '''AB'''
 
 ''A'''B'''''
-!! result
+!! html
 <p><i>A</i><i data-parsoid='{}'>B</i></p>
 <p><b data-parsoid='{}'>A</b><b>B</b></p>
 <p><i>A</i><b data-parsoid='{}'><i data-parsoid='{}'>B</i></b></p>
@@ -19985,9 +19736,9 @@ parsoid=html2wt
 Bug 54262: New entities
 !! options
 parsoid=html2wt
-!! input
+!! wikitext
 foo
-!! result
+!! html
 <span typeof="mw:Entity">foo</span>
 !! end
 
@@ -19998,7 +19749,7 @@ foo
 Magic words
 !! options
 parsoid=html2wt
-!! input
+!! wikitext
 __TOC__
 __NOTOC__
 __FORCETOC__
@@ -20008,7 +19759,7 @@ __NOGALLERY__
 __NOEDITSECTION__
 __NOTITLECONVERT__
 __NOCONTENTCONVERT__
-!! result
+!! html
 <meta property='mw:PageProp/toc' />
 <meta property='mw:PageProp/notoc' />
 <meta property='mw:PageProp/forcetoc' />
@@ -20025,7 +19776,7 @@ __NOCONTENTCONVERT__
 Consecutive <pre>s should not get merged
 !! options
 parsoid=html2wt,html2html
-!! input
+!! wikitext
  a
 
  b
@@ -20039,7 +19790,7 @@ parsoid=html2wt,html2html
 
  
  f
-!! result
+!! html
 <pre>a</pre><pre>b</pre>
 
 <pre>c
@@ -20057,9 +19808,9 @@ f</pre>
 Edited ISBN links not serializable as ISBN links should serialize as wikilinks
 !! options
 parsoid=html2wt
-!! input
+!! wikitext
 [[Special:BookSources/1234567890|ISBN 1234567895]]
-!! result
+!! html
 <a rel="mw:ExtLink" href="./Special:BookSources/1234567890">ISBN 1234567895</a>
 !! end
 
@@ -20067,9 +19818,9 @@ parsoid=html2wt
 Edited RFC links not serializable as RFC links should serialize as extlinks
 !! options
 parsoid=html2wt
-!! input
+!! wikitext
 [//tools.ietf.org/html/rfc123 New RFC]
-!! result
+!! html
 <a href="//tools.ietf.org/html/rfc123" rel="mw:ExtLink">New RFC</a>
 !! end
 
@@ -20077,9 +19828,9 @@ parsoid=html2wt
 Edited PMID links not serializable as PMID links should serialize as extlinks
 !! options
 parsoid=html2wt
-!! input
+!! wikitext
 [//www.ncbi.nlm.nih.gov/pubmed/123?dopt=Abstract New PMID]
-!! result
+!! html
 <a href="//www.ncbi.nlm.nih.gov/pubmed/123?dopt=Abstract" rel="mw:ExtLink">New PMID</a>
 !! end
 
@@ -20087,9 +19838,9 @@ parsoid=html2wt
 Edited Redirect link should emit a non-piped wikitext link
 !! options
 parsoid=html2wt
-!! input
+!! wikitext
 #REDIRECT [[Bar]]
-!! result
+!! html
 <link rel="mw:PageProp/redirect" href="Bar" data-parsoid='{"src":"#REDIRECT ","a":{"href":"./Foo"},"sa":{"href":"Foo"}}'>
 !! end
 
index 723f120..277826c 100644 (file)
@@ -586,9 +586,6 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
         */
        public function __call( $func, $args ) {
                static $compatibility = array(
-                       'assertInternalType' => 'assertType', // assertInternalType was added in phpunit 3.5.0
-                       'assertNotInternalType' => 'assertNotType', // assertNotInternalType was added in phpunit 3.5.0
-                       'assertInstanceOf' => 'assertType', // assertInstanceOf was added in phpunit 3.5.0
                        'assertEmpty' => 'assertEmpty2', // assertEmpty was added in phpunit 3.7.32
                );
 
index 7f9a023..8e78da3 100644 (file)
@@ -8,28 +8,43 @@ class ArticleTablesTest extends MediaWikiLangTestCase {
        /**
         * @covers Title::getTemplateLinksFrom
         * @covers Title::getLinksFrom
+        * @todo give this test a real name explaining what is being tested here
         */
        public function testbug14404() {
-               global $wgContLang, $wgLanguageCode, $wgLang;
-
                $title = Title::newFromText( 'Bug 14404' );
                $page = WikiPage::factory( $title );
                $user = new User();
                $user->mRights = array( 'createpage', 'edit', 'purge' );
-               $wgLanguageCode = 'es';
-               $wgContLang = Language::factory( 'es' );
+               $this->setMwGlobals( 'wgLanguageCode', 'es' );
+               $this->setMwGlobals( 'wgContLang', Language::factory( 'es' ) );
+               $this->setMwGlobals( 'wgLang', Language::factory( 'fr' ) );
 
-               $wgLang = Language::factory( 'fr' );
-               $page->doEditContent( new WikitextContent( '{{:{{int:history}}}}' ), 'Test code for bug 14404', 0, false, $user );
+               $page->doEditContent(
+                       new WikitextContent( '{{:{{int:history}}}}' ),
+                       'Test code for bug 14404',
+                       0,
+                       false,
+                       $user
+               );
                $templates1 = $title->getTemplateLinksFrom();
 
-               $wgLang = Language::factory( 'de' );
-               $page = WikiPage::factory( $title ); // In order to force the rerendering of the same wikitext
+               $this->setMwGlobals( 'wgLang', Language::factory( 'de' ) );
+               $page = WikiPage::factory( $title ); // In order to force the re-rendering of the same wikitext
 
                // We need an edit, a purge is not enough to regenerate the tables
-               $page->doEditContent( new WikitextContent( '{{:{{int:history}}}}' ), 'Test code for bug 14404', EDIT_UPDATE, false, $user );
+               $page->doEditContent(
+                       new WikitextContent( '{{:{{int:history}}}}' ),
+                       'Test code for bug 14404',
+                       EDIT_UPDATE,
+                       false,
+                       $user
+               );
                $templates2 = $title->getTemplateLinksFrom();
 
+               /**
+                * @var Title[] $templates1
+                * @var Title[] $templates2
+                */
                $this->assertEquals( $templates1, $templates2 );
                $this->assertEquals( $templates1[0]->getFullText(), 'Historial' );
        }
index dc19154..3cf7abd 100644 (file)
@@ -32,17 +32,16 @@ class ExtraParserTest extends MediaWikiTestCase {
        }
 
        /**
-        * Bug 8689 - Long numeric lines kill the parser
+        * @see Bug 8689
         * @covers Parser::parse
         */
-       public function testBug8689() {
-               global $wgUser;
+       public function testLongNumericLinesDontKillTheParser() {
                $longLine = '1.' . str_repeat( '1234567890', 100000 ) . "\n";
 
-               $t = Title::newFromText( 'Unit test' );
-               $options = ParserOptions::newFromUser( $wgUser );
+               $title = Title::newFromText( 'Unit test' );
+               $options = ParserOptions::newFromUser( new User() );
                $this->assertEquals( "<p>$longLine</p>",
-                       $this->parser->parse( $longLine, $t, $options )->getText() );
+                       $this->parser->parse( $longLine, $title, $options )->getText() );
        }
 
        /**
@@ -52,16 +51,23 @@ class ExtraParserTest extends MediaWikiTestCase {
        public function testParse() {
                $title = Title::newFromText( __FUNCTION__ );
                $parserOutput = $this->parser->parse( "Test\n{{Foo}}\n{{Bar}}", $title, $this->options );
-               $this->assertEquals( "<p>Test\nContent of <i>Template:Foo</i>\nContent of <i>Template:Bar</i>\n</p>", $parserOutput->getText() );
+               $this->assertEquals(
+                       "<p>Test\nContent of <i>Template:Foo</i>\nContent of <i>Template:Bar</i>\n</p>",
+                       $parserOutput->getText()
+               );
        }
 
        /**
         * @covers Parser::preSaveTransform
         */
        public function testPreSaveTransform() {
-               global $wgUser;
                $title = Title::newFromText( __FUNCTION__ );
-               $outputText = $this->parser->preSaveTransform( "Test\r\n{{subst:Foo}}\n{{Bar}}", $title, $wgUser, $this->options );
+               $outputText = $this->parser->preSaveTransform(
+                       "Test\r\n{{subst:Foo}}\n{{Bar}}",
+                       $title,
+                       new User(),
+                       $this->options
+               );
 
                $this->assertEquals( "Test\nContent of ''Template:Foo''\n{{Bar}}", $outputText );
        }
@@ -73,7 +79,10 @@ class ExtraParserTest extends MediaWikiTestCase {
                $title = Title::newFromText( __FUNCTION__ );
                $outputText = $this->parser->preprocess( "Test\n{{Foo}}\n{{Bar}}", $title, $this->options );
 
-               $this->assertEquals( "Test\nContent of ''Template:Foo''\nContent of ''Template:Bar''", $outputText );
+               $this->assertEquals(
+                       "Test\nContent of ''Template:Foo''\nContent of ''Template:Bar''",
+                       $outputText
+               );
        }
 
        /**
@@ -148,6 +157,12 @@ class ExtraParserTest extends MediaWikiTestCase {
                $this->assertEquals( "{{Foo}} information <!-- is very secret -->", $outputText );
        }
 
+       /**
+        * @param Title $title
+        * @param bool $parser
+        *
+        * @return array
+        */
        static function statelessFetchTemplate( $title, $parser = false ) {
                $text = "Content of ''" . $title->getFullText() . "''";
                $deps = array();
index 1305724..ba3c6c0 100644 (file)
@@ -213,6 +213,7 @@ class TitleTest extends MediaWikiTestCase {
        /**
         * @dataProvider provideBug31100
         * @covers Title::fixSpecialName
+        * @todo give this test a real name explaining what is being tested here
         */
        public function testBug31100FixSpecialName( $text, $expectedParam ) {
                $title = Title::newFromText( $text );
index 2ddf05a..e6af126 100644 (file)
@@ -258,4 +258,33 @@ class UserTest extends MediaWikiTestCase {
 
                $wgPasswordExpireGrace = $wgTemp;
        }
+
+       /**
+        * Test password validity checks. There are 3 checks in core,
+        *      - ensure the password meets the minimal length
+        *      - ensure the password is not the same as the username
+        *      - ensure the username/password combo isn't forbidden
+        * @covers User::checkPasswordValidity()
+        * @covers User::getPasswordValidity()
+        * @covers User::isValidPassword()
+        */
+       public function testCheckPasswordValidity() {
+               $this->setMwGlobals( 'wgMinimalPasswordLength', 6 );
+               $user = User::newFromName( 'Useruser' );
+               // Sanity
+               $this->assertTrue( $user->isValidPassword( 'Password1234' ) );
+
+               // Minimum length
+               $this->assertFalse( $user->isValidPassword( 'a' ) );
+               $this->assertFalse( $user->checkPasswordValidity( 'a' )->isGood() );
+               $this->assertEquals( 'passwordtooshort', $user->getPasswordValidity( 'a' ) );
+
+               // Matches username
+               $this->assertFalse( $user->checkPasswordValidity( 'Useruser' )->isGood() );
+               $this->assertEquals( 'password-name-match', $user->getPasswordValidity( 'Useruser' ) );
+
+               // On the forbidden list
+               $this->assertFalse( $user->checkPasswordValidity( 'Passpass' )->isGood() );
+               $this->assertEquals( 'password-login-forbidden', $user->getPasswordValidity( 'Passpass' ) );
+       }
 }
index bc08afe..124988f 100644 (file)
@@ -6,12 +6,16 @@
  * @group medium
  */
 class ApiQueryAllPagesTest extends ApiTestCase {
+
        protected function setUp() {
                parent::setUp();
                $this->doLogin();
        }
 
-       function testBug25702() {
+       /**
+        * @todo give this test a real name explaining what is being tested here
+        */
+       public function testBug25702() {
                $title = Title::newFromText( 'Category:Template:xyz' );
                $page = WikiPage::factory( $title );
                $page->doEdit( 'Some text', 'inserting content' );
index 62ee45a..01c330a 100644 (file)
@@ -154,6 +154,7 @@ class JavaScriptMinifierTest extends MediaWikiTestCase {
        /**
         * @dataProvider provideBug32548
         * @covers JavaScriptMinifier::minify
+        * @todo give this test a real name explaining what is being tested here
         */
        public function testBug32548Exponent( $num ) {
                // Long line breaking was being incorrectly done between the base and
index b913af8..c627537 100644 (file)
@@ -26,7 +26,7 @@ class SearchUpdateTest extends MediaWikiTestCase {
                $this->setMwGlobals( 'wgSearchType', 'MockSearch' );
        }
 
-       function updateText( $text ) {
+       public function updateText( $text ) {
                return trim( SearchUpdate::updateText( $text ) );
        }
 
@@ -67,6 +67,7 @@ EOT
 
        /**
         * @covers SearchUpdate::updateText
+        * @todo give this test a real name explaining what is being tested here
         */
        public function testBug32712() {
                $text = "text „http://example.com“ text";
index 8a92daf..ea2d28c 100644 (file)
@@ -17,6 +17,7 @@ class SpecialPreferencesTest extends MediaWikiTestCase {
         * is not throwing a fatal error.
         *
         * Test specifications by Alexandre "ialex" Emsenhuber.
+        * @todo give this test a real name explaining what is being tested here
         */
        public function testBug41337() {
 
@@ -41,13 +42,6 @@ class SpecialPreferencesTest extends MediaWikiTestCase {
                        )
                        ) );
 
-               # Validate the mock (FIXME should probably be removed)
-               $this->assertFalse( $user->isAnon() );
-               $this->assertEquals( array(),
-                       $user->getEffectiveGroups() );
-               $this->assertEquals( 'superlongnickname',
-                       $user->getOption( 'nickname' ) );
-
                # Forge a request to call the special page
                $context = new RequestContext();
                $context->setRequest( new FauxRequest() );
index 1c89377..da72a9d 100644 (file)
@@ -1,4 +1,5 @@
 <?php
+
 /**
  * @group Database
  *
@@ -10,6 +11,11 @@ class UploadStashTest extends MediaWikiTestCase {
         */
        public static $users;
 
+       /**
+        * @var string
+        */
+       private $bug29408File;
+
        protected function setUp() {
                parent::setUp();
 
@@ -45,6 +51,9 @@ class UploadStashTest extends MediaWikiTestCase {
                parent::tearDown();
        }
 
+       /**
+        * @todo give this test a real name explaining what is being tested here
+        */
        public function testBug29408() {
                $this->setMwGlobals( 'wgUser', self::$users['uploader']->user );
 
@@ -59,20 +68,40 @@ class UploadStashTest extends MediaWikiTestCase {
                $stash->removeFile( $file->getFileKey() );
        }
 
-       public function testValidRequest() {
-               $request = new FauxRequest( array( 'wpFileKey' => 'foo' ) );
-               $this->assertFalse( UploadFromStash::isValidRequest( $request ), 'Check failure on bad wpFileKey' );
-
-               $request = new FauxRequest( array( 'wpSessionKey' => 'foo' ) );
-               $this->assertFalse( UploadFromStash::isValidRequest( $request ), 'Check failure on bad wpSessionKey' );
-
-               $request = new FauxRequest( array( 'wpFileKey' => 'testkey-test.test' ) );
-               $this->assertTrue( UploadFromStash::isValidRequest( $request ), 'Check good wpFileKey' );
+       public function provideInvalidRequests() {
+               return array(
+                       'Check failure on bad wpFileKey' =>
+                               array( new FauxRequest( array( 'wpFileKey' => 'foo' ) ) ),
+                       'Check failure on bad wpSessionKey' =>
+                               array( new FauxRequest( array( 'wpSessionKey' => 'foo' ) ) ),
+               );
+       }
 
-               $request = new FauxRequest( array( 'wpFileKey' => 'testkey-test.test' ) );
-               $this->assertTrue( UploadFromStash::isValidRequest( $request ), 'Check good wpSessionKey' );
+       /**
+        * @dataProvider provideInvalidRequests
+        */
+       public function testValidRequestWithInvalidRequests( $request ) {
+               $this->assertFalse( UploadFromStash::isValidRequest( $request ) );
+       }
 
-               $request = new FauxRequest( array( 'wpFileKey' => 'testkey-test.test', 'wpSessionKey' => 'foo' ) );
-               $this->assertTrue( UploadFromStash::isValidRequest( $request ), 'Check key precedence' );
+       public function provideValidRequests() {
+               return array(
+                       'Check good wpFileKey' =>
+                               array( new FauxRequest( array( 'wpFileKey' => 'testkey-test.test' ) ) ),
+                       'Check good wpSessionKey' =>
+                               array( new FauxRequest( array( 'wpFileKey' => 'testkey-test.test' ) ) ),
+                       'Check key precedence' =>
+                               array( new FauxRequest( array(
+                                       'wpFileKey' => 'testkey-test.test',
+                                       'wpSessionKey' => 'foo'
+                               ) ) ),
+               );
        }
+       /**
+        * @dataProvider provideValidRequests
+        */
+       public function testValidRequestWithValidRequests( $request ) {
+               $this->assertTrue( UploadFromStash::isValidRequest( $request ) );
+       }
+
 }
index 039cabb..1aa2b4d 100755 (executable)
@@ -6,8 +6,6 @@
  * @file
  */
 
-/* Configuration */
-
 // Set a flag which can be used to detect when other scripts have been entered through this entry point or not
 define( 'MW_PHPUNIT_TEST', true );
 
@@ -16,7 +14,7 @@ require_once dirname( dirname( __DIR__ ) ) . "/maintenance/Maintenance.php";
 
 class PHPUnitMaintClass extends Maintenance {
 
-       function __construct() {
+       public function __construct() {
                parent::__construct();
                $this->addOption( 'with-phpunitdir',
                        'Directory to include PHPUnit from, for example when using a git fetchout from upstream. Path will be prepended to PHP `include_path`.',
@@ -72,7 +70,8 @@ class PHPUnitMaintClass extends Maintenance {
                }
 
                # --with-phpunitdir let us override the default PHPUnit version
-               if ( $phpunitDir = $this->getOption( 'with-phpunitdir' ) ) {
+               if ( $this->hasOption( 'with-phpunitdir' ) ) {
+                       $phpunitDir = $this->getOption( 'with-phpunitdir' );
                        # Sanity checks
                        if ( !is_dir( $phpunitDir ) ) {
                                $this->error( "--with-phpunitdir should be set to an existing directory", 1 );
@@ -83,8 +82,7 @@ class PHPUnitMaintClass extends Maintenance {
 
                        # Now prepends provided PHPUnit directory
                        $this->output( "Will attempt loading PHPUnit from `$phpunitDir`\n" );
-                       set_include_path( $phpunitDir
-                               . PATH_SEPARATOR . get_include_path() );
+                       set_include_path( $phpunitDir . PATH_SEPARATOR . get_include_path() );
 
                        # Cleanup $args array so the option and its value do not
                        # pollute PHPUnit
index f4433f4..1d9cf30 100644 (file)
@@ -419,7 +419,7 @@ class TestFileIterator implements Iterator {
                        $this->lineNum++;
                        $matches = array();
 
-                       if ( preg_match( '/^!!\s*(\w+)/', $line, $matches ) ) {
+                       if ( preg_match( '/^!!\s*(\S+)/', $line, $matches ) ) {
                                $this->section = strtolower( $matches[1] );
 
                                if ( $this->section == 'endarticle' ) {
@@ -467,8 +467,10 @@ class TestFileIterator implements Iterator {
 
                                if ( $this->section == 'end' ) {
                                        $this->checkSection( 'test' );
-                                       $this->checkSection( 'input' );
-                                       $this->checkSection( 'result' );
+                                       // "input" and "result" are old section names allowed
+                                       // for backwards-compatibility.
+                                       $input = $this->checkSection( array( 'wikitext', 'input' ), false );
+                                       $result = $this->checkSection( array( 'html/php', 'html/*', 'html', 'result' ), false );
 
                                        if ( !isset( $this->sectionData['options'] ) ) {
                                                $this->sectionData['options'] = '';
@@ -478,8 +480,9 @@ class TestFileIterator implements Iterator {
                                                $this->sectionData['config'] = '';
                                        }
 
-                                       if ( ( ( preg_match( '/\\bdisabled\\b/i', $this->sectionData['options'] ) && !$this->parserTest->runDisabled )
-                                               || ( preg_match( '/\\bparsoid\\b/i', $this->sectionData['options'] ) && !$this->parserTest->runParsoid )
+                                       if ( $input == false || $result == false ||
+                                                ( ( preg_match( '/\\bdisabled\\b/i', $this->sectionData['options'] ) && !$this->parserTest->runDisabled )
+                                               || ( preg_match( '/\\bparsoid\\b/i', $this->sectionData['options'] ) && $result != 'html/php' && !$this->parserTest->runParsoid )
                                                || !preg_match( "/" . $this->parserTest->regex . "/i", $this->sectionData['test'] ) )
                                        ) {
                                                # disabled test
@@ -501,8 +504,8 @@ class TestFileIterator implements Iterator {
 
                                        $this->test = array(
                                                'test' => ParserTest::chomp( $this->sectionData['test'] ),
-                                               'input' => ParserTest::chomp( $this->sectionData['input'] ),
-                                               'result' => ParserTest::chomp( $this->sectionData['result'] ),
+                                               'input' => ParserTest::chomp( $this->sectionData[ $input ] ),
+                                               'result' => ParserTest::chomp( $this->sectionData[ $result ] ),
                                                'options' => ParserTest::chomp( $this->sectionData['options'] ),
                                                'config' => ParserTest::chomp( $this->sectionData['config'] ),
                                        );
@@ -538,27 +541,55 @@ class TestFileIterator implements Iterator {
 
        /**
         * Verify the current section data has some value for the given token
-        * name (first parameter).
+        * name(s) (first parameter).
         * Throw an exception if it is not set, referencing current section
         * and adding the current file name and line number
         *
-        * @param $token String: expected token that should have been mentionned before closing this section
+        * @param $token String|Array: expected token(s) that should have been
+        * mentioned before closing this section
+        * @param $fatal Boolean: true iff an exception should be thrown if
+        * the section is not found.
         */
-       private function checkSection( $token ) {
+       private function checkSection( $tokens, $fatal = true ) {
                if ( is_null( $this->section ) ) {
                        throw new MWException( __METHOD__ . " can not verify a null section!\n" );
                }
+               if ( !is_array( $tokens ) ) {
+                       $tokens = array( $tokens );
+               }
+               if ( count( $tokens ) == 0 ) {
+                       throw new MWException( __METHOD__ . " can not verify zero sections!\n" );
+               }
 
-               if ( !isset( $this->sectionData[$token] ) ) {
+               $data = $this->sectionData;
+               $tokens = array_filter( $tokens, function ( $token ) use ( $data ) {
+                       return isset( $data[ $token ] );
+               } );
+
+               if ( count( $tokens ) == 0 ) {
+                       if ( !$fatal ) {
+                               return false;
+                       }
                        throw new MWException( sprintf(
                                "'%s' without '%s' at line %s of %s\n",
                                $this->section,
-                               $token,
+                               implode( ',', $tokens ),
                                $this->lineNum,
                                $this->file
                        ) );
                }
-               return true;
+               if ( count( $tokens ) > 1 ) {
+                       throw new MWException( sprintf(
+                               "'%s' with unexpected tokens '%s' at line %s of %s\n",
+                               $this->section,
+                               implode( ',', $tokens ),
+                               $this->lineNum,
+                               $this->file
+                       ) );
+               }
+
+               $tokens = array_values( $tokens );
+               return $tokens[ 0 ];
        }
 }