Merge "Initialise array with contents in one go"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Thu, 25 Feb 2016 17:04:23 +0000 (17:04 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Thu, 25 Feb 2016 17:04:23 +0000 (17:04 +0000)
50 files changed:
.jscsrc
autoload.php
includes/LinkTarget.php
includes/Message.php
includes/WatchedItem.php
includes/WatchedItemStore.php [new file with mode: 0644]
includes/content/Content.php
includes/content/MessageContent.php
includes/content/TextContent.php
includes/content/WikitextContent.php
includes/db/IDatabase.php
includes/installer/i18n/sah.json
includes/logging/DeleteLogFormatter.php
includes/logging/PatrolLogFormatter.php
includes/logging/RightsLogFormatter.php
includes/logging/TagLogFormatter.php
includes/media/BMP.php
includes/media/Bitmap.php
includes/media/DjVu.php
includes/media/ImageHandler.php
includes/media/Jpeg.php
includes/media/MediaHandler.php
includes/media/SVG.php
includes/media/Tiff.php
includes/media/XCF.php
includes/session/SessionBackend.php
includes/specials/SpecialActiveusers.php
includes/specials/SpecialEmailuser.php
includes/specials/SpecialVersion.php
languages/i18n/be-tarask.json
languages/i18n/br.json
languages/i18n/ce.json
languages/i18n/en.json
languages/i18n/gom-deva.json
languages/i18n/gom-latn.json
languages/i18n/it.json
languages/i18n/ko.json
languages/i18n/sah.json
languages/i18n/ta.json
languages/i18n/uk.json
languages/i18n/vi.json
resources/lib/oojs-ui/oojs-ui-core.js
resources/src/mediawiki.special/mediawiki.special.apisandbox.css
resources/src/mediawiki.special/mediawiki.special.apisandbox.js
resources/src/mediawiki.ui/components/buttons.less
resources/src/mediawiki/api/upload.js
tests/parser/parserTest.inc
tests/phpunit/includes/WatchedItemStoreTest.php [new file with mode: 0644]
tests/phpunit/mocks/content/DummyContentForTesting.php
tests/phpunit/mocks/content/DummyNonTextContent.php

diff --git a/.jscsrc b/.jscsrc
index 3b94b90..116c5cf 100644 (file)
--- a/.jscsrc
+++ b/.jscsrc
                "checkAnnotations": {
                        "preset": "jsduck5",
                        "extra": {
-                               "context": true,
-                               "source": true,
-                               "see": true,
-                               "private": true
+                               "context": "some",
+                               "source": "some",
+                               "see": "some"
                        }
                },
                "checkParamNames": true,
index 23beaee..5ec6218 100644 (file)
@@ -1402,6 +1402,7 @@ $wgAutoloadLocalClasses = [
        'WantedTemplatesPage' => __DIR__ . '/includes/specials/SpecialWantedtemplates.php',
        'WatchAction' => __DIR__ . '/includes/actions/WatchAction.php',
        'WatchedItem' => __DIR__ . '/includes/WatchedItem.php',
+       'WatchedItemStore' => __DIR__ . '/includes/WatchedItemStore.php',
        'WatchlistCleanup' => __DIR__ . '/maintenance/cleanupWatchlist.php',
        'WebInstaller' => __DIR__ . '/includes/installer/WebInstaller.php',
        'WebInstallerComplete' => __DIR__ . '/includes/installer/WebInstallerComplete.php',
index 1ce5f32..175a839 100644 (file)
@@ -8,29 +8,28 @@
 interface LinkTarget {
 
        /**
-        * Get the namespace index
+        * Get the namespace index.
         *
         * @return int Namespace index
         */
        public function getNamespace();
 
        /**
-        * Get the link fragment (i.e.\ the bit after the #) in text form
+        * Get the link fragment (i.e. the bit after the #) in text form.
         *
         * @return string link fragment
         */
        public function getFragment();
 
        /**
-        * Get the main part with underscores
+        * Get the main part with underscores.
         *
-        * @return string Main part of the link, with underscores (for use in hrf attributes)
+        * @return string Main part of the link, with underscores (for use in href attributes)
         */
        public function getDBkey();
 
        /**
-        * Returns the link in text form,
-        * without namespace prefix or fragment.
+        * Returns the link in text form, without namespace prefix or fragment.
         *
         * This is computed from the DB key by replacing any underscores with spaces.
         *
index 4056f38..9d5f5e6 100644 (file)
@@ -810,7 +810,7 @@ class Message implements MessageSpecifier, Serializable {
 
        /**
         * Magic method implementation of the above (for PHP >= 5.2.0), so we can do, eg:
-        *     $foo = Message::get( $key );
+        *     $foo = new Message( $key );
         *     $string = "<abbr>$foo</abbr>";
         *
         * @since 1.18
index 2c400d0..b597f99 100644 (file)
@@ -379,63 +379,15 @@ class WatchedItem {
        }
 
        /**
-        * Check if the given title already is watched by the user, and if so
-        * add watches on a new title. To be used for page renames and such.
+        * @deprecated since 1.27. See WatchedItemStore::duplicateEntry
         *
-        * @param Title $ot Page title to duplicate entries from, if present
-        * @param Title $nt Page title to add watches on
+        * @param Title $oldTitle
+        * @param Title $newTitle
         */
-       public static function duplicateEntries( $ot, $nt ) {
-               WatchedItem::doDuplicateEntries( $ot->getSubjectPage(), $nt->getSubjectPage() );
-               WatchedItem::doDuplicateEntries( $ot->getTalkPage(), $nt->getTalkPage() );
+       public static function duplicateEntries( Title $oldTitle, Title $newTitle ) {
+               $store = WatchedItemStore::getDefaultInstance();
+               $store->duplicateEntry( $oldTitle->getSubjectPage(), $newTitle->getSubjectPage() );
+               $store->duplicateEntry( $oldTitle->getTalkPage(), $newTitle->getTalkPage() );
        }
 
-       /**
-        * Handle duplicate entries. Backend for duplicateEntries().
-        *
-        * @param Title $ot
-        * @param Title $nt
-        *
-        * @return bool
-        */
-       private static function doDuplicateEntries( $ot, $nt ) {
-               $oldnamespace = $ot->getNamespace();
-               $newnamespace = $nt->getNamespace();
-               $oldtitle = $ot->getDBkey();
-               $newtitle = $nt->getDBkey();
-
-               $dbw = wfGetDB( DB_MASTER );
-               $res = $dbw->select( 'watchlist',
-                       [ 'wl_user', 'wl_notificationtimestamp' ],
-                       [ 'wl_namespace' => $oldnamespace, 'wl_title' => $oldtitle ],
-                       __METHOD__, 'FOR UPDATE'
-               );
-               # Construct array to replace into the watchlist
-               $values = [];
-               foreach ( $res as $s ) {
-                       $values[] = [
-                               'wl_user' => $s->wl_user,
-                               'wl_namespace' => $newnamespace,
-                               'wl_title' => $newtitle,
-                               'wl_notificationtimestamp' => $s->wl_notificationtimestamp,
-                       ];
-               }
-
-               if ( empty( $values ) ) {
-                       // Nothing to do
-                       return true;
-               }
-
-               # Perform replace
-               # Note that multi-row replace is very efficient for MySQL but may be inefficient for
-               # some other DBMSes, mostly due to poor simulation by us
-               $dbw->replace(
-                       'watchlist',
-                       [ [ 'wl_user', 'wl_namespace', 'wl_title' ] ],
-                       $values,
-                       __METHOD__
-               );
-
-               return true;
-       }
 }
diff --git a/includes/WatchedItemStore.php b/includes/WatchedItemStore.php
new file mode 100644 (file)
index 0000000..83a5856
--- /dev/null
@@ -0,0 +1,86 @@
+<?php
+
+/**
+ * Storage layer class for WatchedItems.
+ * Database interaction
+ *
+ * @author Addshore
+ *
+ * @since 1.27
+ */
+class WatchedItemStore {
+
+       /**
+        * @var LoadBalancer
+        */
+       private $loadBalancer;
+
+       public function __construct( LoadBalancer $loadBalancer ) {
+               $this->loadBalancer = $loadBalancer;
+       }
+
+       /**
+        * @return self
+        */
+       public static function getDefaultInstance() {
+               static $instance;
+               if ( !$instance ) {
+                       $instance = new self( wfGetLB() );
+               }
+               return $instance;
+       }
+
+       /**
+        * Check if the given title already is watched by the user, and if so
+        * add a watch for the new title.
+        *
+        * To be used for page renames and such.
+        * This must be called separately for Subject and Talk pages
+        *
+        * @param LinkTarget $oldTarget
+        * @param LinkTarget $newTarget
+        */
+       public function duplicateEntry( LinkTarget $oldTarget, LinkTarget $newTarget ) {
+               $dbw = $this->loadBalancer->getConnection( DB_MASTER, [ 'watchlist' ] );
+
+               $result = $dbw->select(
+                       'watchlist',
+                       [ 'wl_user', 'wl_notificationtimestamp' ],
+                       [
+                               'wl_namespace' => $oldTarget->getNamespace(),
+                               'wl_title' => $oldTarget->getDBkey(),
+                       ],
+                       __METHOD__,
+                       [ 'FOR UPDATE' ]
+               );
+
+               $newNamespace = $newTarget->getNamespace();
+               $newDBkey = $newTarget->getDBkey();
+
+               # Construct array to replace into the watchlist
+               $values = [];
+               foreach ( $result as $row ) {
+                       $values[] = [
+                               'wl_user' => $row->wl_user,
+                               'wl_namespace' => $newNamespace,
+                               'wl_title' => $newDBkey,
+                               'wl_notificationtimestamp' => $row->wl_notificationtimestamp,
+                       ];
+               }
+
+               if ( !empty( $values ) ) {
+                       # Perform replace
+                       # Note that multi-row replace is very efficient for MySQL but may be inefficient for
+                       # some other DBMSes, mostly due to poor simulation by us
+                       $dbw->replace(
+                               'watchlist',
+                               [ [ 'wl_user', 'wl_namespace', 'wl_title' ] ],
+                               $values,
+                               __METHOD__
+                       );
+               }
+
+               $this->loadBalancer->reuseConnection( $dbw );
+       }
+
+}
index 76881bc..931128f 100644 (file)
@@ -243,7 +243,7 @@ interface Content {
         *
         * @since 1.21
         *
-        * @param bool $hasLinks If it is known whether this content contains
+        * @param bool|null $hasLinks If it is known whether this content contains
         *    links, provide this information here, to avoid redundant parsing to
         *    find out.
         *
index e3f9375..4b58989 100644 (file)
@@ -136,7 +136,7 @@ class MessageContent extends AbstractContent {
        }
 
        /**
-        * @param bool $hasLinks
+        * @param bool|null $hasLinks
         *
         * @return bool Always false.
         *
index baea812..225522e 100644 (file)
@@ -92,7 +92,7 @@ class TextContent extends AbstractContent {
         * Returns true if this content is not a redirect, and $wgArticleCountMethod
         * is "any".
         *
-        * @param bool $hasLinks If it is known whether this content contains links,
+        * @param bool|null $hasLinks If it is known whether this content contains links,
         * provide this information here, to avoid redundant parsing to find out.
         *
         * @return bool
index c1fef7c..a63819d 100644 (file)
@@ -258,10 +258,10 @@ class WikitextContent extends TextContent {
         * Returns true if this content is not a redirect, and this content's text
         * is countable according to the criteria defined by $wgArticleCountMethod.
         *
-        * @param bool $hasLinks If it is known whether this content contains
+        * @param bool|null $hasLinks If it is known whether this content contains
         *    links, provide this information here, to avoid redundant parsing to
         *    find out (default: null).
-        * @param Title $title Optional title, defaults to the title from the current main request.
+        * @param Title|null $title Optional title, defaults to the title from the current main request.
         *
         * @return bool
         */
index e1d1173..7855861 100644 (file)
@@ -1334,9 +1334,13 @@ interface IDatabase {
         * @param string $fname
         * @param string $flush Flush flag, set to 'flush' to disable warnings about
         *   explicitly committing implicit transactions, or calling commit when no
-        *   transaction is in progress. This will silently break any ongoing
-        *   explicit transaction. Only set the flush flag if you are sure that it
-        *   is safe to ignore these warnings in your context.
+        *   transaction is in progress.
+        *
+        *   This will trigger an exception if there is an ongoing explicit transaction.
+        *
+        *   Only set the flush flag if you are sure that these warnings are not applicable,
+        *   and no explicit transactions are open.
+        *
         * @throws DBUnexpectedError
         */
        public function commit( $fname = __METHOD__, $flush = '' );
index ab257dd..19969d2 100644 (file)
@@ -1,12 +1,39 @@
 {
        "@metadata": {
                "authors": [
-                       "HalanTul"
+                       "HalanTul",
+                       "Мария Олесова"
                ]
        },
        "config-desc": "MediaWiki инсталлятора",
        "config-title": "MediaWiki $1 туруоруу",
        "config-information": "Бу туһунан",
+       "config-localsettings-key": "Саҥатытыы күлүүһэ:",
+       "config-localsettings-badkey": "Саҥатытыыга сыыһа күлүүһү ыйдыҥ.",
+       "config-your-language-help": "Туруоруу кэмигэр туттуллар тылы тал.",
+       "config-wiki-language": "Биики туттуохтаах тыла:",
+       "config-back": "← Төттөрү",
+       "config-continue": "Салгыы →",
+       "config-page-language": "Тыла",
+       "config-page-dbconnect": "Билии олоҕор холбонуу",
+       "config-page-upgrade": "Баар туруорууну саҥатытыы",
+       "config-page-dbsettings": "Билии олоҕун бэлэмнээһин",
+       "config-page-name": "Аат",
+       "config-page-options": "Туруоруулар",
+       "config-page-install": "Туруоруу",
+       "config-page-complete": "Бэлэм!",
+       "config-page-restart": "Туруорууну саҥаттан саҕалыырга",
+       "config-page-upgradedoc": "Саҥатытыы",
+       "config-page-existingwiki": "Баар биики",
+       "config-help-restart": "Харайыллыбыт көрдөрүүлэри сотуоххун уонна туруоруу кэмин саҥаттан ыытыаххын баҕараҕын дуо?",
+       "config-restart": "Сөп, саҥаттан саҕалыырга",
+       "config-env-good": "Тас кэккэ бэрэбиэркэтэ ситиһиилээхтик ыытылынна. \nMediaWiki туруоруоххун сөп.",
+       "config-db-type": "Билии олоҕун көрүҥэ:",
+       "config-db-wiki-settings": "Бу биики тэҥнэбилэ",
+       "config-db-name": "Билии олоҕун көрүҥэ:",
+       "config-db-name-oracle": "Билии олоҕун исхиэмэтэ:",
+       "config-db-install-account": "Туруорууга учуоттуур суруйуу",
+       "config-db-username": "Билии олоҕун көрүҥэ:",
        "mainpagetext": "'''«MediaWiki» сөпкө туруорулунна.'''",
        "mainpagedocfooter": "Биики программатын туһунан [//meta.wikimedia.org/wiki/Help:Contents справочникка] көрүөххүн сөп.\n\n== Саҕаланыыта ==\n\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings Конфигурация уларытыытын параметрдара]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ MediaWiki FAQ]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce MediaWiki релизтарын почтовай испииһэгэ]"
 }
index 3b470ec..012d53c 100644 (file)
@@ -33,6 +33,8 @@ class DeleteLogFormatter extends LogFormatter {
                $key = parent::getMessageKey();
                if ( in_array( $this->entry->getSubtype(), [ 'event', 'revision' ] ) ) {
                        if ( count( $this->getMessageParameters() ) < 5 ) {
+                               // Messages: logentry-delete-event-legacy, logentry-delete-revision-legacy,
+                               // logentry-suppress-event-legacy, logentry-suppress-revision-legacy
                                return "$key-legacy";
                        }
                }
index 0d007b3..e6f9fb6 100644 (file)
@@ -33,6 +33,7 @@ class PatrolLogFormatter extends LogFormatter {
                $key = parent::getMessageKey();
                $params = $this->getMessageParameters();
                if ( isset( $params[5] ) && $params[5] ) {
+                       // Messages: logentry-patrol-patrol-auto
                        $key .= '-auto';
                }
 
index eebccdd..b9dfb6c 100644 (file)
@@ -53,6 +53,7 @@ class RightsLogFormatter extends LogFormatter {
                $key = parent::getMessageKey();
                $params = $this->getMessageParameters();
                if ( !isset( $params[3] ) && !isset( $params[4] ) ) {
+                       // Messages: logentry-rights-rights-legacy
                        $key .= '-legacy';
                }
 
index b62bcb4..230d13b 100644 (file)
@@ -39,8 +39,12 @@ class TagLogFormatter extends LogFormatter {
                $key .= ( $remove ? ( $add ? '' : '-remove' ) : '-add' );
 
                if ( isset( $params[3] ) && $params[3] ) {
+                       // Messages: logentry-tag-update-add-revision, logentry-tag-update-remove-revision,
+                       // logentry-tag-update-revision
                        $key .= '-revision';
                } else {
+                       // Messages: logentry-tag-update-add-logentry, logentry-tag-update-remove-logentry,
+                       // logentry-tag-update-logentry
                        $key .= '-logentry';
                }
 
index 64f12f7..4b9b268 100644 (file)
@@ -32,7 +32,7 @@ class BmpHandler extends BitmapHandler {
         * @param File $file
         * @return bool
         */
-       function mustRender( $file ) {
+       public function mustRender( $file ) {
                return true;
        }
 
index b470e06..b055d16 100644 (file)
@@ -59,7 +59,7 @@ class BitmapHandler extends TransformationalImageHandler {
                return $scaler;
        }
 
-       function makeParamString( $params ) {
+       public function makeParamString( $params ) {
                $res = parent::makeParamString( $params );
                if ( isset( $params['interlace'] ) && $params['interlace'] ) {
                        return "interlaced-{$res}";
@@ -68,7 +68,7 @@ class BitmapHandler extends TransformationalImageHandler {
                }
        }
 
-       function parseParamString( $str ) {
+       public function parseParamString( $str ) {
                $remainder = preg_replace( '/^interlaced-/', '', $str );
                $params = parent::parseParamString( $remainder );
                if ( $params === false ) {
@@ -78,7 +78,7 @@ class BitmapHandler extends TransformationalImageHandler {
                return $params;
        }
 
-       function validateParam( $name, $value ) {
+       public function validateParam( $name, $value ) {
                if ( $name === 'interlace' ) {
                        return $value === false || $value === true;
                } else {
index 0d2ed29..d4ef8a8 100644 (file)
@@ -47,7 +47,7 @@ class DjVuHandler extends ImageHandler {
         * @param File $file
         * @return bool
         */
-       function mustRender( $file ) {
+       public function mustRender( $file ) {
                return true;
        }
 
@@ -64,14 +64,14 @@ class DjVuHandler extends ImageHandler {
         * @param File $file
         * @return bool
         */
-       function isMultiPage( $file ) {
+       public function isMultiPage( $file ) {
                return true;
        }
 
        /**
         * @return array
         */
-       function getParamMap() {
+       public function getParamMap() {
                return [
                        'img_width' => 'width',
                        'img_page' => 'page',
@@ -83,7 +83,7 @@ class DjVuHandler extends ImageHandler {
         * @param mixed $value
         * @return bool
         */
-       function validateParam( $name, $value ) {
+       public function validateParam( $name, $value ) {
                if ( $name === 'page' && trim( $value ) !== (string)intval( $value ) ) {
                        // Extra junk on the end of page, probably actually a caption
                        // e.g. [[File:Foo.djvu|thumb|Page 3 of the document shows foo]]
@@ -104,7 +104,7 @@ class DjVuHandler extends ImageHandler {
         * @param array $params
         * @return bool|string
         */
-       function makeParamString( $params ) {
+       public function makeParamString( $params ) {
                $page = isset( $params['page'] ) ? $params['page'] : 1;
                if ( !isset( $params['width'] ) ) {
                        return false;
@@ -117,7 +117,7 @@ class DjVuHandler extends ImageHandler {
         * @param string $str
         * @return array|bool
         */
-       function parseParamString( $str ) {
+       public function parseParamString( $str ) {
                $m = false;
                if ( preg_match( '/^page(\d+)-(\d+)px$/', $str, $m ) ) {
                        return [ 'width' => $m[2], 'page' => $m[1] ];
index a7847bb..158c0dc 100644 (file)
@@ -31,15 +31,15 @@ abstract class ImageHandler extends MediaHandler {
         * @param File $file
         * @return bool
         */
-       function canRender( $file ) {
+       public function canRender( $file ) {
                return ( $file->getWidth() && $file->getHeight() );
        }
 
-       function getParamMap() {
+       public function getParamMap() {
                return [ 'img_width' => 'width' ];
        }
 
-       function validateParam( $name, $value ) {
+       public function validateParam( $name, $value ) {
                if ( in_array( $name, [ 'width', 'height' ] ) ) {
                        if ( $value <= 0 ) {
                                return false;
@@ -51,7 +51,7 @@ abstract class ImageHandler extends MediaHandler {
                }
        }
 
-       function makeParamString( $params ) {
+       public function makeParamString( $params ) {
                if ( isset( $params['physicalWidth'] ) ) {
                        $width = $params['physicalWidth'];
                } elseif ( isset( $params['width'] ) ) {
@@ -65,7 +65,7 @@ abstract class ImageHandler extends MediaHandler {
                return "{$width}px";
        }
 
-       function parseParamString( $str ) {
+       public function parseParamString( $str ) {
                $m = false;
                if ( preg_match( '/^(\d+)px$/', $str, $m ) ) {
                        return [ 'width' => $m[1] ];
index 040ff96..b8b6f6c 100644 (file)
@@ -42,7 +42,7 @@ class JpegHandler extends ExifBitmapHandler {
                return true;
        }
 
-       function validateParam( $name, $value ) {
+       public function validateParam( $name, $value ) {
                if ( $name === 'quality' ) {
                        return self::validateQuality( $value );
                } else {
@@ -58,7 +58,7 @@ class JpegHandler extends ExifBitmapHandler {
                return $value === 'low';
        }
 
-       function makeParamString( $params ) {
+       public function makeParamString( $params ) {
                // Prepend quality as "qValue-". This has to match parseParamString() below
                $res = parent::makeParamString( $params );
                if ( $res && isset( $params['quality'] ) ) {
@@ -67,7 +67,7 @@ class JpegHandler extends ExifBitmapHandler {
                return $res;
        }
 
-       function parseParamString( $str ) {
+       public function parseParamString( $str ) {
                // $str contains "qlow-200px" or "200px" strings because thumb.php would strip the filename
                // first - check if the string begins with "qlow-", and if so, treat it as quality.
                // Pass the first portion, or the whole string if "qlow-" not found, to the parent
index 95498ba..6b0f887 100644 (file)
@@ -75,7 +75,7 @@ abstract class MediaHandler {
         * Get an associative array mapping magic word IDs to parameter names.
         * Will be used by the parser to identify parameters.
         */
-       abstract function getParamMap();
+       abstract public function getParamMap();
 
        /**
         * Validate a thumbnail parameter at parse time.
@@ -85,7 +85,7 @@ abstract class MediaHandler {
         * @param string $name
         * @param mixed $value
         */
-       abstract function validateParam( $name, $value );
+       abstract public function validateParam( $name, $value );
 
        /**
         * Merge a parameter array into a string appropriate for inclusion in filenames
@@ -93,7 +93,7 @@ abstract class MediaHandler {
         * @param array $params Array of parameters that have been through normaliseParams.
         * @return string
         */
-       abstract function makeParamString( $params );
+       abstract public function makeParamString( $params );
 
        /**
         * Parse a param string made with makeParamString back into an array
@@ -101,7 +101,7 @@ abstract class MediaHandler {
         * @param string $str The parameter string without file name (e.g. 122px)
         * @return array|bool Array of parameters or false on failure.
         */
-       abstract function parseParamString( $str );
+       abstract public function parseParamString( $str );
 
        /**
         * Changes the parameter array as necessary, ready for transformation.
@@ -342,7 +342,7 @@ abstract class MediaHandler {
         * @param File $file
         * @return bool
         */
-       function canRender( $file ) {
+       public function canRender( $file ) {
                return true;
        }
 
@@ -353,7 +353,7 @@ abstract class MediaHandler {
         * @param File $file
         * @return bool
         */
-       function mustRender( $file ) {
+       public function mustRender( $file ) {
                return false;
        }
 
@@ -363,7 +363,7 @@ abstract class MediaHandler {
         * @param File $file
         * @return bool
         */
-       function isMultiPage( $file ) {
+       public function isMultiPage( $file ) {
                return false;
        }
 
index d570f30..7e77b25 100644 (file)
@@ -51,7 +51,7 @@ class SvgHandler extends ImageHandler {
                }
        }
 
-       function mustRender( $file ) {
+       public function mustRender( $file ) {
                return true;
        }
 
@@ -462,7 +462,7 @@ class SvgHandler extends ImageHandler {
         * @param mixed $value Parameter value
         * @return bool Validity
         */
-       function validateParam( $name, $value ) {
+       public function validateParam( $name, $value ) {
                if ( in_array( $name, [ 'width', 'height' ] ) ) {
                        // Reject negative heights, widths
                        return ( $value > 0 );
@@ -485,7 +485,7 @@ class SvgHandler extends ImageHandler {
         * @param array $params Name=>value pairs of parameters
         * @return string Filename to use
         */
-       function makeParamString( $params ) {
+       public function makeParamString( $params ) {
                $lang = '';
                if ( isset( $params['lang'] ) && $params['lang'] !== 'en' ) {
                        $params['lang'] = strtolower( $params['lang'] );
@@ -498,7 +498,7 @@ class SvgHandler extends ImageHandler {
                return "$lang{$params['width']}px";
        }
 
-       function parseParamString( $str ) {
+       public function parseParamString( $str ) {
                $m = false;
                if ( preg_match( '/^lang([a-z]+(?:-[a-z]+)*)-(\d+)px$/', $str, $m ) ) {
                        return [ 'width' => array_pop( $m ), 'lang' => $m[1] ];
@@ -509,7 +509,7 @@ class SvgHandler extends ImageHandler {
                }
        }
 
-       function getParamMap() {
+       public function getParamMap() {
                return [ 'img_lang' => 'lang', 'img_width' => 'width' ];
        }
 
index 750528f..2e73249 100644 (file)
@@ -40,7 +40,7 @@ class TiffHandler extends ExifBitmapHandler {
         * @param File $file
         * @return bool
         */
-       function canRender( $file ) {
+       public function canRender( $file ) {
                global $wgTiffThumbnailType;
 
                return (bool)$wgTiffThumbnailType
@@ -54,7 +54,7 @@ class TiffHandler extends ExifBitmapHandler {
         * @param File $file
         * @return bool
         */
-       function mustRender( $file ) {
+       public function mustRender( $file ) {
                return true;
        }
 
index 05c3847..f8fa252 100644 (file)
@@ -37,7 +37,7 @@ class XCFHandler extends BitmapHandler {
         * @param File $file
         * @return bool
         */
-       function mustRender( $file ) {
+       public function mustRender( $file ) {
                return true;
        }
 
index 0a9191b..0424a2d 100644 (file)
@@ -572,7 +572,9 @@ final class SessionBackend {
         * @param bool $closing Whether the session is being closed
         */
        public function save( $closing = false ) {
-               if ( $this->provider->getManager()->isUserSessionPrevented( $this->user->getName() ) ) {
+               $anon = $this->user->isAnon();
+
+               if ( !$anon && $this->provider->getManager()->isUserSessionPrevented( $this->user->getName() ) ) {
                        $this->logger->debug(
                                'SessionBackend "{session}" not saving, user {user} was ' .
                                'passed to SessionManager::preventSessionsForUser',
@@ -585,7 +587,6 @@ final class SessionBackend {
 
                // Ensure the user has a token
                // @codeCoverageIgnoreStart
-               $anon = $this->user->isAnon();
                if ( !$anon && !$this->user->getToken( false ) ) {
                        $this->logger->debug(
                                'SessionBackend "{session}" creating token for user {user} on save',
index c06db01..9c5fc2f 100644 (file)
@@ -223,8 +223,10 @@ class ActiveUsersPager extends UsersPager {
                        [
                                'class' => 'mw-ui-input-inline mw-autocomplete-user',
                                'tabindex' => 1,
-                               'autofocus' => $this->requestedUser === '',
-                       ]
+                       ] + (
+                               // Set autofocus on blank input
+                               $this->requestedUser === '' ? [ 'autofocus' => '' ] : []
+                       )
                ) . '<br />';
 
                $out .= Xml::checkLabel( $this->msg( 'activeusers-hidebots' )->text(),
index cdf350d..80ef4b1 100644 (file)
@@ -280,7 +280,7 @@ class SpecialEmailUser extends UnlistedSpecialPage {
                                $name,
                                [
                                        'class' => 'mw-autocomplete-user',  // used by mediawiki.userSuggest
-                                       'autofocus' => true,
+                                       'autofocus' => '',
                                ]
                        ) .
                        ' ' .
index d706786..c0f9590 100644 (file)
@@ -255,9 +255,10 @@ class SpecialVersion extends SpecialPage {
         * Return a string of the MediaWiki version with Git revision if available.
         *
         * @param string $flags
+        * @param Language|string|null $lang
         * @return mixed
         */
-       public static function getVersion( $flags = '' ) {
+       public static function getVersion( $flags = '', $lang = null ) {
                global $wgVersion, $IP;
 
                $gitInfo = self::getGitHeadSha1( $IP );
@@ -268,7 +269,11 @@ class SpecialVersion extends SpecialPage {
                        $version = "$wgVersion ($shortSha1)";
                } else {
                        $shortSha1 = substr( $gitInfo, 0, 7 );
-                       $shortSha1 = wfMessage( 'parentheses' )->params( $shortSha1 )->escaped();
+                       $msg = wfMessage( 'parentheses' );
+                       if ( $lang !== null ) {
+                               $msg->inLanguage( $lang );
+                       }
+                       $shortSha1 = $msg->params( $shortSha1 )->escaped();
                        $version = "$wgVersion $shortSha1";
                }
 
index 1163f67..a149135 100644 (file)
        "grant-group-page-interaction": "Узаемадзеньне з старонкамі",
        "grant-group-file-interaction": "Узаемадзеяньне з мэдыяфайламі",
        "grant-group-watchlist-interaction": "Узаемадзеяньне з вашым сьпісам назіраньня",
+       "grant-group-email": "Адпраўка лістоў электроннай пошты",
        "grant-createaccount": "Стварыць рахункі",
        "grant-createeditmovepage": "Ствараць, рэдагаваць і пераносіць старонкі",
        "grant-delete": "Выдаляць старонкі, вэрсіі і запісы журналу",
index b3dae32..c60e2d8 100644 (file)
        "pool-timeout": "Aet eur dreist d'an termen gortoz evit ar stankadenn",
        "pool-queuefull": "Soulgarget eo ar servijerioù",
        "pool-errorunknown": "Fazi dianav",
+       "poolcounter-usage-error": "Fazi implij : $1",
        "aboutsite": "Diwar-benn {{SITENAME}}",
        "aboutpage": "Project:Diwar-benn",
        "copyright": "Danvez a c'haller implijout dindan $1 nemet ha notet e vefe ar c'hontrol.",
        "filerenameerror": "Dibosupl da adenvel « $1 » e « $2 ».",
        "filedeleteerror": "Dibosupl eo diverkañ « $1 ».",
        "directorycreateerror": "N'eus ket bet gallet krouiñ kavlec'h \"$1\".",
+       "directoryreadonlyerror": "Kavlec'h  «$1» lenn hepken",
+       "directorynotreadableerror": "Ne c'haller ket lenn ar c'havlec'h « $1 ».",
        "filenotfound": "N'haller ket kavout ar restr \"$1\".",
        "unexpected": "Talvoudenn dic'hortoz : \"$1\"=\"$2\".",
        "formerror": "Fazi: Dibosupl eo kinnig ar furmskrid",
        "resetpass_submit": "Cheñch ar ger-tremen ha kevreañ",
        "changepassword-success": "Cheñchet eo bet ho ker-tremen !",
        "changepassword-throttled": "Betek re hoc'h heus klasket kevreañ en aner.\nGortozit $1, mar plij, a-raok esaeañ en-dro.",
+       "botpasswords-label-appid": "Anv ar robot",
        "botpasswords-label-create": "Krouiñ",
+       "botpasswords-label-update": "Hizivaat",
        "botpasswords-label-cancel": "Nullañ",
        "botpasswords-label-delete": "Dilemel",
+       "botpasswords-label-resetpassword": "Adderaouekaat ar ger-tremen",
+       "botpasswords-bad-appid": "N'eo ket reizh anv ar robot « $1 »",
+       "botpasswords-insert-failed": "C'hwitet eo ouzhpennadenn ar robot « $1 ». Hag ouzhpennet eo bet ?",
+       "botpasswords-update-failed": "C'hwitet eo bet hizivadur anv ar robot « $1 ». Ha dilamet eo bet ?",
+       "botpasswords-created-title": "Ger-tremen robotoù krouet",
+       "botpasswords-created-body": "Krouet mat eo bet ar ger-tremen « $1 ».",
+       "botpasswords-updated-title": "Ger-tremen robotoù hizivaet",
+       "botpasswords-updated-body": "Hizivaet mat eo bet ar ger-tremen « $1 ».",
+       "botpasswords-deleted-title": "Ger-tremen robotoù dilamet",
+       "botpasswords-deleted-body": "Ar ger-tremen robotoù « $1 » zo bet dilamet.",
+       "botpasswords-newpassword": "<strong>\"$2\"</strong> eo ar ger-tremen evit kevreañ gant <strong>$1</strong>. Enrollit anezhañ, par plij, evit ober dave dezhañ diwezhatoc'h.</em>",
+       "botpasswords-no-provider": "N'eo ket hegerz BotPasswordsSessionProvider.",
        "resetpass_forbidden": "N'haller ket cheñch ar gerioù-termen",
        "resetpass-no-info": "Ret eo deoc'h bezañ kevreet a-benn mont d'ar bajenn-se war-eeun.",
        "resetpass-submit-loggedin": "Cheñch ger-tremen",
        "upload-dialog-button-done": "Graet",
        "upload-dialog-button-save": "Enrollañ",
        "upload-dialog-button-upload": "Enporzhiañ",
-       "upload-form-label-select-file": "Diuzañ ur restr",
        "upload-form-label-infoform-title": "Munudoù",
        "upload-form-label-infoform-name": "Anv",
        "upload-form-label-infoform-description": "Deskrivadur",
        "suppress": "Dindan evezh",
        "querypage-disabled": "Diweredekaet eo bet ar bajenn dibar-mañ evit aesaat d'ar reizhiad un tammig.",
        "apihelp-no-such-module": "N'eo ket bet kavet ar vodulenn \"$1\".",
+       "apisandbox": "Poull-traezh API",
+       "apisandbox-api-disabled": "Diweredekaet eo API war al lec'hienn-mañ.",
+       "apisandbox-intro": "Grit gant ar bajenn-mañ evit amprouiñ '''servij Web API MediaWiki'''.\nKit da deuler ur sell war [//www.mediawiki.org/wiki/API:Main_page titouroù an API] evit gouzout hiroc'h war an doare da embreger API. Da skouer :\n[//www.mediawiki.org/wiki/API#A_simple_example gwelet danvez ur bennbajenn]. Dibabit un oberiadenn bennak evit gwelet skouerioù all",
+       "apisandbox-submit": "Sevel ar goulenn",
+       "apisandbox-reset": "Riñsañ",
+       "apisandbox-examples": "Skouer",
+       "apisandbox-results": "Disoc'h",
+       "apisandbox-request-url-label": "Goulenn URL :",
+       "apisandbox-request-time": "Pad ar goulenn: $1",
        "booksources": "Oberennoù dave",
        "booksources-search-legend": "Klask en oberennoù dave",
        "booksources-isbn": "ISBN :",
index 6b2b073..38b8ffc 100644 (file)
        "protect_change": "хийца",
        "protectthispage": "Ларъе хӀара агӀо",
        "unprotect": "Ларъяр хийцар",
-       "unprotectthispage": "Хийца хӀокху агӀона ларъяр",
+       "unprotectthispage": "ХӀокху агӀонан ларъяр хийца",
        "newpage": "Керла агӀонаш",
-       "talkpage": "Ð\94ийÑ\86аÑ\80е Ð¹Ð¸Ð»Ð»Ð° Ñ\85Ó\80аÑ\80а Ð°Ð³Ó\80о",
+       "talkpage": "Ð¥Ó\80аÑ\80а Ð°Ð³Ó\80о Ð¹Ð¸Ð¹Ñ\86аÑ\80е Ð¹Ð¸Ð»Ð»Ð°",
        "talkpagelinktext": "Дийцаре",
        "specialpage": "Белхан агӀо",
        "personaltools": "Долахь болу гӀирсаш",
        "templatepage": "Хьажа кепа агӀоне",
        "viewhelppage": "Схьаэца гӀо",
        "categorypage": "Хьажа категорешан агӀоне",
-       "viewtalkpage": "Ð¥Ñ\8cажа Ð´Ð¸Ð¹Ñ\86аÑ\80е",
+       "viewtalkpage": "Ð\94ийÑ\86аÑ\80е Ñ\85Ñ\8cажа",
        "otherlanguages": "Кхечу маттахь дерш",
-       "redirectedfrom": "(ДӀасахьажийна кху $1)",
+       "redirectedfrom": "($1 дӀасахьажийна кхузе)",
        "redirectpagesub": "АгӀо-дӀасахьажорг",
        "redirectto": "ДӀасахьажор тӀе:",
        "lastmodifiedat": "ХӀокху агӀон тӀаьххьаралера хийцам: $1, $2.",
        "logouttext": "'''Ахьа болх дӀаберзийна.'''\n\nЦхьайолу агӀонаш чохь хьо хьай цӀарца болх беш сана хила тарло ишта ца хилийта керлаякха браузеран кэш.",
        "cannotlogoutnow-title": "ХӀинца чудаха таро яц",
        "welcomeuser": "Марша ДогӀийла, $1!",
-       "welcomecreation-msg": "Хьан декъашхочун дӀаяздар кхоьлина.\nДиц ма делахь {{SITENAME}} сайтан [[Special:Preferences|декъашхочун гӀирс]].",
+       "welcomecreation-msg": "Хьан хьесапан (учётни) дӀаяздар кхоьллина.\nДиц ма делахь {{SITENAME}} сайтан [[Special:Preferences|декъашхочун гӀирс]] чекхбаккха.",
        "yourname": "Декъашхочун цӀе:",
        "userlogin-yourname": "Декъашхочун цӀе",
        "userlogin-yourname-ph": "Язъе декъашхочун цӀе",
        "undo-summary-username-hidden": "Юхадаьккхина декъашхочун нисдарш $1, цунна цӀе дӀахьулйина",
        "cantcreateaccounttitle": "Декъашхочун дӀаяздар кхолла йиш яц",
        "viewpagelogs": "Гайта хӀокху агӀонан тептар",
-       "nohistory": "ХӀокху агӀона хийцамаш бина хила бац.",
+       "nohistory": "ХӀокху агӀонан хийцамаш ца бина.",
        "currentrev": "Карара верси",
        "currentrev-asof": "Карара верси $1",
        "revisionasof": "Верси $1",
        "searchprofile-advanced-tooltip": "Дехарца йолу цӀерийн анашкахь лахар",
        "search-result-size": "$1 ({{PLURAL:$2|$2 дош|$2 дешнаш}})",
        "search-result-category-size": "$1 {{PLURAL:$1|юкъаяр}} ($2 {{PLURAL:$2|1=бухара категори|бухара категореш}}, $3 {{PLURAL:$3|1=файл|файлаш}}).",
-       "search-redirect": "(дlасахьажийна $1)",
+       "search-redirect": "(дӀасахьажийна $1)",
        "search-section": "(дакъа $1)",
        "search-category": "(категори $1)",
        "search-file-match": "(файлан чулацаме тера хилар)",
        "action-createpage": "агӀонаш кхолла",
        "action-createtalk": "дийцаре агӀонаш кхоллар",
        "action-createaccount": "хӀара декъашхочун дӀаяздар кхоллар",
-       "action-history": "хӀокху агӀона исторега хьажар",
+       "action-history": "хӀокху агӀонан исторешка хьажар",
        "action-minoredit": "жима нисдар сана билгало",
        "action-move": "хӀокху агӀон цӀе хийца",
        "action-move-subpages": "хӀокху агӀона цӀе хийцар цуна массо бухара агӀонийн а",
        "action-writeapi": "нисдеш лелойо API",
        "action-delete": "дӀаяккха хӀара агӀо",
        "action-deleterevision": "агӀона хӀара верси дӀаяккхар",
-       "action-deletedhistory": "хӀокху агӀона дӀаяккхинцу исторега хьажар",
+       "action-deletedhistory": "хӀокху агӀонан дӀаяьккхинчу исторешка хьажар",
        "action-browsearchive": "ДӀаяхна агӀонаш лахар",
        "action-undelete": "хӀара агӀо меттахӀоттор",
        "action-suppressrevision": "хӀокху къайлаха йолу агӀон версеш хьажар а, меттахӀоттор а",
        "removedwatchtext": "АгӀо «[[:$1]]» дӀаяьккхина яра хьан [[Special:Watchlist|тергаме могӀанан юкъар]].",
        "removedwatchtext-short": "«$1» агӀо хьан тергаман магӀам чура дӀаяьккхина.",
        "watch": "Тидам бе",
-       "watchthispage": "ТеÑ\80гам Ð±Ã© Ñ\85Ó\80окÑ\85Ñ\83 Ð°Ð³Ó\80она",
+       "watchthispage": "Ð¥Ó\80окÑ\85Ñ\83 Ð°Ð³Ó\80онан Ñ\82идам Ð±ÐµÑ\88 Ñ\85ила",
        "unwatch": "Тергамах къаста",
        "unwatchthispage": "ДӀадаккха терго яр",
        "notanarticle": "Яззам бац",
        "tooltip-n-help": "ГӀоде меттиг",
        "tooltip-t-whatlinkshere": "Массо агӀон могӀам, хӀокху агӀонтӀе хьажийна йолу",
        "tooltip-t-recentchangeslinked": "ТӀаьххьарлера хийцамаш хӀокху агӀонашкахь, хьажийна хӀара агӀо болу",
-       "tooltip-feed-rss": "ХӀокху агӀона трансляци RSS-рца",
+       "tooltip-feed-rss": "RSS-ехь йолу хӀокху агӀонан трансляци",
        "tooltip-feed-atom": "Хьагайтар оцу Atom цани хlокху агlон",
        "tooltip-t-contributions": "ХӀокху декъашхочо хийцина йолу агӀонийн могӀам",
        "tooltip-t-emailuser": "ДӀабахьийта хаам оцу декъашхона",
index eb48dd6..b278df6 100644 (file)
        "newarticletextanon": "{{int:newarticletext|$1}}",
        "talkpagetext": "<!-- MediaWiki:talkpagetext -->",
        "anontalkpagetext": "----\n<em>This is the discussion page for an anonymous user who has not created an account yet, or who does not use it.</em>\nWe therefore have to use the numerical IP address to identify him/her.\nSuch an IP address can be shared by several users.\nIf you are an anonymous user and feel that irrelevant comments have been directed at you, please [[Special:UserLogin/signup|create an account]] or [[Special:UserLogin|log in]] to avoid future confusion with other anonymous users.",
-       "noarticletext": "There is currently no text in this page.\nYou can [[Special:Search/{{PAGENAME}}|search for this page title]] in other pages,\n<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} search the related logs],\nor [{{fullurl:{{FULLPAGENAME}}|action=edit}} edit this page]</span>.",
+       "noarticletext": "There is currently no text in this page.\nYou can [[Special:Search/{{PAGENAME}}|search for this page title]] in other pages,\n<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} search the related logs],\nor [{{fullurl:{{FULLPAGENAME}}|action=edit}} create this page]</span>.",
        "noarticletext-nopermission": "There is currently no text in this page.\nYou can [[Special:Search/{{PAGENAME}}|search for this page title]] in other pages, or <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} search the related logs]</span>, but you do not have permission to create this page.",
        "noarticletextanon": "{{int:noarticletext}}",
        "missing-revision": "The revision #$1 of the page named \"{{FULLPAGENAME}}\" does not exist.\n\nThis is usually caused by following an outdated history link to a page that has been deleted.\nDetails can be found in the [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} deletion log].",
index 832a2c6..2b2519f 100644 (file)
        "shown-title": "दर एका पानार {{PLURAL:$1|निकाल}} दाखय",
        "viewprevnext": "पळयात ($1 {{int:pipe-separator}} $2) ($3)",
        "searchmenu-exists": "ह्या'''विकीचेर \"[[:$1]]\" ह्या नांवाचें पान आसा .''' {{PLURAL:$2|0=|See also the other search results found.}}",
-       "searchmenu-new": "<strong>ह्या विकीचेर \"[[:$1]]\" हें पान रोचात!<strong> {{PLURAL:$2|सोदून मेळिल्लें पानय पळेयात.|सोदून मेळिल्ले निकाळय पळेयात.}}",
+       "searchmenu-new": "<strong>ह्या विकीचेर \"[[:$1]]\" हें पान रोचात!</strong> {{PLURAL:$2|सोदून मेळिल्लें पानय पळेयात.|सोदून मेळिल्ले निकाळय पळेयात.}}",
        "searchprofile-articles": "मजकूराचीं पानां",
        "searchprofile-images": "भोवमाध्यम",
        "searchprofile-everything": "सगळें",
index 4028d1b..459a7c3 100644 (file)
        "qbmyoptions": "Mhoji panam",
        "faq": "Porot porot vicharlele prosn",
        "faqpage": "Project:Porot porot vicharlele prosn",
-       "actions": "Karvaio",
+       "actions": "Kornnio",
        "namespaces": "Nanvthollam",
        "variants": "Dusre",
        "navigation-heading": "Dixa-niontron suchi",
        "shown-title": "Dor eka panar {{PLURAL:$1|porinam}} dakhoi",
        "viewprevnext": "($1 {{int:pipe-separator}} $2) ($3) poloi",
        "searchmenu-exists": "'''Hea Wikicher \"[[:$1]]\" nanvanche pan asa.'''",
-       "searchmenu-new": "<strong>\"[[:$1]]\" hem pan hea vikint roch!<strong> {{PLURAL:$2|0=|Tujea sodan mellelem panui polloi.|Tujea sodan mellelem panamui polloi.}}",
+       "searchmenu-new": "<strong>\"[[:$1]]\" hem pan hea vikint roch!</strong> {{PLURAL:$2|0=|Tujea sodan mellelem panui polloi.|Tujea sodan mellelem panamui polloi.}}",
        "searchprofile-articles": "Mozkurachim panam",
        "searchprofile-images": "Bhovmadhiom",
        "searchprofile-everything": "Sogllem",
index 0cc4f5e..8f183d3 100644 (file)
        "recentchanges-page-added-to-category": "[[:$1]] aggiunta alla categoria",
        "recentchanges-page-added-to-category-bundled": "[[:$1]] e {{PLURAL:$2|una pagina è aggiunta|$2 pagine sono aggiunte}} alla categoria",
        "recentchanges-page-removed-from-category": "[[:$1]] rimossa dalla categoria",
-       "recentchanges-page-removed-from-category-bundled": "[[:$1]] e {{PLURAL:$2|un'altra pagina rimosse|$2 pagine rimosse}} dalla categoria",
+       "recentchanges-page-removed-from-category-bundled": "[[:$1]] e {{PLURAL:$2|un'altra pagina|altre $2 pagine}} rimosse dalla categoria",
        "autochange-username": "Modifica automatica MediaWiki",
        "upload": "Carica un file",
        "uploadbtn": "Carica",
index 636c19f..a37bf64 100644 (file)
        "policy-url": "Project:정책",
        "portal": "사용자 모임",
        "portal-url": "Project:사용자 모임",
-       "privacy": "개인 정보 정책",
-       "privacypage": "Project:개인 정보 정책",
+       "privacy": "개인정보 정책",
+       "privacypage": "Project:개인정보 정책",
        "badaccess": "권한 오류",
        "badaccess-group0": "요청한 명령을 실행할 권한이 없습니다.",
        "badaccess-groups": "요청한 명령은 {{PLURAL:$2|다음|다음 중 하나의}} 권한을 가진 사용자에게 제한됩니다: $1.",
index 0998ff3..109f143 100644 (file)
@@ -14,7 +14,8 @@
                        "Krivoshapkina",
                        "Macofe",
                        "Matma Rex",
-                       "Мария Олесова"
+                       "Мария Олесова",
+                       "Ай-Куо"
                ]
        },
        "tog-underline": "Сигэлэри аннынан тардыы:",
        "databaseerror-query": "Ыйытык: $1",
        "databaseerror-function": "Функция: $1",
        "databaseerror-error": "Алҕас: $1",
+       "transaction-duration-limit-exceeded": "\nРепликация оҥорорго улахан лаг мэһэйдээбэтин туһугар транзакция тохтотуллубута, сурутуу уһуна ($1) ($2){{PLURAL:$2|}}лимиты таһынан ааһарын быһыытынан.\nЭн  биир олорууга хас да элэмиэни уларытар буоллаххына, ол оннугар элбэх улахана суох операциялары оҥорорго холонон көрүҥ.",
        "laggedslavemode": "Болҕой: Бу сирэй бүтэһик уларытыылара суох буолуон сөп",
        "readonly": "Билии олоҕун уларытар бобуллубут",
        "enterlockreason": "Уларытыыны бобуу төрүөтүн уонна төһө өр бобулларын ый.",
        "missingarticle-rev": "(#-с торум: $1)",
        "missingarticle-diff": "(Уратыта: $1, $2)",
        "readonly_lag": "Билии олоҕун хос сиэрбэрдэрэ сүрүн сиэрбэри кытта мэнэйдэһэр кэмнэригэр билии олоҕо хатанна",
+       "nonwrite-api-promise-error": " HTTP-аат 'Promise-Non-Write-API-Action'ыытылынна, ол гынан баран ыйытык суруйуу API-модулугар барбыта.",
        "internalerror": "Ис алҕас (внутренняя ошибка)",
        "internalerror_info": "Ис алҕас: $1",
        "internalerror-fatal-exception": "\"$1\" тииптээх төлөрүйбэт туорааһын",
        "mypreferencesprotected": "Бэйэҥ туруорууларгын уларытар кыаҕыҥ суох эбит.",
        "ns-specialprotected": "{{ns:special}} ааттаах сирэйдэр уларытыллыбаттар.",
        "titleprotected": "Бу бас тыл оҥоһулларын [[User:$1|$1]] боппут.\nТөрүөтэ - ''$2''",
-       "filereadonlyerror": "«$1» билэни уларытар сатаммата, тоҕо диэтэххэ «$2» «ааҕарга эрэ» диэн эрэсиимҥэ турар эбит.\n\nБу эрэсиими туруорбут дьаһабыл маннык быһаарыыны хаалларбыт: «''$3''».",
+       "filereadonlyerror": "«$1» билэни уларытар сатаммата, тоҕо диэтэххэ «$2» «ааҕарга эрэ» диэн эрэсиимҥэ турар эбит.\n\nБу эрэсиими туруорбут систиэмэлээх дьаһабыл маннык быһаарыыны хаалларбыт: «''$3''».",
        "invalidtitle-knownnamespace": "«$2» аат далыгар маннык тиэкистээх «$3» сатаммат аат",
        "invalidtitle-unknownnamespace": "Биллибэт аат дала $1 нүөмэрдээх, \"$2\" тиэкистээх сатаммат аат",
        "exception-nologin": "Ааккын билиһиннэрбэтэххин",
        "changepassword-success": "Киирии тылыҥ этэҥҥэ уларыйда!",
        "changepassword-throttled": "Ааккын аһара элбэхтик билиһиннэрэ сатаатыҥ.\nБука диэн $1 буолан баран өссө киирэн көрөөр.",
        "botpasswords": "Оруобаттар аһарыктара",
+       "botpasswords-summary": "<em>Хатыыр тыллара</em> туттааччы учуоттуур сурутуутугар API-нан   логины уонна хатыыр тылы туттубакка эрэ киирэр кыах биэрэр. Кыттааччы  бота хатыыр тыллаах киириитигэр бырааба хааччахтаныан сөп.\nЭн  ити тоҕо наадатын билбэт буоллаххына, бука, итини гымматыҥ ордук.Ким даҕаны эйигиттэн хаһан даҕаны эн оҥорбутуҥ уонна биллэрбитиҥ диэн ыйытыа суохтаах.",
        "botpasswords-disabled": "Оруобаттар аһарыктара араарыллыбыттар.",
        "botpasswords-no-central-id": "Оруобат аһарыгын туһанарга кииннэммит ааккынан киириэхтээххин.",
        "botpasswords-existing": "Билигин баар оруобат аһарыктара",
        "botpasswords-label-delete": "Сот",
        "botpasswords-label-resetpassword": "Аһарыгы саҥаттан",
        "botpasswords-label-grants": "Туттуллар көҥүллэр:",
+       "botpasswords-help-grants": " Кыттааччы учуоттуур суруйуутугар баар ыйыллыбыт кыттааччы быраабыгар киирэргэ кыах биэрэр. к. [[Special:ListGrants|көҥүллэр табылыыссаларын]] эбии информацияны ылар туһугар.",
        "botpasswords-label-restrictions": "Туттарга хааччахтаах:",
        "botpasswords-label-grants-column": "Көҥүллэннэ",
        "botpasswords-bad-appid": "Маннык аат «$1» сатаммат.",
        "botpasswords-insert-failed": "«$1» диэн ааттаах оруобаты эбэр табыллыбата. Баҕар хайыы-үйэ эбиллибитэ буолаарай?",
+       "botpasswords-update-failed": "\"$1\" диэн ааттаах ботаны кыайан саҥардыбатыбыт. Баҕар, сотторуллубута буолуо?",
        "botpasswords-created-title": "Оруобат аһарыга оҥоһулунна",
        "botpasswords-created-body": "«$1» оруобат аһарыга бигэргэтилиннэ.",
        "botpasswords-updated-title": "Оруобат аһарыга саҥардылынна",
        "botpasswords-updated-body": "«$1» оруобат аһарыга уларытылынна.",
        "botpasswords-deleted-title": "Оруобат аһарыга сотулунна",
        "botpasswords-deleted-body": "«$1» оруобат аһарыга сотулунна.",
+       "botpasswords-newpassword": "\nСаҥа хатыыр тыл <strong>$1</strong> — <strong>$2</strong> аннынан киириигэ. <em> суруй аныгыскыга туттарга.</em>",
+       "botpasswords-no-provider": "BotPasswordsSessionProvider кыаллыбат.",
        "botpasswords-restriction-failed": "Буот аһарыгын кытта сыһыаннаах хааччахтан киирии сатаммата.",
+       "botpasswords-invalid-name": " туттааччы аата ыйыллыбыт (\"$1\") араарааччы бот хатыыр ааты илдьэ сылдьыбат.",
+       "botpasswords-not-exist": "«$1» кыттааччыга «$2» диэн ааттаммыт оруобакка аналлаах аһарыга суох эбит.",
        "resetpass_forbidden": "Киирии тылы уларытар сатаммат",
        "resetpass-no-info": "Ааккын билиһиннэрдэххинэ эрэ бу сирэйгэ быһа тиийиэххин сөп.",
        "resetpass-submit-loggedin": "Киирии тылы уларытыы",
        "previewnote": "'''Бу барыллаан көрүү эрэ.'''\nАтын уларытыы бигэргэтиллэ илик!",
        "continue-editing": "Уларытар сиргэ",
        "previewconflict": "Этот предварительный просмотр отражает текст в верхнем окне редактирования так, как он будет выглядеть, если вы решите записать его.",
-       "session_fail_preview": "'''Сиэрбэр сессия идентификаторын сүтэрэн кэбиһэн эн уларытыыгын кыайан киллэрбэтэ.\nӨссө холонон көр.\nОлох сатамматаҕына биикиттэн [[Special:UserLogout|тахсан]] баран өссө киирэн көрөөр.'''",
+       "session_fail_preview": "'''Сиэрбэр сессия идентификаторын сүтэрэн кэбиһэн эн уларытыыгын кыайан киллэрбэтэ.\nБаҕар, үлэ сеансын бүтэрбитиҥ буолуо. <strong>Баһаалыста, көҥүлү ааспыккын бил уонна өссө холонон көр.\n<strong>\nОлох сатамматаҕына биикиттэн [[Special:UserLogout|тахсан]] баран өссө киирэн көрөөр, ону сэргэ браузерыҥ бу саайтан cookies диэни ыларга көҥүллүүрүн бэрэбиэркэлээҥ.'''",
        "session_fail_preview_html": "'''Сессия дааннайдарын сүтэрэн кэбиһэн сиэрбэр эн уларытыыгын киллэрбэтэ.'''\n\n''{{SITENAME}} ыраас HTML тылы көҥүллүүр буолан JavaScript туһананнар куһаҕаны оҥоруохтарын сөп, онон эрдэ көрдөрүү араарыллыбыт.''\n\n'''Өскө бу уларытыы туох да куһаҕаны аҕалыа диэбэт буоллаххына хатылаа. Ол сатамматаҕына [[Special:UserLogout|тахсан баран]] өссө киирэн көрөөр.'''",
        "token_suffix_mismatch": "'''Эн уларытыыҥ киирбэтэ, тоҕо диэтэххэ эн бырагырааммаҥ сорох сурук бэлиэлэрин сыыһа көрөр эбит.\nЫстатыйаны буорту гынымаары уларытыыҥ ылыныллыбата.\nИтинник сыыһалар үксүн прокси-сиэрбэрдэри туһаннахха тахсааччылар.'''",
        "edit_form_incomplete": "'''Уларытыы сорҕото сиэрбэргэ тиийбэтэ. Үчүгэйдик сыныйан көр, Эн уларытыыларыҥ туох да омсото суохтар дуо. Онтон өссө боруобалаа.'''",
        "mergehistory-fail-bad-timestamp": "Кэм бэлиэтэ алҕастаах.",
        "mergehistory-fail-invalid-source": "Сирэй төрүтэ алҕастаах.",
        "mergehistory-fail-invalid-dest": "Барыахтаах сирэйиҥ алҕастаах.",
+       "mergehistory-fail-no-change": "Устуоруйа холбоһуутугар ханнык да биэрсийэ холбоһуута буолбата. Баһаалыста сирэйи уонна быстах кэмнээх кэмнэбили өссө төгүл бэрэбиэркэлээ.",
        "mergehistory-fail-permission": "Устуоруйаны холбуурга быраап тиийбэт",
        "mergehistory-fail-self-merge": "Саҕалыыр уонна түмүктүүр сирэйдэриҥ атын буолуохтаахтар",
        "mergehistory-fail-toobig": "Устуоруйаны холбуур табыллыбата, тоҕо диэтэххэ $1  барылга көҥүллэнэр лимииттэн элбэҕи көһөрөр наада эбит.",
        "apisandbox-submit": "Ыйытык оҥоруу",
        "apisandbox-reset": "Сот",
        "apisandbox-retry": "Хатылаа",
+       "apisandbox-helpurls": "Көмө сигэлэр",
+       "apisandbox-examples": "Холобурдар",
        "apisandbox-dynamic-parameters": "Дьайыы кээмэйдэрэ.",
        "apisandbox-dynamic-parameters-add-label": "Кэриҥи эбии.",
        "apisandbox-dynamic-parameters-add-placeholder": "Кэриҥ аата.",
+       "apisandbox-dynamic-error-exists": "«$1» диэн ааттаах параметр хайыы үйэ баар эбит.",
        "apisandbox-deprecated-parameters": "Эргэрбит кэриҥнэр.",
+       "apisandbox-fetch-token": "Токены аптамаатынан толоруу",
+       "apisandbox-submit-invalid-fields-title": "Сорҕото алҕастаах",
        "apisandbox-submit-invalid-fields-message": "Бука диэн бэлиэтэммит хонууну көннөр уонна хаттаан ук.",
        "apisandbox-results": "Түмүк",
+       "apisandbox-sending-request": "API-көрдөбүлү ыытыы…",
+       "apisandbox-loading-results": "API-түмүгүн ылыы…",
        "apisandbox-results-fixtoken": "Токены көннөрөн баран саҥаттан ыыт.",
        "booksources": "Кинигэлэр источниктара",
        "booksources-search-legend": "Кинигэ туһунан көрдөө",
        "tags-deactivate-not-allowed": "\"$1\" тиэги араарар табыллыбат.",
        "tags-deactivate-submit": "араар",
        "tags-apply-no-permission": "Бэйэҥ уларытыыгар уларытыы тиэгин туруорар кыаҕыҥ суох эбит.",
+       "tags-apply-blocked": "Хатана сылдьар кэмҥитигэр көннөрүүлэргитигэр уларытыы бэлиэлэрин туттаргыт табыллыбат.",
        "tags-apply-not-allowed-one": "«$1» тиэги илииннэн туруорар табыллыбат эбит.",
        "tags-apply-not-allowed-multi": "Маннык {{PLURAL:$2|тиэк илиинэн угуллубат|тиэктэр илиинэн угуллубаттар}}: $1",
        "tags-update-no-permission": "Сурунаал тус-туспа торумнарын уонна суруктарын тиэгин эбэр уонна уларытар кыаҕыҥ суох эбит.",
index da74677..756a436 100644 (file)
@@ -44,7 +44,8 @@
                        "Matma Rex",
                        "Anj.balaji",
                        "Dineshkumar Ponnusamy",
-                       "Sharanrajindia"
+                       "Sharanrajindia",
+                       "Maathavan"
                ]
        },
        "tog-underline": "இணைப்புகளுக்கு அடிக்கோடிடு",
        "right-blockemail": "பயனர் மின்னஞ்சல் அனுப்புவதை தடுக்கவும்",
        "right-hideuser": "பயனர்பெயரை தடுத்து, மறைக்கவும்",
        "right-ipblock-exempt": "ஐ.பி (IP) தடுப்புகளையும், தானியங்கியான தடுப்புகளையும், வரம்புவரையான தடுப்புகளையும் மீறிச் செயல்படுக.",
-       "right-proxyunbannable": "தானாக தடுப்புகப்பட்ட  Proxies ஐ மீறு.",
        "right-unblockself": "நீங்களே தடுப்பு நீக்குக",
        "right-protect": "பாதுகாப்பு மட்டங்களை மாற்று மற்றும் தொடர்-பாதுகாக்கப்பட்ட பக்கங்களை திருத்து",
        "right-editprotected": "\"{{int:protect-level-sysop}}\" ஆல் பாதுகாக்கப்பட்ட பக்கங்களை திருத்து",
        "right-managechangetags": "தரவுதளத்திலிருந்து [[Special:Tags|அடையாளங்களை]] உருவாக்கு மற்றும் நீக்கு",
        "right-applychangetags": "ஒருவரின் மாற்றத்துடன் [[Special:Tags|அடையாளங்களை]] செயற்படுத்து",
        "right-changetags": "தனியொருவரின் திருத்தம் மற்றும் செயற்பாட்டு பதிவுகளில்  [[Special:Tags|அடையாளங்களை]] சேர் அல்லது நீக்கு",
+       "grant-group-administration": "நிர்வாக நடவடிக்கைகளை செயல்படுத்து",
        "newuserlogpage": "பயனர் உருவாக்கம் பற்றிய குறிப்பு",
        "newuserlogpagetext": "இது பயனர் படைப்புகளின் பதிவு ஆகும்.",
        "rightslog": "பயனர் உரிமைகள் பதிகை",
        "watchthisupload": "இந்த கோப்பினைக் கவனி",
        "filewasdeleted": "இப்பெயரைக் கொண்ட கோப்பு முன்பு பதிவேற்றப்பட்டு பின்னர் நீக்கப்பட்டது. பதிவேற்றத்துக்குப் முன்னர் $1 ஐச் சரிபார்க்கவும்.",
        "filename-bad-prefix": "நீங்கள் பதிவேற்ற எத்தனிக்கும் கோப்பின் பெயர் '''\"$1\"''' என்பதுடன் தொடங்குகிறது, பொதுவாக இது எண்மருவி கமெராக்கலால் தானியக்கமாக வழங்கப்புடும் பெயராகும். அருள் கூர்ந்து கோப்பிற்கு விளக்கமான பெயரொன்றைக் கொடுக்கவும்.",
-       "upload-success-subj": "வெற்றிகரமான பதிவேற்றம்",
-       "upload-success-msg": "[$2]  லிருந்து உங்கள் தகவலேற்றம் நடக்கவில்லை.அது  [[:{{ns:file}}:$1]] இங்கு கிடைக்கப்பெறும்.",
-       "upload-failure-subj": "பதிவேற்றத்தில் ஏற்பட்டத் தொல்லை",
-       "upload-failure-msg": "[$2] லிருந்து உங்கள்  தகவலேற்றத்தில் சிக்கல் உள்ளது.\n$1",
-       "upload-warning-subj": "பதிவேற்றல் எச்சரிக்கை",
-       "upload-warning-msg": "$2 லிருந்து உங்கள் தகவலேற்றத்தில் சிக்கல் உள்ளது. அதை சரி செய்ய நீங்கள் இங்கே செல்லலாம் [[Special:Upload/stash/$1|upload form]].",
        "upload-proto-error": "பிழையான நெறி",
        "upload-proto-error-text": "தொலைவுப் பதிவேற்றத்துக்கு யு.ஆர்.எல். <code>http://</code> அல்லது <code>ftp://</code> என்ற முன்னொட்டுடன் தொடங்கவேண்டும்.",
        "upload-file-error": "உள்ளகத் தவறு",
        "querypage-disabled": "செயல்பாட்டு காரணங்களுக்காக இந்த சிறப்புப் பக்கம் முடக்கப்பட்டுள்ளது.",
        "apihelp": "ஏபிஐ உதவி",
        "apihelp-no-such-module": "''$1'' என்ற மாடுயூல் காணப்படவில்லை.",
+       "apisandbox": "API மணற்தொட்டி",
+       "apisandbox-api-disabled": "இத் தளத்தில் API செயலிழக்கம் செய்யப்பட்டுள்ளது.",
+       "apisandbox-submit": "கோரிக்கை செய்",
+       "apisandbox-reset": "வெறுமையாக்கு",
+       "apisandbox-examples": "உதாரணம்",
+       "apisandbox-results": "முடிவு",
+       "apisandbox-request-time": "வேண்டுகோள் நேரம்: $1",
        "booksources": "நூல் மூலங்கள்",
        "booksources-search-legend": "நூல் மூலங்களைத் தேடு",
        "booksources-search": "தேடுக",
        "wlheader-showupdated": "உங்கள் கடைசி வருகைக்குப் பின்னர் மாற்றங்கள் செய்யப்பட்ட பக்கங்கள் '''தடித்த எழுத்துக்களில்''' காட்டப்பட்டுள்ளன",
        "wlnote": "பின்வருவன கடைசி {{PLURAL:$2|மணித்தியாலத்தில்|'''$2''' மணித்தியாலங்களில்}} செய்யப்பட்ட {{PLURAL:$1|கடைசி ஒரு மாற்றமாகும்|கடைசி $1 மாற்றங்களாகும்}}.",
        "wlshowlast": "கடைசி $1 மணித்தியாலங்கள் $2 நாட்களைக் காட்டு",
-       "watchlistall2": "அனைத்து",
        "watchlist-options": "கவனிப்பு பட்டியலின் விருப்பத் தேர்வுகள்",
        "watching": "கவனிக்கப்படுகிறது...",
        "unwatching": "கவனிப்பு விடப்படுகிறது...",
        "tooltip-t-recentchangeslinked": "இப்பக்கத்துடன் இணைக்கப்பட்ட பக்கங்களில் மாற்றங்கள்",
        "tooltip-feed-rss": "இப்பக்கத்துக்கான ஆர்.எஸ்.எஸ். ஓடை கிடையாது",
        "tooltip-feed-atom": "இப்பக்கத்துக்கான அடொம் ஓடை கிடையாது",
-       "tooltip-t-contributions": "இப்பயனரின்  பங்களிப்புக்களின் பட்டியலைப் பார்",
+       "tooltip-t-contributions": "{{GENDER:$1|இப்பயனரின்}} பங்களிப்புக்களின் பட்டியலைப் பார்",
        "tooltip-t-emailuser": "இப் பயனருக்கு மின்னஞ்சல் செய்",
        "tooltip-t-info": "இப்பக்கத்தைப்பற்றி மேலதிக விபரம்",
        "tooltip-t-upload": "கோப்புகளைப் பதிவேற்றுக",
        "special-characters-group-lao": "இலாவோ",
        "special-characters-group-khmer": "கெமெர்",
        "special-characters-title-minus": "கழித்தல் குறி",
-       "api-error-blacklisted": "தயவுகூர்ந்து வேறு, விளக்கமான தலைப்பைத் தேர்ந்தெடுக்கவும்."
+       "api-error-blacklisted": "தயவுகூர்ந்து வேறு, விளக்கமான தலைப்பைத் தேர்ந்தெடுக்கவும்.",
+       "randomrootpage": "தற்போக்கு வேர்ப் பக்கம்"
 }
index 858a578..6313fd4 100644 (file)
        "restoreprefs": "Відновити всі стандартні налаштування (у всіх розділах)",
        "prefs-editing": "Редагування",
        "rows": "Рядків:",
-       "columns": "Ð\9aолонок:",
+       "columns": "СÑ\82овпÑ\86Ñ\96в:",
        "searchresultshead": "Пошук",
        "stub-threshold": "Поріг для визначення оформлення посилань на стаби ($1):",
        "stub-threshold-sample-link": "зразок",
        "rcshowhidemine-show": "показати",
        "rcshowhidemine-hide": "приховати",
        "rcshowhidecategorization": "$1 категоризацію сторінок",
-       "rcshowhidecategorization-show": "Ð\9fоказати",
+       "rcshowhidecategorization-show": "показати",
        "rcshowhidecategorization-hide": "Приховати",
        "rclinks": "Показати останні $1 редагувань за $2 днів<br />$3",
        "diff": "різн.",
index 0b89559..6351ac4 100644 (file)
        "passwordreset-emailtext-ip": "Ai đó (có thể là bạn, từ địa chỉ IP $1) đã yêu cầu tái tạo mật khẩu của bạn \ntại {{SITENAME}} ($4). {{PLURAL:$3|Tài khoản|Các tài khoản}} dưới đây gắn liền \nvới địa chỉ thư điện tử này:\n\n$2\n\n{{PLURAL:$3|Mật khẩu|Các mật khẩu}} tạm này sẽ hết hạn trong vòng {{PLURAL:$5|một ngày|$5 ngày}}. Bạn nên đăng nhập\nngay bây giờ để chọn mật khẩu mới. Nếu bạn không phải là người yêu cầu\nhoặc đã nhớ lại mật khẩu hiện hành, và bạn không còn\nmuốn thay đổi nó, xin vui lòng bỏ qua thông điệp này và tiếp tục sử dụng\nmật khẩu cũ.",
        "passwordreset-emailtext-user": "Thành viên $1 tại {{SITENAME}} đã yêu cầu tái tạo mật khẩu tại {{SITENAME}} \n($4). {{PLURAL:$3|Tài khoản|Các tài khoản}} dưới đây gắn liền với địa chỉ thư điện tử này:\n\n$2\n\n{{PLURAL:$3|Mật khẩu|Các mật khẩu}} tạm này sẽ hết hạn trong vòng {{PLURAL:$5|một ngày|$5 ngày}}. Bạn nên đăng nhập\nngay bây giờ để chọn mật khẩu mới. Nếu bạn không phải là người yêu cầu hoặc đã nhớ lại mật khẩu hiện hành, và bạn không còn\nmuốn thay đổi nó, xin vui lòng bỏ qua thông điệp này và tiếp tục sử dụng\nmật khẩu cũ.",
        "passwordreset-emailelement": "Tên người dùng: \n$1\n\nMật khẩu tạm: \n$2",
-       "passwordreset-emailsentemail": "Nếu đây là đúng địa chỉ thư điện tử của tài khoản của bạn, một thư điện tử để tái tạo mật khẩu sẽ được gửi cho bạn.",
-       "passwordreset-emailsentusername": "Nếu một địa chỉ thư điện tử tương ứng đã được đăng ký, chúng tôi sẽ gửi thông tin để đặt lại mật khẩu qua thư điện tử.",
+       "passwordreset-emailsentemail": "Nếu đây là đúng địa chỉ thư điện tử của tài khoản của bạn, một thư điện tử dùng để tái tạo mật khẩu sẽ được gửi cho bạn.",
+       "passwordreset-emailsentusername": "Nếu một địa chỉ thư điện tử đã gắn với tên người dùng này thì một thư điện tử để đặt lại mật khẩu sẽ được gửi đến.",
        "passwordreset-emailsent-capture": "Thư điện tử để tái tạo mật khẩu đã được gửi, nội dung như sau.",
        "passwordreset-emailerror-capture": "Chúng tôi đã tạo thư tái tạo mật khẩu dưới đây, nhưng không thể gửi đến {{GENDER:$2}}người dùng: $1",
        "changeemail": "Đổi hoặc gỡ địa chỉ thư điện tử",
index e244037..67d3c02 100644 (file)
@@ -610,13 +610,13 @@ OO.ui.Element.static.unsafeInfuse = function ( idOrNode, domPromise ) {
                }
                if ( domPromise ) {
                        // pick up dynamic state, like focus, value of form inputs, scroll position, etc.
-                       state = data.gatherPreInfuseState( $elem );
+                       state = data.constructor.static.gatherPreInfuseState( $elem, data );
                        // restore dynamic state after the new element is re-inserted into DOM under infused parent
                        domPromise.done( data.restorePreInfuseState.bind( data, state ) );
                        infusedChildren = $elem.data( 'ooui-infused-children' );
                        if ( infusedChildren && infusedChildren.length ) {
                                infusedChildren.forEach( function ( data ) {
-                                       var state = data.gatherPreInfuseState( $elem );
+                                       var state = data.constructor.static.gatherPreInfuseState( $elem, data );
                                        domPromise.done( data.restorePreInfuseState.bind( data, state ) );
                                } );
                        }
index e52955f..2517605 100644 (file)
        width: 5em;
 }
 
+.mw-apisandbox-help-field {
+       border-bottom: 1px solid rgba( 0, 0, 0, 0.1 );
+}
+
+.mw-apisandbox-help-field:last-child {
+       border-bottom: none;
+}
+
 .mw-apisandbox-optionalWidget {
        width: 100%;
 }
index 10664fa..06d1538 100644 (file)
 
                        // I'm surprised this doesn't seem to exist in jQuery or mw.util.
                        params = {};
-                       hash = hash.replace( '+', '%20' );
+                       hash = hash.replace( /\+/g, '%20' );
                        re = /([^&=#]+)=?([^&#]*)/g;
                        while ( ( m = re.exec( hash ) ) ) {
                                params[ decodeURIComponent( m[ 1 ] ) ] = decodeURIComponent( m[ 2 ] );
                                                                classes: [ 'mw-apisandbox-spacer' ]
                                                        } ), {
                                                                align: 'inline',
+                                                               classes: [ 'mw-apisandbox-help-field' ],
                                                                label: dl
                                                        }
                                                );
                                                        widget,
                                                        {
                                                                align: 'left',
+                                                               classes: [ 'mw-apisandbox-widget-field' ],
                                                                label: prefix + pi.parameters[ i ].name,
                                                                $label: $widgetLabel
                                                        }
index 4ffaeee..71febe3 100644 (file)
        font-size: 1em;
        // Container layout
        display: inline-block;
+       min-width: 4em;
+       max-width: 28.75em; // equivalent to 460px, @see T95367
        padding: .5em 1em;
        margin: 0;
+       border-radius: @borderRadius;
        .box-sizing( border-box );
 
        // Disable weird iOS styling
        *display: inline;
        zoom: 1;
 
-       // Container styling
-       .button-colors( #fff, #ccc, #777 );
-       border-radius: @borderRadius;
-       min-width: 4em;
-
        // Ensure that buttons and inputs are nicely aligned when they have differing heights
        vertical-align: middle;
 
        // Content styling
+       .button-colors( #fff, @colorGray12, @colorGray7 );
        text-align: center;
        font-weight: bold;
 
        &.mw-ui-block {
                display: block;
                width: 100%;
+               margin-left: auto;
+               margin-right: auto;
        }
 
        // Progressive buttons
index 437ddec..981a2e9 100644 (file)
@@ -17,9 +17,9 @@
                };
 
        /**
-        * @private
         * Get nonce for iframe IDs on the page.
         *
+        * @private
         * @return {number}
         */
        function getNonce() {
@@ -27,9 +27,9 @@
        }
 
        /**
-        * @private
         * Given a non-empty object, return one of its keys.
         *
+        * @private
         * @param {Object} obj
         * @return {string}
         */
@@ -42,9 +42,9 @@
        }
 
        /**
-        * @private
         * Get new iframe object for an upload.
         *
+        * @private
         * @return {HTMLIframeElement}
         */
        function getNewIframe( id ) {
@@ -55,9 +55,9 @@
        }
 
        /**
-        * @private
         * Shortcut for getting hidden inputs
         *
+        * @private
         * @return {jQuery}
         */
        function getHiddenInput( name, val ) {
index 549a51f..c42ff30 100644 (file)
@@ -829,7 +829,7 @@ class ParserTest {
                        'wgServer' => 'http://example.org',
                        'wgServerName' => 'example.org',
                        'wgScript' => '/index.php',
-                       'wgScriptPath' => '/',
+                       'wgScriptPath' => '',
                        'wgArticlePath' => '/wiki/$1',
                        'wgActionPaths' => [],
                        'wgLockManagers' => [ [
diff --git a/tests/phpunit/includes/WatchedItemStoreTest.php b/tests/phpunit/includes/WatchedItemStoreTest.php
new file mode 100644 (file)
index 0000000..fc132b0
--- /dev/null
@@ -0,0 +1,91 @@
+<?php
+
+/**
+ * @author Addshore
+ *
+ * @covers WatchedItemStore
+ */
+class WatchedItemStoreTest extends PHPUnit_Framework_TestCase {
+
+       /**
+        * @return PHPUnit_Framework_MockObject_MockObject|IDatabase
+        */
+       private function getMockDb() {
+               return $this->getMock( 'IDatabase' );
+       }
+
+       /**
+        * @return PHPUnit_Framework_MockObject_MockObject|LoadBalancer
+        */
+       private function getMockLoadBalancer( $mockDb ) {
+               $mock = $this->getMockBuilder( 'LoadBalancer' )
+                       ->disableOriginalConstructor()
+                       ->getMock();
+               $mock->expects( $this->any() )
+                       ->method( 'getConnection' )
+                       ->will( $this->returnValue( $mockDb ) );
+               return $mock;
+       }
+
+       private function getFakeRow( $userId, $timestamp ) {
+               $fakeRow = new stdClass();
+               $fakeRow->wl_user = $userId;
+               $fakeRow->wl_notificationtimestamp = $timestamp;
+               return $fakeRow;
+       }
+
+       public function testDuplicateEntry_nothingToDuplicate() {
+               $mockDb = $this->getMockDb();
+               $mockDb->expects( $this->exactly( 1 ) )
+                       ->method( 'select' )
+                       ->will( $this->returnValue( new FakeResultWrapper( [] ) ) );
+
+               $store = new WatchedItemStore( $this->getMockLoadBalancer( $mockDb ) );
+
+               $store->duplicateEntry(
+                       Title::newFromText( 'Old_Title' ),
+                       Title::newFromText( 'New_Title' )
+               );
+       }
+
+       public function testDuplicateEntry_somethingToDuplicate() {
+               $fakeRows = [
+                       $this->getFakeRow( 1, '20151212010101' ),
+                       $this->getFakeRow( 2, null ),
+               ];
+
+               $mockDb = $this->getMockDb();
+               $mockDb->expects( $this->at( 0 ) )
+                       ->method( 'select' )
+                       ->will( $this->returnValue( new FakeResultWrapper( $fakeRows ) ) );
+               $mockDb->expects( $this->at( 1 ) )
+                       ->method( 'replace' )
+                       ->with(
+                               'watchlist',
+                               [ [ 'wl_user', 'wl_namespace', 'wl_title' ] ],
+                               [
+                                       [
+                                               'wl_user' => 1,
+                                               'wl_namespace' => 0,
+                                               'wl_title' => 'New_Title',
+                                               'wl_notificationtimestamp' => '20151212010101',
+                                       ],
+                                       [
+                                               'wl_user' => 2,
+                                               'wl_namespace' => 0,
+                                               'wl_title' => 'New_Title',
+                                               'wl_notificationtimestamp' => null,
+                                       ],
+                               ],
+                               $this->isType( 'string' )
+                       );
+
+               $store = new WatchedItemStore( $this->getMockLoadBalancer( $mockDb ) );
+
+               $store->duplicateEntry(
+                       Title::newFromText( 'Old_Title' ),
+                       Title::newFromText( 'New_Title' )
+               );
+       }
+
+}
index 0c69027..cdb3f78 100644 (file)
@@ -82,7 +82,7 @@ class DummyContentForTesting extends AbstractContent {
         * Returns true if this content is countable as a "real" wiki page, provided
         * that it's also in a countable location (e.g. a current revision in the main namespace).
         *
-        * @param bool $hasLinks If it is known whether this content contains links,
+        * @param bool|null $hasLinks If it is known whether this content contains links,
         * provide this information here, to avoid redundant parsing to find out.
         * @return bool
         */
index 889efb7..afc1a4a 100644 (file)
@@ -82,7 +82,7 @@ class DummyNonTextContent extends AbstractContent {
         * Returns true if this content is countable as a "real" wiki page, provided
         * that it's also in a countable location (e.g. a current revision in the main namespace).
         *
-        * @param bool $hasLinks If it is known whether this content contains links,
+        * @param bool|null $hasLinks If it is known whether this content contains links,
         * provide this information here, to avoid redundant parsing to find out.
         * @return bool
         */