Merge "TextContent: Normalize newlines in preSaveTransform()"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Tue, 16 Aug 2016 15:34:16 +0000 (15:34 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Tue, 16 Aug 2016 15:34:16 +0000 (15:34 +0000)
44 files changed:
composer.json
includes/DefaultSettings.php
includes/WatchedItemStore.php
includes/api/i18n/fr.json
includes/api/i18n/he.json
includes/auth/AuthManager.php
includes/changes/RecentChange.php
includes/deferred/AtomicSectionUpdate.php
includes/deferred/AutoCommitUpdate.php
includes/deferred/DeferredUpdates.php
includes/deferred/MWCallableUpdate.php
includes/filebackend/lockmanager/DBLockManager.php
includes/filerepo/file/LocalFile.php
includes/jobqueue/JobRunner.php
includes/page/WikiPage.php
includes/parser/Preprocessor_DOM.php
includes/parser/Preprocessor_Hash.php
includes/revisiondelete/RevDelList.php
includes/specials/SpecialTags.php
includes/upload/UploadBase.php
languages/i18n/ang.json
languages/i18n/ar.json
languages/i18n/ast.json
languages/i18n/be.json
languages/i18n/bn.json
languages/i18n/diq.json
languages/i18n/en.json
languages/i18n/fr.json
languages/i18n/gl.json
languages/i18n/he.json
languages/i18n/it.json
languages/i18n/ja.json
languages/i18n/jv.json
languages/i18n/lb.json
languages/i18n/pt-br.json
languages/i18n/pt.json
languages/i18n/qqq.json
languages/i18n/si.json
languages/i18n/tr.json
maintenance/findDeprecated.php
maintenance/refreshImageMetadata.php
mw-config/overrides/README
resources/src/mediawiki.ui/components/icons.less
resources/src/mediawiki/page/gallery-slideshow.js

index 9bd0fa1..90f7063 100644 (file)
@@ -48,7 +48,7 @@
                "justinrainbow/json-schema": "~1.6",
                "mediawiki/mediawiki-codesniffer": "0.7.2",
                "monolog/monolog": "~1.18.2",
-               "nikic/php-parser": "1.4.1",
+               "nikic/php-parser": "2.1.0",
                "nmred/kafka-php": "0.1.5",
                "phpunit/phpunit": "4.8.24",
                "wikimedia/avro": "1.7.7"
index a5d8c5b..4e08aa6 100644 (file)
@@ -5710,6 +5710,8 @@ $wgGrantPermissions['sendemail']['sendemail'] = true;
 
 $wgGrantPermissions['createaccount']['createaccount'] = true;
 
+$wgGrantPermissions['privateinfo']['viewmyprivateinfo'] = true;
+
 /**
  * @var Array Map of grants to their UI grouping
  * @since 1.27
@@ -5743,6 +5745,8 @@ $wgGrantPermissionGroups = [
        'createaccount'       => 'administration',
 
        'highvolume'          => 'high-volume',
+
+       'privateinfo'         => 'private-information',
 ];
 
 /**
index 89ca50c..b8a47fa 100644 (file)
@@ -761,7 +761,9 @@ class WatchedItemStore implements StatsdAwareInterface {
                                        $this->uncacheLinkTarget( $target );
 
                                        $this->reuseConnection( $dbw );
-                               }
+                               },
+                               DeferredUpdates::POSTSEND,
+                               $dbw
                        );
                }
 
index b34131b..80eec50 100644 (file)
        "apihelp-stashedit-param-section": "Numéro de section. <kbd>0</kbd> pour la section du haut, <kbd>new</kbd> pour une nouvelle section.",
        "apihelp-stashedit-param-sectiontitle": "Le titre pour une nouvelle section.",
        "apihelp-stashedit-param-text": "Contenu de la page.",
-       "apihelp-stashedit-param-stashedtexthash": "Hachage du contenu de la page d’une réserve antérieure à utiliser à la place.",
+       "apihelp-stashedit-param-stashedtexthash": "A substituer par le hachage du contenu de la page venant d’une réserve antérieure.",
        "apihelp-stashedit-param-contentmodel": "Modèle de contenu du nouveau contenu.",
        "apihelp-stashedit-param-contentformat": "Format de sérialisation de contenu utilisé pour le texte saisi.",
        "apihelp-stashedit-param-baserevid": "ID de révision de la révision de base.",
index 08a27d6..a28cbda 100644 (file)
        "apihelp-linkaccount-example-link": "תחילת תהליך הקישור לחשבון מ־<kbd>Example</kbd>.",
        "apihelp-login-description": "להיכנס ולקבל עוגיות אימות.\n\nהפעולה הזאת צריכה לשמש רק בשילוב [[Special:BotPasswords]]; שימוש לכניסה לחשבון ראשי מיושן ועשוי להיכשל ללא אזהרה. כדי להיכנס בבטחה לחשבון הראשי, יש להשתמש ב־<kbd>[[Special:ApiHelp/clientlogin|action=clientlogin]]</kbd>.",
        "apihelp-login-description-nobotpasswords": "להיכנס ולקבל עוגיות אימות.\n\nהפעולה הזאת מיושנת ועשויה להיכשל ללא אזהרה. כדי להיכנס בבטחה, יש להשתמש ב־<kbd>[[Special:ApiHelp/clientlogin|action=clientlogin]]</kbd>.",
-       "apihelp-login-description-nonauthmanager": "להיכנס ולקבל עוגיות אימות.\n\nבמקרה של כניסה מוצלחת, העוגיות המקוננות תיכללנה בכותרות תשובות ה־HTTP. במקרה של כניסה כושלת, הניסיונות הבאים יוגבלו למספר ניסויי ניחוש הססמה האוטומטיים.",
        "apihelp-login-param-name": "שם משתמש.",
        "apihelp-login-param-password": "ססמה.",
        "apihelp-login-param-domain": "שם מתחם (רשות).",
        "apihelp-stashedit-param-section": "מספר הפסקה. <kbd>0</kbd> עבור הפסקה הראשונה, <kbd>new</kbd> עבור פסקה חדשה.",
        "apihelp-stashedit-param-sectiontitle": "כותרת הפסקה החדשה.",
        "apihelp-stashedit-param-text": "תוכן הדף.",
+       "apihelp-stashedit-param-stashedtexthash": "גיבוב של תוכן דף מסליק קודם שישמש במקום זה.",
        "apihelp-stashedit-param-contentmodel": "מודל התוכן של התוכן החדש.",
        "apihelp-stashedit-param-contentformat": "תסדיר הסדרת תוכן עבור טקסט הקלט.",
        "apihelp-stashedit-param-baserevid": "מזהה גסה של גרסת הבסיס.",
index eab5068..50e370e 100644 (file)
@@ -1605,9 +1605,6 @@ class AuthManager implements LoggerAwareInterface {
                        }
                }
 
-               // Ignore warnings about master connections/writes...hard to avoid here
-               \Profiler::instance()->getTransactionProfiler()->resetExpectations();
-
                $backoffKey = wfMemcKey( 'AuthManager', 'autocreate-failed', md5( $username ) );
                if ( $cache->get( $backoffKey ) ) {
                        $this->logger->debug( __METHOD__ . ': {username} denied by prior creation attempt failures', [
@@ -1625,6 +1622,9 @@ class AuthManager implements LoggerAwareInterface {
                        'from' => $from,
                ] );
 
+               // Ignore warnings about master connections/writes...hard to avoid here
+               $trxProfiler = \Profiler::instance()->getTransactionProfiler();
+               $trxProfiler->setSilenced( true );
                try {
                        $status = $user->addToDatabase();
                        if ( !$status->isOk() ) {
@@ -1652,6 +1652,7 @@ class AuthManager implements LoggerAwareInterface {
                                return $status;
                        }
                } catch ( \Exception $ex ) {
+                       $trxProfiler->setSilenced( false );
                        $this->logger->error( __METHOD__ . ': {username} failed with exception {exception}', [
                                'username' => $username,
                                'exception' => $ex,
@@ -1673,9 +1674,10 @@ class AuthManager implements LoggerAwareInterface {
 
                // Update user count
                \DeferredUpdates::addUpdate( new \SiteStatsUpdate( 0, 0, 0, 0, 1 ) );
-
                // Watch user's userpage and talk page
-               $user->addWatch( $user->getUserPage(), User::IGNORE_USER_RIGHTS );
+               \DeferredUpdates::addCallableUpdate( function () use ( $user ) {
+                       $user->addWatch( $user->getUserPage(), User::IGNORE_USER_RIGHTS );
+               } );
 
                // Log the creation
                if ( $this->config->get( 'NewUserLog' ) ) {
@@ -1693,6 +1695,8 @@ class AuthManager implements LoggerAwareInterface {
                // the newly-created user doesn't get lost.
                wfGetLBFactory()->commitMasterChanges( __METHOD__ );
 
+               $trxProfiler->setSilenced( false );
+
                if ( $login ) {
                        $this->setSessionDataForUser( $user );
                }
index 159cfd9..daf76df 100644 (file)
@@ -589,16 +589,20 @@ class RecentChange {
                        'pageStatus' => 'changed'
                ];
 
-               DeferredUpdates::addCallableUpdate( function() use ( $rc, $tags ) {
-                       $rc->save();
-                       if ( $rc->mAttribs['rc_patrolled'] ) {
-                               PatrolLog::record( $rc, true, $rc->getPerformer() );
-                       }
-                       if ( count( $tags ) ) {
-                               ChangeTags::addTags( $tags, $rc->mAttribs['rc_id'],
-                                       $rc->mAttribs['rc_this_oldid'], null, null );
-                       }
-               } );
+               DeferredUpdates::addCallableUpdate(
+                       function () use ( $rc, $tags ) {
+                               $rc->save();
+                               if ( $rc->mAttribs['rc_patrolled'] ) {
+                                       PatrolLog::record( $rc, true, $rc->getPerformer() );
+                               }
+                               if ( count( $tags ) ) {
+                                       ChangeTags::addTags( $tags, $rc->mAttribs['rc_id'],
+                                               $rc->mAttribs['rc_this_oldid'], null, null );
+                               }
+                       },
+                       DeferredUpdates::POSTSEND,
+                       wfGetDB( DB_MASTER )
+               );
 
                return $rc;
        }
@@ -661,16 +665,20 @@ class RecentChange {
                        'pageStatus' => 'created'
                ];
 
-               DeferredUpdates::addCallableUpdate( function() use ( $rc, $tags ) {
-                       $rc->save();
-                       if ( $rc->mAttribs['rc_patrolled'] ) {
-                               PatrolLog::record( $rc, true, $rc->getPerformer() );
-                       }
-                       if ( count( $tags ) ) {
-                               ChangeTags::addTags( $tags, $rc->mAttribs['rc_id'],
-                                       $rc->mAttribs['rc_this_oldid'], null, null );
-                       }
-               } );
+               DeferredUpdates::addCallableUpdate(
+                       function () use ( $rc, $tags ) {
+                               $rc->save();
+                               if ( $rc->mAttribs['rc_patrolled'] ) {
+                                       PatrolLog::record( $rc, true, $rc->getPerformer() );
+                               }
+                               if ( count( $tags ) ) {
+                                       ChangeTags::addTags( $tags, $rc->mAttribs['rc_id'],
+                                               $rc->mAttribs['rc_this_oldid'], null, null );
+                               }
+                       },
+                       DeferredUpdates::POSTSEND,
+                       wfGetDB( DB_MASTER )
+               );
 
                return $rc;
        }
index 0da5d7d..a348719 100644 (file)
@@ -9,7 +9,7 @@ class AtomicSectionUpdate implements DeferrableUpdate, DeferrableCallback {
        private $dbw;
        /** @var string */
        private $fname;
-       /** @var callable */
+       /** @var callable|null */
        private $callback;
 
        /**
index ef5903b..d26cf9d 100644 (file)
@@ -9,7 +9,7 @@ class AutoCommitUpdate implements DeferrableUpdate, DeferrableCallback {
        private $dbw;
        /** @var string */
        private $fname;
-       /** @var callable */
+       /** @var callable|null */
        private $callback;
 
        /**
index 9768838..ee14e1a 100644 (file)
@@ -68,9 +68,12 @@ class DeferredUpdates {
         *
         * @param callable $callable
         * @param integer $type DeferredUpdates constant (PRESEND or POSTSEND) (since 1.27)
+        * @param IDatabase|null $dbw Abort if this DB is rolled back [optional] (since 1.28)
         */
-       public static function addCallableUpdate( $callable, $type = self::POSTSEND ) {
-               self::addUpdate( new MWCallableUpdate( $callable, wfGetCaller() ), $type );
+       public static function addCallableUpdate(
+               $callable, $type = self::POSTSEND, IDatabase $dbw = null
+       ) {
+               self::addUpdate( new MWCallableUpdate( $callable, wfGetCaller(), $dbw ), $type );
        }
 
        /**
index d63c292..47b162c 100644 (file)
@@ -4,7 +4,7 @@
  * Deferrable Update for closure/callback
  */
 class MWCallableUpdate implements DeferrableUpdate, DeferrableCallback {
-       /** @var callable */
+       /** @var callable|null */
        private $callback;
        /** @var string */
        private $fname;
@@ -12,14 +12,27 @@ class MWCallableUpdate implements DeferrableUpdate, DeferrableCallback {
        /**
         * @param callable $callback
         * @param string $fname Calling method
+        * @param IDatabase|null $dbw Abort if this DB is rolled back [optional] (since 1.28)
         */
-       public function __construct( callable $callback, $fname = 'unknown' ) {
+       public function __construct( callable $callback, $fname = 'unknown', IDatabase $dbw = null ) {
                $this->callback = $callback;
                $this->fname = $fname;
+
+               if ( $dbw && $dbw->trxLevel() ) {
+                       $dbw->onTransactionResolution( [ $this, 'cancelOnRollback' ] );
+               }
        }
 
        public function doUpdate() {
-               call_user_func( $this->callback );
+               if ( $this->callback ) {
+                       call_user_func( $this->callback );
+               }
+       }
+
+       public function cancelOnRollback( $trigger ) {
+               if ( $trigger === IDatabase::TRIGGER_ROLLBACK ) {
+                       $this->callback = null;
+               }
        }
 
        public function getOrigin() {
index b61b08d..c9aad43 100644 (file)
@@ -26,9 +26,8 @@
  *
  * This is meant for multi-wiki systems that may share files.
  *
- * All lock requests for a resource, identified by a hash string, will map
- * to one bucket. Each bucket maps to one or several peer DBs, each on their
- * own server, all having the filelocks.sql tables (with row-level locking).
+ * All lock requests for a resource, identified by a hash string, will map to one bucket.
+ * Each bucket maps to one or several peer DBs, each on their own server.
  * A majority of peer DBs must agree for a lock to be acquired.
  *
  * Caching is used to avoid hitting servers that are down.
@@ -243,6 +242,8 @@ abstract class DBLockManager extends QuorumLockManager {
 
 /**
  * MySQL version of DBLockManager that supports shared locks.
+ *
+ * All lock servers must have the innodb table defined in locking/filelocks.sql.
  * All locks are non-blocking, which avoids deadlocks.
  *
  * @ingroup LockManager
index b8be4ea..91d628c 100644 (file)
@@ -117,6 +117,9 @@ class LocalFile extends File {
        /** @var bool Whether the row was upgraded on load */
        private $upgraded;
 
+       /** @var bool Whether the row was scheduled to upgrade on load */
+       private $upgrading;
+
        /** @var bool True if the image row is locked */
        private $locked;
 
@@ -559,37 +562,43 @@ class LocalFile extends File {
         */
        function maybeUpgradeRow() {
                global $wgUpdateCompatibleMetadata;
-               if ( wfReadOnly() ) {
+
+               if ( wfReadOnly() || $this->upgrading ) {
                        return;
                }
 
                $upgrade = false;
-               if ( is_null( $this->media_type ) ||
-                       $this->mime == 'image/svg'
-               ) {
+               if ( is_null( $this->media_type ) || $this->mime == 'image/svg' ) {
                        $upgrade = true;
                } else {
                        $handler = $this->getHandler();
                        if ( $handler ) {
                                $validity = $handler->isMetadataValid( $this, $this->getMetadata() );
-                               if ( $validity === MediaHandler::METADATA_BAD
-                                       || ( $validity === MediaHandler::METADATA_COMPATIBLE && $wgUpdateCompatibleMetadata )
-                               ) {
+                               if ( $validity === MediaHandler::METADATA_BAD ) {
                                        $upgrade = true;
+                               } elseif ( $validity === MediaHandler::METADATA_COMPATIBLE ) {
+                                       $upgrade = $wgUpdateCompatibleMetadata;
                                }
                        }
                }
 
                if ( $upgrade ) {
-                       try {
-                               $this->upgradeRow();
-                       } catch ( LocalFileLockError $e ) {
-                               // let the other process handle it (or do it next time)
-                       }
-                       $this->upgraded = true; // avoid rework/retries
+                       $this->upgrading = true;
+                       // Defer updates unless in auto-commit CLI mode
+                       DeferredUpdates::addCallableUpdate( function() {
+                               $this->upgrading = false; // avoid duplicate updates
+                               try {
+                                       $this->upgradeRow();
+                               } catch ( LocalFileLockError $e ) {
+                                       // let the other process handle it (or do it next time)
+                               }
+                       } );
                }
        }
 
+       /**
+        * @return bool Whether upgradeRow() ran for this object
+        */
        function getUpgraded() {
                return $this->upgraded;
        }
@@ -639,7 +648,7 @@ class LocalFile extends File {
                $this->invalidateCache();
 
                $this->unlock(); // done
-
+               $this->upgraded = true; // avoid rework/retries
        }
 
        /**
@@ -964,6 +973,33 @@ class LocalFile extends File {
                DeferredUpdates::addUpdate( new CdnCacheUpdate( $urls ), DeferredUpdates::PRESEND );
        }
 
+       /**
+        * Prerenders a configurable set of thumbnails
+        *
+        * @since 1.28
+        */
+       public function prerenderThumbnails() {
+               global $wgUploadThumbnailRenderMap;
+
+               $jobs = [];
+
+               $sizes = $wgUploadThumbnailRenderMap;
+               rsort( $sizes );
+
+               foreach ( $sizes as $size ) {
+                       if ( $this->isVectorized() || $this->getWidth() > $size ) {
+                               $jobs[] = new ThumbnailRenderJob(
+                                       $this->getTitle(),
+                                       [ 'transformParams' => [ 'width' => $size ] ]
+                               );
+                       }
+               }
+
+               if ( $jobs ) {
+                       JobQueueGroup::singleton()->lazyPush( $jobs );
+               }
+       }
+
        /**
         * Delete a list of thumbnails visible at urls
         * @param string $dir Base dir of the files.
@@ -1516,6 +1552,8 @@ class LocalFile extends File {
                                                # Update backlink pages pointing to this title if created
                                                LinksUpdate::queueRecursiveJobsForTable( $this->getTitle(), 'imagelinks' );
                                        }
+
+                                       $this->prerenderThumbnails();
                                }
                        ),
                        DeferredUpdates::PRESEND
index a132dc5..4b906a7 100644 (file)
@@ -522,10 +522,10 @@ class JobRunner implements LoggerAwareInterface {
                        // This will trigger a rollback in the main loop
                        throw new DBError( $dbwSerial, "Timed out waiting on commit queue." );
                }
-               // Wait for the generic slave to catch up
+               // Wait for the slave DBs to catch up
                $pos = $lb->getMasterPos();
                if ( $pos ) {
-                       $lb->waitForOne( $pos );
+                       $lb->waitForAll( $pos );
                }
 
                $fname = __METHOD__;
index 8eba1cc..0344756 100644 (file)
@@ -90,6 +90,14 @@ class WikiPage implements Page, IDBAccessObject {
                $this->mTitle = $title;
        }
 
+       /**
+        * Makes sure that the mTitle object is cloned
+        * to the newly cloned WikiPage.
+        */
+       public function __clone() {
+               $this->mTitle = clone $this->mTitle;
+       }
+
        /**
         * Create a WikiPage object of the appropriate class for the given title.
         *
@@ -887,9 +895,13 @@ class WikiPage implements Page, IDBAccessObject {
                // Update the DB post-send if the page has not cached since now
                $that = $this;
                $latest = $this->getLatest();
-               DeferredUpdates::addCallableUpdate( function() use ( $that, $retval, $latest ) {
-                       $that->insertRedirectEntry( $retval, $latest );
-               } );
+               DeferredUpdates::addCallableUpdate(
+                       function () use ( $that, $retval, $latest ) {
+                               $that->insertRedirectEntry( $retval, $latest );
+                       },
+                       DeferredUpdates::POSTSEND,
+                       wfGetDB( DB_MASTER )
+               );
 
                return $retval;
        }
@@ -1048,9 +1060,9 @@ class WikiPage implements Page, IDBAccessObject {
         * @param bool          $forceParse Force reindexing, regardless of cache settings
         * @return bool|ParserOutput ParserOutput or false if the revision was not found
         */
-       public function getParserOutput( ParserOptions $parserOptions, $oldid = null,
-                                        $forceParse = false ) {
-
+       public function getParserOutput(
+               ParserOptions $parserOptions, $oldid = null, $forceParse = false
+       ) {
                $useParserCache =
                        ( !$forceParse ) && $this->shouldCheckParserCache( $parserOptions, $oldid );
                wfDebug( __METHOD__ .
@@ -2934,6 +2946,11 @@ class WikiPage implements Page, IDBAccessObject {
                // Save this so we can pass it to the ArticleDeleteComplete hook.
                $archivedRevisionCount = $dbw->affectedRows();
 
+               // Clone the title and wikiPage, so we have the information we need when
+               // we log and run the ArticleDeleteComplete hook.
+               $logTitle = clone $this->mTitle;
+               $wikiPageBeforeDelete = clone $this;
+
                // Now that it's safely backed up, delete it
                $dbw->delete( 'page', [ 'page_id' => $id ], __METHOD__ );
 
@@ -2941,9 +2958,6 @@ class WikiPage implements Page, IDBAccessObject {
                        $dbw->delete( 'revision', [ 'rev_page' => $id ], __METHOD__ );
                }
 
-               // Clone the title, so we have the information we need when we log
-               $logTitle = clone $this->mTitle;
-
                // Log the deletion, if the page was suppressed, put it in the suppression log instead
                $logtype = $suppress ? 'suppress' : 'delete';
 
@@ -2962,8 +2976,15 @@ class WikiPage implements Page, IDBAccessObject {
 
                $this->doDeleteUpdates( $id, $content );
 
-               Hooks::run( 'ArticleDeleteComplete',
-                       [ &$this, &$user, $reason, $id, $content, $logEntry, $archivedRevisionCount ] );
+               Hooks::run( 'ArticleDeleteComplete', [
+                       &$wikiPageBeforeDelete,
+                       &$user,
+                       $reason,
+                       $id,
+                       $content,
+                       $logEntry,
+                       $archivedRevisionCount
+               ] );
                $status->value = $logid;
 
                // Show log excerpt on 404 pages rather than just a link
index a28c0aa..5da7cd7 100644 (file)
@@ -539,7 +539,7 @@ class Preprocessor_DOM extends Preprocessor {
                        } elseif ( $found == 'line-end' ) {
                                $piece = $stack->top;
                                // A heading must be open, otherwise \n wouldn't have been in the search list
-                               assert( '$piece->open == "\n"' );
+                               assert( $piece->open === "\n" );
                                $part = $piece->getCurrentPart();
                                // Search back through the input to see if it has a proper close.
                                // Do this using the reversed string since the other solutions
index 012288f..8a4637e 100644 (file)
@@ -475,7 +475,7 @@ class Preprocessor_Hash extends Preprocessor {
                        } elseif ( $found == 'line-end' ) {
                                $piece = $stack->top;
                                // A heading must be open, otherwise \n wouldn't have been in the search list
-                               assert( '$piece->open == "\n"' );
+                               assert( $piece->open === "\n" );
                                $part = $piece->getCurrentPart();
                                // Search back through the input to see if it has a proper close.
                                // Do this using the reversed string since the other solutions
index d365bf6..48604e1 100644 (file)
@@ -275,7 +275,8 @@ abstract class RevDelList extends RevisionListBase {
                        function () use ( $visibilityChangeMap ) {
                                $this->doPostCommitUpdates( $visibilityChangeMap );
                        },
-                       DeferredUpdates::PRESEND
+                       DeferredUpdates::PRESEND,
+                       $dbw
                );
 
                $dbw->endAtomic( __METHOD__ );
index e957b3c..47bed62 100644 (file)
@@ -142,7 +142,7 @@ class SpecialTags extends SpecialPage {
                        Xml::tags( 'th', null, $this->msg( 'tags-source-header' )->parse() ) .
                        Xml::tags( 'th', null, $this->msg( 'tags-active-header' )->parse() ) .
                        Xml::tags( 'th', null, $this->msg( 'tags-hitcount-header' )->parse() ) .
-                       ( $userCanManage ?
+                       ( ( $userCanManage || $userCanDelete ) ?
                                Xml::tags( 'th', [ 'class' => 'unsortable' ],
                                        $this->msg( 'tags-actions-header' )->parse() ) :
                                '' )
@@ -266,7 +266,7 @@ class SpecialTags extends SpecialPage {
 
                }
 
-               if ( $actionLinks ) {
+               if ( $showDeleteActions || $showManageActions ) {
                        $newRow .= Xml::tags( 'td', null, $this->getLanguage()->pipeList( $actionLinks ) );
                }
 
index 03c864a..9f534d2 100644 (file)
@@ -774,27 +774,6 @@ abstract class UploadBase {
         * @since  1.25
         */
        public function postProcessUpload() {
-               global $wgUploadThumbnailRenderMap;
-
-               $jobs = [];
-
-               $sizes = $wgUploadThumbnailRenderMap;
-               rsort( $sizes );
-
-               $file = $this->getLocalFile();
-
-               foreach ( $sizes as $size ) {
-                       if ( $file->isVectorized() || $file->getWidth() > $size ) {
-                               $jobs[] = new ThumbnailRenderJob(
-                                       $file->getTitle(),
-                                       [ 'transformParams' => [ 'width' => $size ] ]
-                               );
-                       }
-               }
-
-               if ( $jobs ) {
-                       JobQueueGroup::singleton()->push( $jobs );
-               }
        }
 
        /**
index d10b150..f511d2b 100644 (file)
@@ -14,7 +14,8 @@
                        "아라",
                        "Dpk",
                        "Macofe",
-                       "WhatamIdoing"
+                       "WhatamIdoing",
+                       "Hogweard"
                ]
        },
        "tog-underline": "Mearc under hlencan:",
        "october-date": "$1. Winterfylleðes",
        "november-date": "$1. Blōtmōnaðes",
        "december-date": "$1. Ǣrran Gēolan",
+       "period-am": "on undernmǣl",
+       "period-pm": "on ofernōn",
        "pagecategories": "{{PLURAL:$1|Flocc|Floccas}}",
        "category_header": "Trametas in \"$1\" flocce",
        "subcategories": "Underfloccas",
        "jumptonavigation": "þurhfōr",
        "jumptosearch": "sēcan",
        "view-pool-error": "Wālā, þā þegntōlas nū oferlīce wyrcaþ.\nTō mænige brūcendas gesēcaþ tō sēonne þisne tramet.\nWē biddaþ þæt þū abīde scortne tīman ǣr þū gesēce to sēonne þisne tramet eft.\n\n$1",
+       "pool-queuefull": "Pundfaldes forepenn is full",
        "pool-errorunknown": "Uncūþ wōh",
+       "pool-servererror": "Seo pundaldgetalere þēgnung nis gearo",
        "aboutsite": "Gecȳþness ymbe {{GRAMMAR:wrēgendlīc|{{SITENAME}}}}",
        "aboutpage": "Project:Gefrǣge",
        "copyright": "Man mæg innunge under $1 findan, būton þǣr hit is elles amearcod.",
index 80df33f..5e8b4b2 100644 (file)
        "undeletedrevisions-files": "أسترجعت {{PLURAL:$1||مراجعة واحدة|مراجعتان|$1 مراجعات|$1 مراجعة}}  و{{PLURAL:$2||ملف واحد|ملفان|$2 ملفات|$2 ملفًا|$2 ملف}}",
        "undeletedfiles": "أسترجع {{PLURAL:$1||ملف واحد|ملفان|$1 ملفات|$1 ملفًا|$1 ملف}}",
        "cannotundelete": "فشل الاسترجاع؛\n$1",
-       "undeletedpage": "'''تÙ\85 Ø§Ø³ØªØ±Ø¬Ø§Ø¹ $1'''\n\nراجع [[Special:Log/delete|سجÙ\84 Ø§Ù\84حدف]] لمعاينة عمليات الحذف والاسترجاعات الحديثة.",
+       "undeletedpage": "'''تÙ\85 Ø§Ø³ØªØ±Ø¬Ø§Ø¹ $1'''\n\nراجع [[Special:Log/delete|سجÙ\84 Ø§Ù\84حذف]] لمعاينة عمليات الحذف والاسترجاعات الحديثة.",
        "undelete-header": "انظر الصفحات المحذوفة حديثا في [[Special:Log/delete|سجل الحذف]].",
        "undelete-search-title": "البحث في الصفحات المحذوفة",
        "undelete-search-box": "ابحث في الصفحات المحذوفة",
index 4c8c6d0..0b4a793 100644 (file)
        "action-applychangetags": "aplicar etiquetes xunto colos cambios",
        "action-changetags": "amestar y desaniciar etiquetes arbitraries en revisiones individuales y entraes del rexistru",
        "action-deletechangetags": "desaniciar etiquetes de la base de datos",
+       "action-purge": "purgar esta páxina",
        "nchanges": "{{PLURAL:$1|un cambiu|$1 cambios}}",
        "enhancedrc-since-last-visit": "$1 {{PLURAL:$1|dende la última visita}}",
        "enhancedrc-history": "historial",
        "watchnologin": "Non identificáu",
        "addwatch": "Amestar a la llista de siguimientu",
        "addedwatchtext": "«[[:$1]]» y la so páxina d'alderique amestáronse a la to [[Special:Watchlist|llista de siguimientu]].",
+       "addedwatchtext-talk": "«[[:$1]]» y la so páxina asociada amestáronse a la to [[Special:Watchlist|llista de siguimientu]].",
        "addedwatchtext-short": "Amestóse la páxina «$1» a la to llista de siguimientu.",
        "removewatch": "Desaniciar de la llista de siguimientu",
        "removedwatchtext": "«[[:$1]]» y la so páxina d'alderique desaniciáronse de la to [[Special:Watchlist|llista de siguimientu]].",
+       "removedwatchtext-talk": "«[[:$1]]» y la so páxina asociada desaniciáronse de la to [[Special:Watchlist|llista de siguimientu]].",
        "removedwatchtext-short": "Desanicióse la páxina «$1» de la to llista de siguimientu.",
        "watch": "Vixilar",
        "watchthispage": "Vixilar esta páxina",
        "undeletedrevisions": "{{PLURAL:$1|1 revisión restaurada|$1 revisiones restauraes}}",
        "undeletedrevisions-files": "{{PLURAL:$1|1 revisión|$1 revisiones}} y {{PLURAL:$2|1 archivu|$2 archivos}} restauraos",
        "undeletedfiles": "{{PLURAL:$1|1 archivu restauráu|$1 archivos restauraos}}",
-       "cannotundelete": "Falló la restauración:\n$1",
+       "cannotundelete": "Falló total o parcialmente la restauración:\n$1",
        "undeletedpage": "'''Restauróse $1'''\n\nConsulta'l [[Special:Log/delete|rexistru d'esborraos]] pa ver los esborraos y restauraciones de recién.",
        "undelete-header": "Mira nel [[Special:Log/delete|rexistru d'esborraos]] les páxines esborraes recién.",
        "undelete-search-title": "Buscar páxines desaniciaes",
        "sp-contributions-newbies-sub": "Namái les cuentes nueves",
        "sp-contributions-newbies-title": "Contribuciones d'usuariu pa cuentes nueves",
        "sp-contributions-blocklog": "rexistru de bloqueos",
-       "sp-contributions-suppresslog": "collaboraciones del usuariu desaniciaes",
-       "sp-contributions-deleted": "Contribuciones d'usuariu desaniciaes",
+       "sp-contributions-suppresslog": "collaboraciones {{GENDER:$1|del usuariu|de la usuaria}} suprimíes",
+       "sp-contributions-deleted": "collaboraciones {{GENDER:$1|del usuariu|de la usuaria}} desaniciaes",
        "sp-contributions-uploads": "xubes",
        "sp-contributions-logs": "rexistros",
        "sp-contributions-talk": "alderique",
        "authform-notoken": "Falta token",
        "authform-wrongtoken": "Token incorreutu",
        "specialpage-securitylevel-not-allowed-title": "Nun ta permitío",
+       "authpage-cannot-login": "Nun pudo empecipiase l'aniciu de sesión.",
+       "authpage-cannot-login-continue": "Nun pudo siguise col aniciu de sesión. Probablemente la sesión caducó.",
+       "authpage-cannot-create": "Nun pudo empecipiase la creación de la cuenta.",
        "cannotauth-not-allowed-title": "Permisu refugáu",
        "cannotauth-not-allowed": "Nun tienes permisu pa usar esta páxina",
        "credentialsform-account": "Nome de la cuenta:",
index fdb5b84..f89f294 100644 (file)
        "passwordreset-emailelement": "Імя ўдзельніка: \n$1\n\nЧасовы пароль: \n$2",
        "passwordreset-emailsentemail": "Калі гэты адрас электроннай пошты злучаны з вашым уліковым запісам, будзе адпраўлены ліст пра скід пароля.",
        "passwordreset-emailsentusername": "Калі ёсць адрас электроннай пошты, злучаны з гэтым імем удзельніка, то будзе дасланы ліст пра скід пароля.",
-       "passwordreset-emailsent-capture": "Ніжэй прыведзены адпраўлены ліст пра скід пароля.",
-       "passwordreset-emailerror-capture": "Ніжэй прыведзены створаны ліст пра скід пароля, яго адпраўка не атрымалася па прычыне: $1",
        "passwordreset-invalideamil": "Няслушны адрас электроннай пошты",
        "passwordreset-nodata": "Не былі пададзены ні імя ўдзельніка, ні адрас электроннай пошты",
        "changeemail": "Змяніць або выдаліць адрас электроннай пошты",
        "changeemail-header": "Запоўніце гэтую форму, каб змяніць свой адрас электроннай пошты. Калі хочаце выдаліць адрас электроннай пошты, злучаны з вашым уліковым запісам, пакіньце поле новага адраса электроннай пошты пустым пры адпраўцы формы.",
-       "changeemail-passwordrequired": "Вам трэба будзе ўвесці свой пароль, каб пацвердзіць гэта змяненне.",
        "changeemail-no-info": "Каб звяртацца непасрэдна да гэтай старонкі, вам варта прадставіцца сістэме.",
        "changeemail-oldemail": "Бягучы адрас электроннай пошты:",
        "changeemail-newemail": "Новы адрас электроннай пошты:",
        "undo-nochange": "Выглядае на тое, што праўка ўжо была адкочаная.",
        "undo-summary": "Адкат версіі $1 аўтарства [[Special:Contributions/$2|$2]] ([[User talk:$2|размова]])",
        "undo-summary-username-hidden": "Адкат версіі $1 схаванага ўдзельніка",
-       "cantcreateaccounttitle": "Немагчыма стварыць рахунак",
        "cantcreateaccount-text": "Стварэнне рахункаў было забаронена для гэтага адрасу IP ('''$1''').\n\nЗабарона зроблена ўдзельнікам [[User:$3|$3]], з такім тлумачэннем: ''$2''",
        "cantcreateaccount-range-text": "Стварэнне ўліковага запісу ўдзельніка з IP-адрасоў у дыяпазоне <strong>$1</strong>, што ўключае ваш адрас IP (<strong>$4</strong>), было забаронена {{GENDER:$3|ўдзельнікам|ўдзельніцай}} [[User:$3|$3]].\n\n$3 {{GENDER:$3|патлумачыў|патлумачыла}} гэта так: <em>$2</em>",
        "viewpagelogs": "Паказаць журналы для гэтай старонкі",
        "special-characters-title-endash": "кароткі працяжнік",
        "special-characters-title-emdash": "доўгі працяжнік",
        "special-characters-title-minus": "мінус",
+       "mw-widgets-dateinput-no-date": "Дата не выбрана",
+       "mw-widgets-titleinput-description-new-page": "старонка яшчэ не існуе",
+       "mw-widgets-titleinput-description-redirect": "перанакіраванне на $1",
        "log-action-filter-all": "Усе",
        "log-action-filter-block-block": "заблакаваць",
        "log-action-filter-block-reblock": "Змена блакіроўкі",
index 97596c4..4921d09 100644 (file)
        "log-action-filter-rights-autopromote": "স্বয়ংক্রিয় পরিবর্তন",
        "log-action-filter-upload-upload": "নতুন আপলোড",
        "log-action-filter-upload-overwrite": "পুনঃআপলোড",
+       "authmanager-create-from-login": "আপনার একাউন্ট তৈরি করতে, নীচের ক্ষেত্রগুলি পূরণ করুন।",
        "authmanager-authplugin-setpass-failed-title": "পাসওয়ার্ড পরিবর্তন ব্যর্থ হয়েছে",
        "authmanager-authplugin-setpass-bad-domain": "অবৈধ ডোমেইন।",
        "authmanager-autocreate-noperm": "স্বয়ংক্রিয় অ্যাকাউন্ট সৃষ্টি মঞ্জুরিপ্রাপ্ত নয়।",
index ae2cd38..af785a0 100644 (file)
        "august-date": "Tebaxe $1",
        "september-date": "Keşkelun $1",
        "october-date": "Tışrino Verên $1",
-       "november-date": "$1 Kelverdan",
+       "november-date": "Tışrino Peyên $1",
        "december-date": "Kanun $1",
        "period-am": "AM",
        "period-pm": "PM",
        "redirectedfrom": "($1 ra kırışı yê)",
        "redirectpagesub": "Pela berdışi",
        "redirectto": "Beno hetê:",
-       "lastmodifiedat": "Ena pele tewr peyên roca $1, seate $2 de rocneya.",
+       "lastmodifiedat": "Ena pele tewr peyên roca $1, saeta $2 de biye rocane.",
        "viewcount": "Ena pele {{PLURAL:$1|rae|$1 rey}} vêniya.",
        "protectedpage": "Pela pawıtiye",
        "jumpto": "Şo be:",
        "anonymous": "{{PLURAL:$1|karberê|karberê}} anonimi yê keyepelê {{SITENAME}}i",
        "siteuser": "karberê {{SITENAME}}i $1",
        "anonuser": "karberê anonim o {{SITENAME}}i $1",
-       "lastmodifiedatby": "Ena pele tewr peyên roca $2, $1 de tereftê $3 ra vuriya ya.",
+       "lastmodifiedatby": "Ena per tewr peyên roca $2, $1 de terefê $3 ra vurmaya ya.",
        "othercontribs": "xebatê $1 ıney geriyayo diqqeti/geriyayo nezer.",
        "others": "bini",
        "siteusers": "{{SITENAME}} {{PLURAL:$2|karberê ey|karberanê ey}} $1",
index cf5710a..e1c37c8 100644 (file)
        "grant-group-high-volume": "Perform high volume activity",
        "grant-group-customization": "Customization and preferences",
        "grant-group-administration": "Perform administrative actions",
+       "grant-group-private-information": "Access private data about you",
        "grant-group-other": "Miscellaneous activity",
        "grant-blockusers": "Block and unblock users",
        "grant-createaccount": "Create accounts",
        "grant-highvolume": "High-volume editing",
        "grant-oversight": "Hide users and suppress revisions",
        "grant-patrol": "Patrol changes to pages",
+       "grant-privateinfo": "Access private information",
        "grant-protect": "Protect and unprotect pages",
        "grant-rollback": "Rollback changes to pages",
        "grant-sendemail": "Send email to other users",
index dbc0cf1..cfdb0bb 100644 (file)
        "tmp-create-error": "Impossible de créer le fichier temporaire.",
        "tmp-write-error": "Erreur d'écriture du fichier temporaire.",
        "large-file": "Les fichiers importés ne devraient pas dépasser $1 ; ce fichier fait $2.",
-       "largefileserver": "La taille de ce fichier est supérieure au maximum autorisé.",
+       "largefileserver": "La taille de ce fichier est supérieure au maximum autorisé par le serveur.",
        "emptyfile": "Le fichier que vous voulez importer semble vide.\nCeci peut être dû à une erreur dans le nom du fichier.\nVeuillez vérifier que vous désirez vraiment importer ce fichier.",
        "windows-nonascii-filename": "Ce wiki ne supporte pas les noms de fichiers avec des caractères spéciaux.",
        "fileexists": "Un fichier existe déjà sous ce nom.\nMerci de vérifier <strong>[[:$1]]</strong> si vous n'êtes pas certain{{GENDER:||e|}} de vouloir le remplacer.\n[[$1|thumb]]",
-       "filepageexists": "La page de description pour ce fichier a déjà été créée ici <strong>[[:$1]]</strong>, mais aucun fichier n'existe actuellement sous ce nom.\nLe résumé que vous allez spécifier n'apparaîtra pas sur la page de description.\nPour que ce soit le cas, vous devrez modifier manuellement la page. [[$1|thumb]]",
+       "filepageexists": "La page de description pour ce fichier a déjà été créée ici <strong>[[:$1]]</strong>, mais aucun fichier n'existe actuellement sous ce nom.\nLe résumé que vous allez spécifier n'apparaîtra pas sur la page de description.\nPour que ce soit le cas, vous devrez modifier manuellement la page. \n[[$1|thumb]]",
        "fileexists-extension": "Un fichier existe avec un nom proche : [[$2|thumb]]\n* Nom du fichier à importer : <strong>[[:$1]]</strong>\n* Nom du fichier existant : <strong>[[:$2]]</strong>\nPeut-être voulez-vous utiliser un nom plus explicite ?",
        "fileexists-thumbnail-yes": "Le fichier semble être une image en taille réduite <em>(vignette)</em>. \n[[$1|thumb]]\nVeuillez vérifier le fichier <strong>[[:$1]]</strong>.\nSi le fichier vérifié est la même image avec la taille initiale, il n'y a pas besoin d'importer une version réduite.",
        "file-thumbnail-no": "Le nom du fichier commence par <strong>$1</strong>.\nIl est possible qu'il s'agisse d'une version réduite <em>(vignette)</em>.\nSi vous disposez du fichier en haute résolution, importez-le, sinon veuillez modifier son nom.",
        "apisandbox-fullscreen-tooltip": "Étendre le panneau du bac à sable pour remplir la fenêtre du navigateur.",
        "apisandbox-unfullscreen": "Afficher la page",
        "apisandbox-unfullscreen-tooltip": "Réduire le panneau du bac à sable, pour que les liens de navigation de MediaWiki soient disponibles.",
-       "apisandbox-submit": "Faire la demande",
+       "apisandbox-submit": "Envoyer la requête",
        "apisandbox-reset": "Effacer",
        "apisandbox-retry": "Réessayer",
        "apisandbox-loading": "Chargement des informations du module \"$1\" de l'API...",
index 10bb66a..5d7b797 100644 (file)
@@ -22,7 +22,8 @@
                        "VaiPolaSombra",
                        "Macofe",
                        "Banjo",
-                       "Josep Maria Roca Peña"
+                       "Josep Maria Roca Peña",
+                       "Luan"
                ]
        },
        "tog-underline": "Subliñar as ligazóns:",
index 84e13ef..d12fc51 100644 (file)
        "tags-active-yes": "כן",
        "tags-active-no": "לא",
        "tags-source-extension": "הוגדר על־ידי הרחבה",
-       "tags-source-manual": "×\94וחל באופן ידני על־ידי משתמשים ובוטים",
+       "tags-source-manual": "×\9eוחל באופן ידני על־ידי משתמשים ובוטים",
        "tags-source-none": "אינו בשימוש כעת",
        "tags-edit": "עריכה",
        "tags-delete": "מחיקה",
index 72788b3..c4ebf7c 100644 (file)
        "undeletedrevisions": "{{PLURAL:$1|Una versione recuperata|$1 versioni recuperate}}",
        "undeletedrevisions-files": "{{PLURAL:$1|Una versione|$1 versioni}} e $2 file recuperati",
        "undeletedfiles": "{{PLURAL:$1|Un file recuperato|$1 file recuperati}}",
-       "cannotundelete": "Ripristino non riuscito:\n$1",
+       "cannotundelete": "Alcuni o tutti i ripristini non riusciti:\n$1",
        "undeletedpage": "'''La pagina $1 è stata recuperata'''\n\nConsulta il [[Special:Log/delete|registro delle cancellazioni]] per vedere le cancellazioni e i recuperi più recenti.",
        "undelete-header": "Consulta il [[Special:Log/delete|registro delle cancellazioni]] per vedere le cancellazioni più recenti.",
        "undelete-search-title": "Ricerca nelle pagine cancellate",
index 491e492..321c5d4 100644 (file)
        "undeletehistorynoadmin": "このページは削除されています。\n削除の理由は、削除前にこのページを編集していた利用者の詳細情報と共に、以下に表示されています。\n管理者以外の利用者には、削除された各版の本文への制限がかけられています。",
        "undelete-revision": "削除されたページ $1 の $4 $5 時点での $3 による版:",
        "undeleterevision-missing": "無効または存在しない版です。\n間違ったリンクをたどったか、この版は既に復元されたか、もしくは保存版から除去された可能性があります。",
+       "undeleterevision-duplicate-revid": "<code>rev_id</code> は既に使用されているため、{{PLURAL:$1|1件の版|$1件の版}}を復元できませんでした。",
        "undelete-nodiff": "これより前の版はありません。",
        "undeletebtn": "復元",
        "undeletelink": "閲覧/復元",
        "undeletedrevisions": "{{PLURAL:$1|$1版}}を復元しました",
        "undeletedrevisions-files": "{{PLURAL:$1|$1版}}と{{PLURAL:$2|$2ファイル}}を復元しました",
        "undeletedfiles": "{{PLURAL:$1|$1ファイル}}を復元しました",
-       "cannotundelete": "復元に失敗しました:\n$1",
+       "cannotundelete": "復元に一部またはすべて失敗しました:\n$1",
        "undeletedpage": "<strong>$1を復元しました。</strong>\n\n最近の削除と復元の記録については[[Special:Log/delete|削除記録]]を参照してください。",
        "undelete-header": "最近削除されたページは[[Special:Log/delete|削除記録]]で確認できます。",
        "undelete-search-title": "削除されたページの検索",
index f3a6409..2402224 100644 (file)
        "listfiles_thumb": "Gambar mini",
        "listfiles_date": "Tanggal",
        "listfiles_name": "Jeneng",
-       "listfiles_user": "Panganggo",
+       "listfiles_user": "Naraguna",
        "listfiles_size": "Ukuran (bita)",
        "listfiles_description": "Dèskripsi",
        "listfiles_count": "Vèrsi",
        "filehist-thumb": "Gambar cilik",
        "filehist-thumbtext": "Gambar cilik kanggo owahan $1",
        "filehist-nothumb": "Ora ana miniatur",
-       "filehist-user": "Panganggo",
+       "filehist-user": "Naraguna",
        "filehist-dimensions": "Alang ujur",
        "filehist-filesize": "Gedhené berkas",
        "filehist-comment": "Tanggapan",
        "blocklogpage": "Log pamblokiran",
        "blocklog-showlog": "Panganggo iki wis tau diblokir sakdurungé.\nLog blokiran sumadhiya nèng ngisor kanggo rujukan:",
        "blocklog-showsuppresslog": "Panganggo iki wis tau diblokir lan didhelikaké sakdurungé.\nLog brèdèlan sumadhiya nèng ngisor kanggo rujukan:",
-       "blocklogentry": "mblokir \"[[$1]]\" dipun watesi wekdalipun $2 $3",
-       "reblock-logentry": "Ngowahi sèting pamblokiran [[$1]] kanthi wektu daluwarsa $2 $3",
+       "blocklogentry": "mblokir [[$1]] kanthi wektu kadaluwarsa $2 $3",
+       "reblock-logentry": "ngowah setèlan blokir tumrap [[$1]] kanthi wektu kadaluwarsa $2 $3",
        "blocklogtext": "Ing ngisor iki kapacak log pamblokiran lan panjabelan blokir panganggo.\nAlamat IP sing diblokir sacara otomatis ora ana ing daftar iki.\nMangga mirsani [[Special:BlockList|daftar panganggo sing diblokir]] kanggo daftar blokir pungkasan.",
        "unblocklogentry": "njabel blokir \"$1\"",
        "block-log-flags-anononly": "namung panganggo anonim waé",
        "block-log-flags-hiddenname": "jeneng panganggo didhelikaké",
        "range_block_disabled": "Fungsi pamblokir blok IP kanggo para opsis dipatèni.",
        "ipb_expiry_invalid": "Wektu kadaluwarsa ora absah.",
+       "ipb_expiry_old": "Wektu kadaluwarsa ana ing nguni.",
        "ipb_expiry_temp": "Pamblokiran tumrap jeneng panganggo sing didhelikaké kudu permanèn.",
        "ipb_hide_invalid": "Ora bisa ndhelikaké akun iki; manawa wis kakèhan suntingan.",
        "ipb_already_blocked": "\"$1\" wis diblokir",
        "revdelete-uname-unhid": "jeneng panganggo dituduhaké",
        "revdelete-restricted": "rèstriksi ditrapaké marang para opsis",
        "revdelete-unrestricted": "rèstriksi marang para opsis dijabel",
+       "logentry-block-block": "$1 {{GENDER:$2|mblokir}} {{GENDER:$4|$3}} kanthi wektu kadaluwarsa $5 $6",
+       "logentry-block-reblock": "$1 {{GENDER:$2|ngowah}} setèlan blokir tumrap {{GENDER:$4|$3}} kanthi wektu kadaluwarsa $5 $6",
+       "logentry-suppress-block": "$1 {{GENDER:$2|mblokir}} {{GENDER:$4|$3}} kanthi wektu kadaluwarsa $5 $6",
+       "logentry-suppress-reblock": "$1 {{GENDER:$2|ngowah}} setèlan blokir tumrap {{GENDER:$4|$3}} kanthi wektu kadaluwarsa $5 $6",
        "logentry-move-move": "$1 {{GENDER:$2|ngalih}} kaca $3 nyang $4",
        "logentry-move-move-noredirect": "$1 {{GENDER:$2|mindhahaké}} kaca $3 nèng $4 tanpa ninggalaké pangalihan",
        "logentry-move-move_redir": "$1 {{GENDER:$2|mindhahaké}} kaca $3 nèng $4 nindesi pangalihan liyane",
index 995237c..ad0b104 100644 (file)
        "nocookiesnew": "De Benotzerkont gouf ugeluecht, awer Dir sidd net ageloggt.\n{{SITENAME}} brauch fir dës Funktioun Cookien.\nDir hutt d'Cookien desaktivéiert.\nAktivéiert déi w.e.g. a loggt Iech da mat Ärem neie Benotzernomm a mat dem respektive Passwuert an.",
        "nocookieslogin": "{{SITENAME}} benotzt Cookië beim Umelle vun de Benotzer.\nDir hutt Cookien ausgeschalt.\nAktivéiert d'Cookien w.e.g. a versicht et nach eng Kéier.",
        "nocookiesfornew": "De Benotzerkont gouf net ugeluecht, well mir seng Quell net bestëmme konnten.\nVergewëssert Iech datt Dir Cookien zouloosst, luet dës Säit nei a probéiert nach emol.",
+       "createacct-loginerror": "De Benotzerkont gouf ugeluecht, mä Dir konnt net automatesch ageloggt ginn. [[Special:UserLogin|Loggt Iech w.e.g. manuell an]].",
        "noname": "Dir hutt kee gëltege Benotzernumm uginn.",
        "loginsuccesstitle": "Ageloggt",
        "loginsuccess": "'''Dir sidd elo als \"$1\" op {{SITENAME}} ugemellt.'''",
        "botpasswords-label-cancel": "Ofbriechen",
        "botpasswords-label-delete": "Läschen",
        "botpasswords-label-resetpassword": "D'Passwuert zrécksetzen",
+       "botpasswords-help-grants": "All Berechtegung gëtt Zougang op déi Benotzerrechter déi e Benotzerkont schonn huet. Kuckt d'[[Special:ListGrants|Tabell vun de Berechtigunge]] fir méi Informatiounen.",
        "botpasswords-label-restrictions": "Limite fir d'Benotzen:",
        "botpasswords-label-grants-column": "Accordéiert",
        "botpasswords-bad-appid": "Den Numm vum Bot \"$1\" ass net valabel.",
        "botpasswords-insert-failed": "De Botnumm \"$1\" konnt net dobäigesat ginn. Gouf e schonn derbäigesat?",
+       "botpasswords-created-title": "Botpasswuert ugeluecht",
        "botpasswords-created-body": "D'Botpasswuert fir de Bot-Numm \"$1\" vum Benotzer ''$2'' gouf ugeluecht.",
        "botpasswords-updated-title": "Botpasswuert aktualiséiert",
        "botpasswords-updated-body": "D'Botpasswuert fir de Bot-Numm \"$1\" vum Benotzer ''$2'' gouf aktualiséiert.",
        "botpasswords-deleted-title": "Botpasswuert geläscht",
        "botpasswords-deleted-body": "D'Botpasswuert fir de Bot-Numm \"$1\" vum Benotzer ''$2'' gouf geläscht.",
+       "botpasswords-newpassword": "Dat neit Passwuert fir sech mat <strong>$1</strong> anzeloggen ass <strong>$2</strong>.\n<em>Versuergt dat fir sech spéider dorop ze referéieren.</em>",
        "botpasswords-not-exist": "De Benotzer \"$1\" huet kee Botpasswuert mam Numm \"$2\".",
        "resetpass_forbidden": "Passwierder kënnen net geännert ginn.",
        "resetpass_forbidden-reason": "Passwierder kënnen net geännert ginn: $1",
        "right-createpage": "Säiten uleeën (déi keng Diskussiounssäite sinn)",
        "right-createtalk": "Diskussiounssäiten uleeën",
        "right-createaccount": "Nei Benotzerkonten uleeën",
+       "right-autocreateaccount": "Automatesch alogge mat engem externe Benotzerkont",
        "right-minoredit": "Ännerungen als kleng markéieren",
        "right-move": "Säite réckelen",
        "right-move-subpages": "Säiten zesumme mat hiren Ënnersäite réckelen",
index f50e348..a4514e7 100644 (file)
        "content-model-css": "CSS",
        "content-json-empty-object": "Objeto vazio",
        "content-json-empty-array": "Array vazia",
+       "deprecated-self-close-category": "Páginas com etiquetas HTML de autofechamento não válidas",
        "duplicate-args-warning": "<strong> Aviso: </strong> [[:$1]] está chamando [[:$2]] com mais de um valor para o parâmetro \"$3\". Será utilizado apenas o último valor fornecido.",
        "duplicate-args-category": "Páginas com argumentos de predefinições duplicados",
        "duplicate-args-category-desc": "A pagina contem modelos que usam argumentos duplicados, como <code><nowiki>{{foo|bar=1|bar=2}}</nowiki></code> ou <code><nowiki>{{foo|bar|1=baz}}</nowiki></code>.",
index 4db45fc..85894af 100644 (file)
        "content-model-css": "CSS",
        "content-json-empty-object": "Objeto vazio",
        "content-json-empty-array": "Matriz vazia",
+       "deprecated-self-close-category": "Páginas com etiquetas HTML de autofechamento não válidas",
        "duplicate-args-warning": "<strong>Aviso:</strong> [[:$1]] chama [[:$2]] com mais de um valor para o parâmetro \"$3\". Somente o último valor fornecido será utilizado.",
        "duplicate-args-category": "Páginas com argumentos de predefinições duplicados",
        "duplicate-args-category-desc": "A página contém campos de predefinições que utilizam duplicatas de argumentos, tais como <code><nowiki>{{foo|bar=1|bar=2}}</nowiki></code> ou <code><nowiki>{{foo|bar|1=baz}}</nowiki></code>.",
index 2f315e8..998511d 100644 (file)
        "right-applychangetags": "{{doc-right|applychangetags}}",
        "right-changetags": "{{doc-right|changetags}}",
        "right-deletechangetags": "{{doc-right|deletechangetags}}",
-       "grant-generic": "Used if the grant name is not defined. Parameters:\n* $1 - grant name\n\nDefined grants (grant name refers: blockusers, createeditmovepage, ...):\n* {{msg-mw|grant-checkuser}}\n* {{msg-mw|grant-blockusers}}\n* {{msg-mw|grant-createaccount}}\n* {{msg-mw|grant-createeditmovepage}}\n* {{msg-mw|grant-delete}}\n* {{msg-mw|grant-editinterface}}\n* {{msg-mw|grant-editmycssjs}}\n* {{msg-mw|grant-editmyoptions}}\n* {{msg-mw|grant-editmywatchlist}}\n* {{msg-mw|grant-editpage}}\n* {{msg-mw|grant-editprotected}}\n* {{msg-mw|grant-highvolume}}\n* {{msg-mw|grant-oversight}}\n* {{msg-mw|grant-patrol}}\n* {{msg-mw|grant-protect}}\n* {{msg-mw|grant-rollback}}\n* {{msg-mw|grant-sendemail}}\n* {{msg-mw|grant-uploadeditmovefile}}\n* {{msg-mw|grant-uploadfile}}\n* {{msg-mw|grant-basic}}\n* {{msg-mw|grant-viewdeleted}}\n* {{msg-mw|grant-viewmywatchlist}}",
+       "grant-generic": "Used if the grant name is not defined. Parameters:\n* $1 - grant name\n\nDefined grants (grant name refers: blockusers, createeditmovepage, ...):\n* {{msg-mw|grant-checkuser}}\n* {{msg-mw|grant-blockusers}}\n* {{msg-mw|grant-createaccount}}\n* {{msg-mw|grant-createeditmovepage}}\n* {{msg-mw|grant-delete}}\n* {{msg-mw|grant-editinterface}}\n* {{msg-mw|grant-editmycssjs}}\n* {{msg-mw|grant-editmyoptions}}\n* {{msg-mw|grant-editmywatchlist}}\n* {{msg-mw|grant-editpage}}\n* {{msg-mw|grant-editprotected}}\n* {{msg-mw|grant-highvolume}}\n* {{msg-mw|grant-oversight}}\n* {{msg-mw|grant-patrol}}\n* {{msg-mw|grant-privateinfo}}\n* {{msg-mw|grant-protect}}\n* {{msg-mw|grant-rollback}}\n* {{msg-mw|grant-sendemail}}\n* {{msg-mw|grant-uploadeditmovefile}}\n* {{msg-mw|grant-uploadfile}}\n* {{msg-mw|grant-basic}}\n* {{msg-mw|grant-viewdeleted}}\n* {{msg-mw|grant-viewmywatchlist}}",
        "grant-group-page-interaction": "{{Related|grant-group}}",
        "grant-group-file-interaction": "{{Related|grant-group}}",
        "grant-group-watchlist-interaction": "{{Related|grant-group}}",
        "grant-group-high-volume": "{{Related|Grant-group}}",
        "grant-group-customization": "{{Related|Grant-group}}",
        "grant-group-administration": "{{Related|Grant-group}}",
+       "grant-group-private-information": "{{Related|Grant-group}}",
        "grant-group-other": "{{Related|Grant-group}}",
        "grant-blockusers": "Name for grant \"blockusers\".\n{{Related|Grant}}",
        "grant-createaccount": "Name for grant \"createaccount\".\n{{Related|grant}}",
        "grant-editprotected": "Name for grant \"editprotected\".\n{{Related|grant}}",
        "grant-highvolume": "Name for grant \"highvolume\".\n{{Related|grant}}",
        "grant-oversight": "Name for grant \"oversight\".\n{{Related|grant}}",
+       "grant-privateinfo": "Name for grant \"privateinfo\".\n{{Related|grant}}",
        "grant-patrol": "Name for grant \"patrol\".\n{{Related|grant}}",
        "grant-protect": "Name for grant \"protect\".\n{{Related|grant}}",
        "grant-rollback": "Name for grant \"rollback\".\n{{Related|grant}}",
        "tags-active-yes": "Table cell contents if given tag is \"active\".\n\nSee also:\n* {{msg-mw|Tags-active-no}}\n{{Identical|Yes}}",
        "tags-active-no": "Table cell contents if given tag is not \"active\".\n\nSee also:\n* {{msg-mw|Tags-active-yes}}\n{{Identical|No}}",
        "tags-source-extension": "Table cell contents if given tag can be applied automatically by a software [[mw:Manual:Extensions|extension]].\n\nSee also:\n* {{msg-mw|Tags-source-manual}}\n* {{msg-mw|Tags-source-none}}",
-       "tags-source-manual": "Table cell contents if given tag can be applied by users or bots.\n\nSee also:\n* {{msg-mw|Tags-source-extension}}\n* {{msg-mw|Tags-source-none}}",
+       "tags-source-manual": "\"Applied\" is not past tense, but an adjective that describes an action that sometimes happens, as in the sentence: \"(this tag is usually) applied by users and bots\".\n\nTable cell contents if given tag can be applied by users or bots.\n\nSee also:\n* {{msg-mw|Tags-source-extension}}\n* {{msg-mw|Tags-source-none}}",
        "tags-source-none": "Table cell contents if given tag is no longer in use. (It was applied in the past, but it is currently not applied.)\n\nSee also:\n* {{msg-mw|Tags-source-extension}}\n* {{msg-mw|Tags-source-manual}}",
        "tags-edit": "Used on [[Special:Tags]]. Verb. Used as display text on a link to create/edit a description.\n{{Identical|Edit}}",
        "tags-delete": "Used on [[Special:Tags]]. Verb. Used as display text on a link to delete a tag.\n{{Identical|Delete}}",
index 87c4234..ff8f1de 100644 (file)
@@ -32,7 +32,8 @@
                        "Roonyh",
                        "Matma Rex",
                        "SusithCM",
-                       "Sandaru"
+                       "Sandaru",
+                       1100100
                ]
        },
        "tog-underline": "සබැඳි යටීර කිරීම:",
        "userlogout": "නික්මීම",
        "notloggedin": "ප්‍රවිසී නැත",
        "userlogin-noaccount": "ගිණුමක් නොමැතිද?",
-       "userlogin-joinproject": "{{SITENAME}}හා එක්වන්න",
+       "userlogin-joinproject": "{{SITENAME}} හා එක්වන්න",
        "nologin": "ඔබ හට ගිණුමක් නොමැතිද? '''$1'''.",
        "nologinlink": "ගිණුමක් තනන්න",
        "createaccount": "අලුත් ගිණුමක් තනන්න",
        "passwordreset-emailtext-user": "{{SITENAME}} හි පරිශීලක $1,{{SITENAME}}($4)සඳහා මුරපදය යලි පිහිටුවීමට ඉල්ලා ඇත.\n\n$2\n\n{{PLURAL:$3|මෙම මුරපදය|මෙම මුරපද}}{{PLURAL:$5|එක් දිනකින්|දවස්$5කින්}}කල් ඉකුත් වනු ඇත.\nඔබ දැන් ඇතුළු වී නව මුරපදයක් තේරිය යුතුය.මෙම ඉල්ලීම වෙන කෙනෙකු විසින් හෝ ඔබට ඔබගේ මුල් මුරපදය මතක නම් හෝ ඔබ තව දුරටත් එය වෙනස් කිරීමට අදහස් නොකරයි නම් හෝ ඔබ මෙම පනිවිඩය නොසලකාහැර ඔබගේ පැරණි මුරපදය භාවිතා කරන්න.",
        "passwordreset-emailelement": "පරිශීලක නාමය: \n$1\n\nතාවකාලික මුරපදය: \n$2",
        "passwordreset-emailsentemail": "මුර-පදය නැවත සකස් කිරීම පිළිබඳව විද්‍යුත් තැපෑලක් යවන ලදී.",
-       "passwordreset-emailsent-capture": "මුර-පදය වෙනස් කිරීම පිළිබඳව විද්‍යුත් තැපෑලක් යවන ලදී, එය පහත දැක්වේ.",
-       "passwordreset-emailerror-capture": "සිහිකැඳවුම් ඊ-තැපෑල ජනිත කරනු ලැබූ අතර, එය පහත දැක්වේ, නමුත් එය {{GENDER:$2|}}පරිශීලකයාට යැවීම අසාර්ථක වුනි: $1",
        "changeemail": "විද්‍යුත් තැපෑල වෙනස් කරන්න හෝ ඉවත් කරන්න",
        "changeemail-header": "ගිණුම් විද්‍යුත් තැපැල් ලිපිනය වෙනස් කරන්න",
        "changeemail-no-info": "මෙම පිටුව සෘජු ලෙස සම්ප්‍රවේශය කෙරුමට පළමුව ඔබ ප්‍රවිෂ්ටව සිටිය යුතුය.",
        "undo-nochange": "මෙම සංස්කරණය දැනටමත් අතහැර දමන ලද කර ඇති බව පෙනී යයි.",
        "undo-summary": " [[Special:Contributions/$2|$2]] මගින් සිදුකල  $1 සංශෝධනය අහෝසි කරන්න ([[User talk:$2|සාකච්ඡා]])",
        "undo-summary-username-hidden": "සැඟවුණු පරිශීලකයෙක් විසින් සංශෝධනය $1 අස් කරන්න",
-       "cantcreateaccounttitle": "ගිණුම තැනිය නොහැක",
        "cantcreateaccount-text": "මෙම IP ලිපිනය ('''$1''') මගින් ගිණුම් තැනීම [[User:$3|$3]] විසින් වාරණය කොට ඇත.\n\n$3 විසින් සපයා ඇති හේතුව ''$2'' වේ",
        "cantcreateaccount-range-text": "ඔබේ IP ලිපිනය ('' '$4' '') ද ඇතුළත් වන පරාසය තුළ IP ලිපිනයන් '' '$1', '' සිට ගිණුම් තැනීම  [[User:$3|$3]] විසින් වාරණය කොට ඇත. $3 විසින් දී ඇති හේතුව '' '$2' වේ",
        "viewpagelogs": "මෙම පිටුව පිලිබඳ සටහන් නරඹන්න",
        "special-characters-title-endash": "en තේජස",
        "special-characters-title-emdash": "em තේජස",
        "special-characters-title-minus": "ඍණ ලකුණ",
-       "api-error-blacklisted": "කරුණාකර වෙනස්, විස්තරාත්මක මාතෘකාවක් තෝරන්න.",
        "randomrootpage": "අහඹු මූල පිටුව"
 }
index c2c40dc..20aea78 100644 (file)
        "print": "Yazdır",
        "view": "Görüntüle",
        "view-foreign": "$1 üzerinde gör",
-       "edit": "Değiştir",
+       "edit": "Düzenle",
        "edit-local": "Yerel açıklamayı düzenle",
        "create": "Oluştur",
        "create-local": "Yerel açıklama ekle",
index bc1b34a..94b7fb4 100644 (file)
@@ -71,6 +71,9 @@ class DeprecatedInterfaceFinder extends FileAwareNodeVisitor {
         * indicating that it is a hard-deprecated interface.
         */
        public function isHardDeprecated( PhpParser\Node $node ) {
+               if ( !$node->stmts ) {
+                       return false;
+               }
                foreach ( $node->stmts as $stmt ) {
                        if (
                                $stmt instanceof PhpParser\Node\Expr\FuncCall
@@ -142,7 +145,7 @@ class FindDeprecated extends Maintenance {
                $files = $this->getFiles();
                $chunkSize = ceil( count( $files ) / 72 );
 
-               $parser = new PhpParser\Parser( new PhpParser\Lexer\Emulative );
+               $parser = ( new PhpParser\ParserFactory )->create( PhpParser\ParserFactory::PREFER_PHP7 );
                $traverser = new PhpParser\NodeTraverser;
                $finder = new DeprecatedInterfaceFinder;
                $traverser->addVisitor( $finder );
index bdbb347..aea966f 100644 (file)
@@ -139,6 +139,7 @@ class RefreshImageMetadata extends Maintenance {
                        }
 
                        foreach ( $res as $row ) {
+                               // LocalFile will upgrade immediately here if obsolete
                                $file = $repo->newFileFromRow( $row );
                                if ( $file->getUpgraded() ) {
                                        // File was upgraded.
index 68e0fad..9a9d84d 100644 (file)
@@ -5,7 +5,7 @@ you can override classes used by the installer.
 You can override 3 classes:
 * LocalSettingsGenerator - generates LocalSettings.php
 * WebInstaller - web installer UI
-* CliInstaller - command line installer
+* CliInstaller - command-line installer
 
 Example override:
 
index 9b9d324..b4edc50 100644 (file)
@@ -26,6 +26,7 @@
 
 .mw-ui-icon {
        position: relative;
+       line-height: @iconSize;
        min-height: @iconSize;
        min-width: @iconSize;
 
index 85ded44..3b2c86e 100644 (file)
                var api, title, params,
                        imageSrc = $img.attr( 'src' );
 
+               // Reject promise if there is no thumbnail image
+               if ( $img[ 0 ] === undefined ) {
+                       return $.Deferred().reject();
+               }
+
                if ( this.imageInfoCache[ imageSrc ] === undefined ) {
                        api = new mw.Api();
                        // TODO: This supports only gallery of images