Merge "Set ignore_user_abort( true ) during DB commit for sanity"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Wed, 28 Sep 2016 03:27:58 +0000 (03:27 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Wed, 28 Sep 2016 03:27:58 +0000 (03:27 +0000)
167 files changed:
autoload.php
docs/hooks.txt
includes/DefaultSettings.php
includes/EditPage.php
includes/GlobalFunctions.php
includes/Html.php
includes/MergeHistory.php
includes/MovePage.php
includes/OutputPage.php
includes/TemplateParser.php
includes/WatchedItemQueryService.php
includes/WatchedItemStore.php
includes/api/ApiAuthManagerHelper.php
includes/api/ApiCSPReport.php
includes/api/ApiQuerySearch.php
includes/api/i18n/bn.json
includes/api/i18n/hr.json [new file with mode: 0644]
includes/auth/ButtonAuthenticationRequest.php
includes/auth/LocalPasswordPrimaryAuthenticationProvider.php
includes/auth/PasswordDomainAuthenticationRequest.php
includes/auth/ResetPasswordSecondaryAuthenticationProvider.php
includes/auth/TemporaryPasswordPrimaryAuthenticationProvider.php
includes/cache/LinkBatch.php
includes/changes/ChangesFeed.php
includes/changes/RecentChange.php
includes/changetags/ChangeTags.php
includes/content/ContentHandler.php
includes/content/FileContentHandler.php [new file with mode: 0644]
includes/content/WikiTextStructure.php
includes/content/WikitextContentHandler.php
includes/context/ContextSource.php
includes/dao/DBAccessBase.php
includes/db/DatabaseMssql.php
includes/exception/MWExceptionRenderer.php
includes/filebackend/FileBackendGroup.php
includes/filebackend/SwiftFileBackend.php [deleted file]
includes/filerepo/ForeignDBRepo.php
includes/filerepo/file/LocalFile.php
includes/htmlform/HTMLForm.php
includes/htmlform/OOUIHTMLForm.php
includes/htmlform/fields/HTMLDateTimeField.php [new file with mode: 0644]
includes/installer/DatabaseInstaller.php
includes/installer/DatabaseUpdater.php
includes/installer/MssqlInstaller.php
includes/installer/MysqlInstaller.php
includes/installer/PostgresInstaller.php
includes/installer/SqliteInstaller.php
includes/installer/i18n/diq.json
includes/installer/i18n/nb.json
includes/jobqueue/JobQueueRedis.php
includes/libs/filebackend/FSFileBackend.php
includes/libs/filebackend/FileBackend.php
includes/libs/filebackend/FileBackendStore.php
includes/libs/filebackend/SwiftFileBackend.php [new file with mode: 0644]
includes/libs/lockmanager/DBLockManager.php
includes/libs/lockmanager/RedisLockManager.php
includes/libs/objectcache/RedisBagOStuff.php [new file with mode: 0644]
includes/libs/rdbms/TransactionProfiler.php
includes/libs/rdbms/database/Database.php
includes/libs/rdbms/database/DatabaseBase.php
includes/libs/rdbms/database/DatabaseSqlite.php
includes/libs/rdbms/database/IDatabase.php
includes/libs/rdbms/encasing/LikeMatch.php
includes/libs/rdbms/exception/DBQueryError.php
includes/libs/rdbms/loadbalancer/LoadBalancer.php
includes/libs/virtualrest/VirtualRESTServiceClient.php
includes/logging/LogEntry.php
includes/logging/LogEventsList.php
includes/media/Bitmap.php
includes/media/MediaHandler.php
includes/media/TransformationalImageHandler.php
includes/objectcache/RedisBagOStuff.php [deleted file]
includes/objectcache/SqlBagOStuff.php
includes/page/WikiPage.php
includes/parser/Parser.php
includes/poolcounter/PoolCounterRedis.php
includes/search/SearchIndexField.php
includes/specialpage/AuthManagerSpecialPage.php
includes/specials/SpecialPreferences.php
includes/specials/SpecialRandomInCategory.php
includes/specials/SpecialUserrights.php
includes/tidy/Balancer.php
includes/user/User.php
includes/widget/AUTHORS.txt
includes/widget/DateTimeInputWidget.php [new file with mode: 0644]
languages/Language.php
languages/LanguageConverter.php
languages/classes/LanguageKm.php
languages/classes/LanguageMy.php
languages/i18n/ace.json
languages/i18n/ar.json
languages/i18n/ba.json
languages/i18n/be-tarask.json
languages/i18n/bn.json
languages/i18n/bs.json
languages/i18n/ce.json
languages/i18n/cs.json
languages/i18n/de.json
languages/i18n/diq.json
languages/i18n/dty.json
languages/i18n/egl.json
languages/i18n/el.json
languages/i18n/en.json
languages/i18n/eo.json
languages/i18n/es.json
languages/i18n/eu.json
languages/i18n/fi.json
languages/i18n/fr.json
languages/i18n/gl.json
languages/i18n/he.json
languages/i18n/hr.json
languages/i18n/it.json
languages/i18n/kk-cyrl.json
languages/i18n/kn.json
languages/i18n/ko.json
languages/i18n/lb.json
languages/i18n/lt.json
languages/i18n/lv.json
languages/i18n/mai.json
languages/i18n/mk.json
languages/i18n/mr.json
languages/i18n/nah.json
languages/i18n/nb.json
languages/i18n/nl.json
languages/i18n/olo.json
languages/i18n/or.json
languages/i18n/pl.json
languages/i18n/pnb.json
languages/i18n/pt-br.json
languages/i18n/qqq.json
languages/i18n/ro.json
languages/i18n/ru.json
languages/i18n/sd.json
languages/i18n/sk.json
languages/i18n/sl.json
languages/i18n/uk.json
languages/i18n/ur.json
languages/i18n/yi.json
languages/i18n/zh-hans.json
languages/messages/MessagesEn.php
maintenance/cleanupEmptyCategories.php
maintenance/initEditCount.php
maintenance/language/checkDupeMessages.php
maintenance/language/digit2html.php
maintenance/preprocessorFuzzTest.php
maintenance/rebuildFileCache.php
maintenance/storage/compressOld.php
resources/Resources.php
resources/src/mediawiki.less/mediawiki.ui/variables.less
resources/src/mediawiki.widgets.datetime/DateTimeInputWidget.js
resources/src/mediawiki/htmlform/datetime.js [new file with mode: 0644]
resources/src/mediawiki/mediawiki.Upload.Dialog.js
tests/parser/ParserTestRunner.php
tests/phpunit/MediaWikiTestCase.php
tests/phpunit/includes/WatchedItemQueryServiceUnitTest.php
tests/phpunit/includes/WatchedItemStoreUnitTest.php
tests/phpunit/includes/api/RandomImageGenerator.php
tests/phpunit/includes/content/FileContentHandlerTest.php [new file with mode: 0644]
tests/phpunit/includes/content/WikitextContentHandlerTest.php
tests/phpunit/includes/db/DatabaseMysqlBaseTest.php
tests/phpunit/includes/db/DatabaseSQLTest.php
tests/phpunit/includes/db/DatabaseSqliteTest.php
tests/phpunit/includes/db/DatabaseTest.php
tests/phpunit/includes/db/DatabaseTestHelper.php
tests/phpunit/includes/db/LBFactoryTest.php
tests/phpunit/includes/installer/DatabaseUpdaterTest.php
tests/phpunit/includes/utils/BatchRowUpdateTest.php

index 2df7cbb..dfb0bf6 100644 (file)
@@ -466,6 +466,7 @@ $wgAutoloadLocalClasses = [
        'FileBackendStoreShardListIterator' => __DIR__ . '/includes/libs/filebackend/FileBackendStore.php',
        'FileBasedSiteLookup' => __DIR__ . '/includes/site/FileBasedSiteLookup.php',
        'FileCacheBase' => __DIR__ . '/includes/cache/FileCacheBase.php',
+       'FileContentHandler' => __DIR__ . '/includes/content/FileContentHandler.php',
        'FileContentsHasher' => __DIR__ . '/includes/utils/FileContentsHasher.php',
        'FileDeleteForm' => __DIR__ . '/includes/FileDeleteForm.php',
        'FileDependency' => __DIR__ . '/includes/cache/CacheDependency.php',
@@ -526,6 +527,7 @@ $wgAutoloadLocalClasses = [
        'HTMLCheckField' => __DIR__ . '/includes/htmlform/fields/HTMLCheckField.php',
        'HTMLCheckMatrix' => __DIR__ . '/includes/htmlform/fields/HTMLCheckMatrix.php',
        'HTMLComboboxField' => __DIR__ . '/includes/htmlform/fields/HTMLComboboxField.php',
+       'HTMLDateTimeField' => __DIR__ . '/includes/htmlform/fields/HTMLDateTimeField.php',
        'HTMLEditTools' => __DIR__ . '/includes/htmlform/fields/HTMLEditTools.php',
        'HTMLFileCache' => __DIR__ . '/includes/cache/HTMLFileCache.php',
        'HTMLFloatField' => __DIR__ . '/includes/htmlform/fields/HTMLFloatField.php',
@@ -913,6 +915,7 @@ $wgAutoloadLocalClasses = [
        'MediaWiki\\Tidy\\TidyDriverBase' => __DIR__ . '/includes/tidy/TidyDriverBase.php',
        'MediaWiki\\Widget\\ComplexNamespaceInputWidget' => __DIR__ . '/includes/widget/ComplexNamespaceInputWidget.php',
        'MediaWiki\\Widget\\ComplexTitleInputWidget' => __DIR__ . '/includes/widget/ComplexTitleInputWidget.php',
+       'MediaWiki\\Widget\\DateTimeInputWidget' => __DIR__ . '/includes/widget/DateTimeInputWidget.php',
        'MediaWiki\\Widget\\NamespaceInputWidget' => __DIR__ . '/includes/widget/NamespaceInputWidget.php',
        'MediaWiki\\Widget\\SearchInputWidget' => __DIR__ . '/includes/widget/SearchInputWidget.php',
        'MediaWiki\\Widget\\TitleInputWidget' => __DIR__ . '/includes/widget/TitleInputWidget.php',
@@ -1141,7 +1144,7 @@ $wgAutoloadLocalClasses = [
        'RecompressTracked' => __DIR__ . '/maintenance/storage/recompressTracked.php',
        'RedirectSpecialArticle' => __DIR__ . '/includes/specialpage/RedirectSpecialPage.php',
        'RedirectSpecialPage' => __DIR__ . '/includes/specialpage/RedirectSpecialPage.php',
-       'RedisBagOStuff' => __DIR__ . '/includes/objectcache/RedisBagOStuff.php',
+       'RedisBagOStuff' => __DIR__ . '/includes/libs/objectcache/RedisBagOStuff.php',
        'RedisConnRef' => __DIR__ . '/includes/libs/redis/RedisConnRef.php',
        'RedisConnectionPool' => __DIR__ . '/includes/libs/redis/RedisConnectionPool.php',
        'RedisLockManager' => __DIR__ . '/includes/libs/lockmanager/RedisLockManager.php',
@@ -1396,11 +1399,11 @@ $wgAutoloadLocalClasses = [
        'SubmitAction' => __DIR__ . '/includes/actions/SubmitAction.php',
        'SubpageImportTitleFactory' => __DIR__ . '/includes/title/SubpageImportTitleFactory.php',
        'SvgHandler' => __DIR__ . '/includes/media/SVG.php',
-       'SwiftFileBackend' => __DIR__ . '/includes/filebackend/SwiftFileBackend.php',
-       'SwiftFileBackendDirList' => __DIR__ . '/includes/filebackend/SwiftFileBackend.php',
-       'SwiftFileBackendFileList' => __DIR__ . '/includes/filebackend/SwiftFileBackend.php',
-       'SwiftFileBackendList' => __DIR__ . '/includes/filebackend/SwiftFileBackend.php',
-       'SwiftFileOpHandle' => __DIR__ . '/includes/filebackend/SwiftFileBackend.php',
+       'SwiftFileBackend' => __DIR__ . '/includes/libs/filebackend/SwiftFileBackend.php',
+       'SwiftFileBackendDirList' => __DIR__ . '/includes/libs/filebackend/SwiftFileBackend.php',
+       'SwiftFileBackendFileList' => __DIR__ . '/includes/libs/filebackend/SwiftFileBackend.php',
+       'SwiftFileBackendList' => __DIR__ . '/includes/libs/filebackend/SwiftFileBackend.php',
+       'SwiftFileOpHandle' => __DIR__ . '/includes/libs/filebackend/SwiftFileBackend.php',
        'SwiftVirtualRESTService' => __DIR__ . '/includes/libs/virtualrest/SwiftVirtualRESTService.php',
        'SyncFileBackend' => __DIR__ . '/maintenance/syncFileBackend.php',
        'TableCleanup' => __DIR__ . '/maintenance/cleanupTable.inc',
index 2bfeb66..2dc1270 100644 (file)
@@ -1019,6 +1019,18 @@ $user: user initiating the action
 uses are in active use.
 &$tags: list of all active tags. Append to this array.
 
+'ChangeTagsAfterUpdateTags': Called after tags have been updated with the
+ChangeTags::updateTags function. Params:
+$addedTags: tags effectively added in the update
+$removedTags: tags effectively removed in the update
+$prevTags: tags that were present prior to the update
+$rc_id: recentchanges table id
+$rev_id: revision table id
+$log_id: logging table id
+$params: tag params
+$rc: RecentChange being tagged when the tagging accompanies the action or null
+$user: User who performed the tagging when the tagging is subsequent to the action or null
+
 'Collation::factory': Called if $wgCategoryCollation is an unknown collation.
 $collationName: Name of the collation in question
 &$collationObject: Null. Replace with a subclass of the Collation class that
index 7facf2f..f8626e9 100644 (file)
@@ -6022,7 +6022,7 @@ $wgTrxProfilerLimits = [
        'JobRunner' => [
                'readQueryTime' => 30,
                'writeQueryTime' => 5,
-               'maxAffected' => 1000
+               'maxAffected' => 500 // ballpark of $wgUpdateRowsPerQuery
        ],
        // Command-line scripts
        'Maintenance' => [
index 406673d..f449283 100644 (file)
@@ -3496,7 +3496,7 @@ HTML
         * @param string $format Output format, valid values are any function of a Message object
         * @return string
         */
-       public static function getCopyrightWarning( $title, $format = 'plain' ) {
+       public static function getCopyrightWarning( $title, $format = 'plain', $langcode = null ) {
                global $wgRightsText;
                if ( $wgRightsText ) {
                        $copywarnMsg = [ 'copyrightwarning',
@@ -3509,8 +3509,12 @@ HTML
                // Allow for site and per-namespace customization of contribution/copyright notice.
                Hooks::run( 'EditPageCopyrightWarning', [ $title, &$copywarnMsg ] );
 
+               $msg = call_user_func_array( 'wfMessage', $copywarnMsg )->title( $title );
+               if ( $langcode ) {
+                       $msg->inLanguage( $langcode );
+               }
                return "<div id=\"editpage-copywarn\">\n" .
-                       call_user_func_array( 'wfMessage', $copywarnMsg )->title( $title )->$format() . "\n</div>";
+                       $msg->$format() . "\n</div>";
        }
 
        /**
@@ -4263,7 +4267,7 @@ HTML
        protected function safeUnicodeOutput( $text ) {
                return $this->checkUnicodeCompliantBrowser()
                        ? $text
-                       : $this->makesafe( $text );
+                       : $this->makeSafe( $text );
        }
 
        /**
index 6e8ce8f..5fe4b4e 100644 (file)
@@ -2194,12 +2194,11 @@ function wfIniGetBool( $setting ) {
 }
 
 /**
- * Windows-compatible version of escapeshellarg()
- * Windows doesn't recognise single-quotes in the shell, but the escapeshellarg()
- * function puts single quotes in regardless of OS.
+ * Version of escapeshellarg() that works better on Windows.
  *
- * Also fixes the locale problems on Linux in PHP 5.2.6+ (bug backported to
- * earlier distro releases of PHP)
+ * Originally, this fixed the incorrect use of single quotes on Windows
+ * (https://bugs.php.net/bug.php?id=26285) and the locale problems on Linux in
+ * PHP 5.2.6+ (bug backported to earlier distro releases of PHP).
  *
  * @param string ... strings to escape and glue together, or a single array of strings parameter
  * @return string
index 2ef891d..48b30c7 100644 (file)
@@ -155,8 +155,8 @@ class Html {
         *
         * @param string $contents The raw HTML contents of the element: *not*
         *   escaped!
-        * @param array $attrs Associative array of attributes, e.g., array(
-        *   'href' => 'http://www.mediawiki.org/' ). See expandAttributes() for
+        * @param array $attrs Associative array of attributes, e.g., [
+        *   'href' => 'http://www.mediawiki.org/' ]. See expandAttributes() for
         *   further documentation.
         * @param string[] $modifiers classes to add to the button
         * @see http://tools.wmflabs.org/styleguide/desktop/index.html for guidance on available modifiers
@@ -175,8 +175,8 @@ class Html {
         *
         * @param string $contents The raw HTML contents of the element: *not*
         *   escaped!
-        * @param array $attrs Associative array of attributes, e.g., array(
-        *   'href' => 'http://www.mediawiki.org/' ). See expandAttributes() for
+        * @param array $attrs Associative array of attributes, e.g., [
+        *   'href' => 'http://www.mediawiki.org/' ]. See expandAttributes() for
         *   further documentation.
         * @param string[] $modifiers classes to add to the button
         * @see http://tools.wmflabs.org/styleguide/desktop/index.html for guidance on available modifiers
@@ -199,8 +199,8 @@ class Html {
         * content model.
         *
         * @param string $element The element's name, e.g., 'a'
-        * @param array $attribs Associative array of attributes, e.g., array(
-        *   'href' => 'http://www.mediawiki.org/' ). See expandAttributes() for
+        * @param array $attribs Associative array of attributes, e.g., [
+        *   'href' => 'http://www.mediawiki.org/' ]. See expandAttributes() for
         *   further documentation.
         * @param string $contents The raw HTML contents of the element: *not*
         *   escaped!
@@ -320,8 +320,8 @@ class Html {
         * to the input array (currently per the HTML 5 draft as of 2009-09-06).
         *
         * @param string $element Name of the element, e.g., 'a'
-        * @param array $attribs Associative array of attributes, e.g., array(
-        *   'href' => 'http://www.mediawiki.org/' ).  See expandAttributes() for
+        * @param array $attribs Associative array of attributes, e.g., [
+        *   'href' => 'http://www.mediawiki.org/' ].  See expandAttributes() for
         *   further documentation.
         * @return array An array of attributes functionally identical to $attribs
         */
@@ -430,8 +430,8 @@ class Html {
 
        /**
         * Given an associative array of element attributes, generate a string
-        * to stick after the element name in HTML output.  Like array( 'href' =>
-        * 'http://www.mediawiki.org/' ) becomes something like
+        * to stick after the element name in HTML output.  Like [ 'href' =>
+        * 'http://www.mediawiki.org/' ] becomes something like
         * ' href="http://www.mediawiki.org"'.  Again, this is like
         * Xml::expandAttributes(), but it implements some HTML-specific logic.
         *
@@ -443,25 +443,25 @@ class Html {
         *
         * @par Numerical array
         * @code
-        *     Html::element( 'em', array(
-        *         'class' => array( 'foo', 'bar' )
-        *     ) );
+        *     Html::element( 'em', [
+        *         'class' => [ 'foo', 'bar' ]
+        *     ] );
         *     // gives '<em class="foo bar"></em>'
         * @endcode
         *
         * @par Associative array
         * @code
-        *     Html::element( 'em', array(
-        *         'class' => array( 'foo', 'bar', 'foo' => false, 'quux' => true )
-        *     ) );
+        *     Html::element( 'em', [
+        *         'class' => [ 'foo', 'bar', 'foo' => false, 'quux' => true ]
+        *     ] );
         *     // gives '<em class="bar quux"></em>'
         * @endcode
         *
-        * @param array $attribs Associative array of attributes, e.g., array(
-        *   'href' => 'http://www.mediawiki.org/' ).  Values will be HTML-escaped.
+        * @param array $attribs Associative array of attributes, e.g., [
+        *   'href' => 'http://www.mediawiki.org/' ].  Values will be HTML-escaped.
         *   A value of false means to omit the attribute.  For boolean attributes,
-        *   you can omit the key, e.g., array( 'checked' ) instead of
-        *   array( 'checked' => 'checked' ) or such.
+        *   you can omit the key, e.g., [ 'checked' ] instead of
+        *   [ 'checked' => 'checked' ] or such.
         *
         * @throws MWException If an attribute that doesn't allow lists is set to an array
         * @return string HTML fragment that goes between element name and '>'
@@ -470,13 +470,13 @@ class Html {
        public static function expandAttributes( array $attribs ) {
                $ret = '';
                foreach ( $attribs as $key => $value ) {
-                       // Support intuitive array( 'checked' => true/false ) form
+                       // Support intuitive [ 'checked' => true/false ] form
                        if ( $value === false || is_null( $value ) ) {
                                continue;
                        }
 
-                       // For boolean attributes, support array( 'foo' ) instead of
-                       // requiring array( 'foo' => 'meaningless' ).
+                       // For boolean attributes, support [ 'foo' ] instead of
+                       // requiring [ 'foo' => 'meaningless' ].
                        if ( is_int( $key ) && in_array( strtolower( $value ), self::$boolAttribs ) ) {
                                $key = $value;
                        }
@@ -533,7 +533,7 @@ class Html {
                                                        }
                                                } elseif ( $v ) {
                                                        // If the value is truthy but not a string this is likely
-                                                       // an array( 'foo' => true ), falsy values don't add strings
+                                                       // an [ 'foo' => true ], falsy values don't add strings
                                                        $newValue[] = $k;
                                                }
                                        }
@@ -1009,11 +1009,11 @@ class Html {
         *
         * @par Example:
         * @code
-        *     Html::srcSet( array(
+        *     Html::srcSet( [
         *         '1x'   => 'standard.jpeg',
         *         '1.5x' => 'large.jpeg',
         *         '3x'   => 'extra-large.jpeg',
-        *     ) );
+        *     ] );
         *     // gives 'standard.jpeg 1x, large.jpeg 1.5x, extra-large.jpeg 2x'
         * @endcode
         *
index dd1fd37..f797fe3 100644 (file)
@@ -42,7 +42,7 @@ class MergeHistory {
        /** @var Title Page to which history will be merged */
        protected $dest;
 
-       /** @var DatabaseBase Database that we are using */
+       /** @var IDatabase Database that we are using */
        protected $dbw;
 
        /** @var MWTimestamp Maximum timestamp that we can use (oldest timestamp of dest) */
index d17f234..5f1dd3f 100644 (file)
@@ -446,7 +446,7 @@ class MovePage {
                        $status = $newpage->doDeleteArticleReal(
                                $overwriteMessage,
                                /* $suppress */ false,
-                               $nt->getArticleId(),
+                               $nt->getArticleID(),
                                /* $commit */ false,
                                $errs,
                                $user
index f5405d7..b2e7d94 100644 (file)
@@ -2356,7 +2356,7 @@ class OutputPage extends ContextSource {
         * Output a standard error page
         *
         * showErrorPage( 'titlemsg', 'pagetextmsg' );
-        * showErrorPage( 'titlemsg', 'pagetextmsg', array( 'param1', 'param2' ) );
+        * showErrorPage( 'titlemsg', 'pagetextmsg', [ 'param1', 'param2' ] );
         * showErrorPage( 'titlemsg', $messageObject );
         * showErrorPage( $titleMessageObject, $messageObject );
         *
index 20142a7..a1e6d5b 100644 (file)
@@ -186,10 +186,10 @@ class TemplateParser {
         * @code
         *     echo $templateParser->processTemplate(
         *         'ExampleTemplate',
-        *         array(
+        *         [
         *             'username' => $user->getName(),
         *             'message' => 'Hello!'
-        *         )
+        *         ]
         *     );
         * @endcode
         * @param string $templateName The name of the template
index 4ac4dea..c040fb1 100644 (file)
@@ -63,10 +63,10 @@ class WatchedItemQueryService {
        }
 
        /**
-        * @param DatabaseBase $connection
+        * @param Database $connection
         * @throws MWException
         */
-       private function reuseConnection( DatabaseBase $connection ) {
+       private function reuseConnection( Database $connection ) {
                $this->loadBalancer->reuseConnection( $connection );
        }
 
@@ -337,7 +337,7 @@ class WatchedItemQueryService {
        }
 
        private function getWatchedItemsWithRCInfoQueryConds(
-               DatabaseBase $db,
+               Database $db,
                User $user,
                array $options
        ) {
@@ -445,7 +445,7 @@ class WatchedItemQueryService {
                return $conds;
        }
 
-       private function getStartEndConds( DatabaseBase $db, array $options ) {
+       private function getStartEndConds( Database $db, array $options ) {
                if ( !isset( $options['start'] ) && ! isset( $options['end'] ) ) {
                        return [];
                }
@@ -464,7 +464,7 @@ class WatchedItemQueryService {
                return $conds;
        }
 
-       private function getUserRelatedConds( DatabaseBase $db, User $user, array $options ) {
+       private function getUserRelatedConds( Database $db, User $user, array $options ) {
                if ( !array_key_exists( 'onlyByUser', $options ) && !array_key_exists( 'notByUser', $options ) ) {
                        return [];
                }
@@ -491,7 +491,7 @@ class WatchedItemQueryService {
                return $conds;
        }
 
-       private function getExtraDeletedPageLogEntryRelatedCond( DatabaseBase $db, User $user ) {
+       private function getExtraDeletedPageLogEntryRelatedCond( Database $db, User $user ) {
                // LogPage::DELETED_ACTION hides the affected page, too. So hide those
                // entirely from the watchlist, or someone could guess the title.
                $bitmask = 0;
@@ -509,7 +509,7 @@ class WatchedItemQueryService {
                return '';
        }
 
-       private function getStartFromConds( DatabaseBase $db, array $options ) {
+       private function getStartFromConds( Database $db, array $options ) {
                $op = $options['dir'] === self::DIR_OLDER ? '<' : '>';
                list( $rcTimestamp, $rcId ) = $options['startFrom'];
                $rcTimestamp = $db->addQuotes( $db->timestamp( $rcTimestamp ) );
@@ -529,7 +529,7 @@ class WatchedItemQueryService {
                );
        }
 
-       private function getWatchedItemsForUserQueryConds( DatabaseBase $db, User $user, array $options ) {
+       private function getWatchedItemsForUserQueryConds( Database $db, User $user, array $options ) {
                $conds = [ 'wl_user' => $user->getId() ];
                if ( $options['namespaceIds'] ) {
                        $conds['wl_namespace'] = array_map( 'intval', $options['namespaceIds'] );
@@ -563,12 +563,12 @@ class WatchedItemQueryService {
         * Creates a query condition part for getting only items before or after the given link target
         * (while ordering using $sort mode)
         *
-        * @param DatabaseBase $db
+        * @param Database $db
         * @param LinkTarget $target
         * @param string $op comparison operator to use in the conditions
         * @return string
         */
-       private function getFromUntilTargetConds( DatabaseBase $db, LinkTarget $target, $op ) {
+       private function getFromUntilTargetConds( Database $db, LinkTarget $target, $op ) {
                return $db->makeList(
                        [
                                "wl_namespace $op " . $target->getNamespace(),
index 9a74401..90d45ce 100644 (file)
@@ -192,20 +192,11 @@ class WatchedItemStore implements StatsdAwareInterface {
        /**
         * @param int $dbIndex DB_MASTER or DB_REPLICA
         *
-        * @return DatabaseBase
+        * @return IDatabase
         * @throws MWException
         */
-       private function getConnection( $dbIndex ) {
-               return $this->loadBalancer->getConnection( $dbIndex, [ 'watchlist' ] );
-       }
-
-       /**
-        * @param DatabaseBase $connection
-        *
-        * @throws MWException
-        */
-       private function reuseConnection( $connection ) {
-               $this->loadBalancer->reuseConnection( $connection );
+       private function getConnectionRef( $dbIndex ) {
+               return $this->loadBalancer->getConnectionRef( $dbIndex, [ 'watchlist' ] );
        }
 
        /**
@@ -217,7 +208,7 @@ class WatchedItemStore implements StatsdAwareInterface {
         * @return int
         */
        public function countWatchedItems( User $user ) {
-               $dbr = $this->getConnection( DB_REPLICA );
+               $dbr = $this->getConnectionRef( DB_REPLICA );
                $return = (int)$dbr->selectField(
                        'watchlist',
                        'COUNT(*)',
@@ -226,7 +217,6 @@ class WatchedItemStore implements StatsdAwareInterface {
                        ],
                        __METHOD__
                );
-               $this->reuseConnection( $dbr );
 
                return $return;
        }
@@ -237,7 +227,7 @@ class WatchedItemStore implements StatsdAwareInterface {
         * @return int
         */
        public function countWatchers( LinkTarget $target ) {
-               $dbr = $this->getConnection( DB_REPLICA );
+               $dbr = $this->getConnectionRef( DB_REPLICA );
                $return = (int)$dbr->selectField(
                        'watchlist',
                        'COUNT(*)',
@@ -247,7 +237,6 @@ class WatchedItemStore implements StatsdAwareInterface {
                        ],
                        __METHOD__
                );
-               $this->reuseConnection( $dbr );
 
                return $return;
        }
@@ -263,7 +252,7 @@ class WatchedItemStore implements StatsdAwareInterface {
         * @throws MWException
         */
        public function countVisitingWatchers( LinkTarget $target, $threshold ) {
-               $dbr = $this->getConnection( DB_REPLICA );
+               $dbr = $this->getConnectionRef( DB_REPLICA );
                $visitingWatchers = (int)$dbr->selectField(
                        'watchlist',
                        'COUNT(*)',
@@ -276,7 +265,6 @@ class WatchedItemStore implements StatsdAwareInterface {
                        ],
                        __METHOD__
                );
-               $this->reuseConnection( $dbr );
 
                return $visitingWatchers;
        }
@@ -293,7 +281,7 @@ class WatchedItemStore implements StatsdAwareInterface {
        public function countWatchersMultiple( array $targets, array $options = [] ) {
                $dbOptions = [ 'GROUP BY' => [ 'wl_namespace', 'wl_title' ] ];
 
-               $dbr = $this->getConnection( DB_REPLICA );
+               $dbr = $this->getConnectionRef( DB_REPLICA );
 
                if ( array_key_exists( 'minimumWatchers', $options ) ) {
                        $dbOptions['HAVING'] = 'COUNT(*) >= ' . (int)$options['minimumWatchers'];
@@ -308,8 +296,6 @@ class WatchedItemStore implements StatsdAwareInterface {
                        $dbOptions
                );
 
-               $this->reuseConnection( $dbr );
-
                $watchCounts = [];
                foreach ( $targets as $linkTarget ) {
                        $watchCounts[$linkTarget->getNamespace()][$linkTarget->getDBkey()] = 0;
@@ -341,7 +327,7 @@ class WatchedItemStore implements StatsdAwareInterface {
                array $targetsWithVisitThresholds,
                $minimumWatchers = null
        ) {
-               $dbr = $this->getConnection( DB_REPLICA );
+               $dbr = $this->getConnectionRef( DB_REPLICA );
 
                $conds = $this->getVisitingWatchersCondition( $dbr, $targetsWithVisitThresholds );
 
@@ -357,8 +343,6 @@ class WatchedItemStore implements StatsdAwareInterface {
                        $dbOptions
                );
 
-               $this->reuseConnection( $dbr );
-
                $watcherCounts = [];
                foreach ( $targetsWithVisitThresholds as list( $target ) ) {
                        /* @var LinkTarget $target */
@@ -452,14 +436,13 @@ class WatchedItemStore implements StatsdAwareInterface {
                        return false;
                }
 
-               $dbr = $this->getConnection( DB_REPLICA );
+               $dbr = $this->getConnectionRef( DB_REPLICA );
                $row = $dbr->selectRow(
                        'watchlist',
                        'wl_notificationtimestamp',
                        $this->dbCond( $user, $target ),
                        __METHOD__
                );
-               $this->reuseConnection( $dbr );
 
                if ( !$row ) {
                        return false;
@@ -499,7 +482,7 @@ class WatchedItemStore implements StatsdAwareInterface {
                                "wl_title {$options['sort']}"
                        ];
                }
-               $db = $this->getConnection( $options['forWrite'] ? DB_MASTER : DB_REPLICA );
+               $db = $this->getConnectionRef( $options['forWrite'] ? DB_MASTER : DB_REPLICA );
 
                $res = $db->select(
                        'watchlist',
@@ -508,7 +491,6 @@ class WatchedItemStore implements StatsdAwareInterface {
                        __METHOD__,
                        $dbOptions
                );
-               $this->reuseConnection( $db );
 
                $watchedItems = [];
                foreach ( $res as $row ) {
@@ -569,7 +551,7 @@ class WatchedItemStore implements StatsdAwareInterface {
                        return $timestamps;
                }
 
-               $dbr = $this->getConnection( DB_REPLICA );
+               $dbr = $this->getConnectionRef( DB_REPLICA );
 
                $lb = new LinkBatch( $targetsToLoad );
                $res = $dbr->select(
@@ -581,7 +563,6 @@ class WatchedItemStore implements StatsdAwareInterface {
                        ],
                        __METHOD__
                );
-               $this->reuseConnection( $dbr );
 
                foreach ( $res as $row ) {
                        $timestamps[$row->wl_namespace][$row->wl_title] = $row->wl_notificationtimestamp;
@@ -630,13 +611,12 @@ class WatchedItemStore implements StatsdAwareInterface {
                        $this->uncache( $user, $target );
                }
 
-               $dbw = $this->getConnection( DB_MASTER );
+               $dbw = $this->getConnectionRef( DB_MASTER );
                foreach ( array_chunk( $rows, 100 ) as $toInsert ) {
                        // Use INSERT IGNORE to avoid overwriting the notification timestamp
                        // if there's already an entry for this page
                        $dbw->insert( 'watchlist', $toInsert, __METHOD__, 'IGNORE' );
                }
-               $this->reuseConnection( $dbw );
 
                return true;
        }
@@ -660,7 +640,7 @@ class WatchedItemStore implements StatsdAwareInterface {
 
                $this->uncache( $user, $target );
 
-               $dbw = $this->getConnection( DB_MASTER );
+               $dbw = $this->getConnectionRef( DB_MASTER );
                $dbw->delete( 'watchlist',
                        [
                                'wl_user' => $user->getId(),
@@ -669,7 +649,6 @@ class WatchedItemStore implements StatsdAwareInterface {
                        ], __METHOD__
                );
                $success = (bool)$dbw->affectedRows();
-               $this->reuseConnection( $dbw );
 
                return $success;
        }
@@ -687,7 +666,7 @@ class WatchedItemStore implements StatsdAwareInterface {
                        return false;
                }
 
-               $dbw = $this->getConnection( DB_MASTER );
+               $dbw = $this->getConnectionRef( DB_MASTER );
 
                $conds = [ 'wl_user' => $user->getId() ];
                if ( $targets ) {
@@ -702,8 +681,6 @@ class WatchedItemStore implements StatsdAwareInterface {
                        __METHOD__
                );
 
-               $this->reuseConnection( $dbw );
-
                $this->uncacheUser( $user );
 
                return $success;
@@ -718,7 +695,7 @@ class WatchedItemStore implements StatsdAwareInterface {
         * @return int[] Array of user IDs the timestamp has been updated for
         */
        public function updateNotificationTimestamp( User $editor, LinkTarget $target, $timestamp ) {
-               $dbw = $this->getConnection( DB_MASTER );
+               $dbw = $this->getConnectionRef( DB_MASTER );
                $uids = $dbw->selectFieldValues(
                        'watchlist',
                        'wl_user',
@@ -730,7 +707,6 @@ class WatchedItemStore implements StatsdAwareInterface {
                        ],
                        __METHOD__
                );
-               $this->reuseConnection( $dbw );
 
                $watchers = array_map( 'intval', $uids );
                if ( $watchers ) {
@@ -740,7 +716,7 @@ class WatchedItemStore implements StatsdAwareInterface {
                                function () use ( $timestamp, $watchers, $target, $fname ) {
                                        global $wgUpdateRowsPerQuery;
 
-                                       $dbw = $this->getConnection( DB_MASTER );
+                                       $dbw = $this->getConnectionRef( DB_MASTER );
                                        $factory = wfGetLBFactory();
                                        $ticket = $factory->getEmptyTransactionTicket( __METHOD__ );
 
@@ -762,8 +738,6 @@ class WatchedItemStore implements StatsdAwareInterface {
                                                }
                                        }
                                        $this->uncacheLinkTarget( $target );
-
-                                       $this->reuseConnection( $dbw );
                                },
                                DeferredUpdates::POSTSEND,
                                $dbw
@@ -885,7 +859,7 @@ class WatchedItemStore implements StatsdAwareInterface {
                        $queryOptions['LIMIT'] = $unreadLimit;
                }
 
-               $dbr = $this->getConnection( DB_REPLICA );
+               $dbr = $this->getConnectionRef( DB_REPLICA );
                $rowCount = $dbr->selectRowCount(
                        'watchlist',
                        '1',
@@ -896,7 +870,6 @@ class WatchedItemStore implements StatsdAwareInterface {
                        __METHOD__,
                        $queryOptions
                );
-               $this->reuseConnection( $dbr );
 
                if ( !isset( $unreadLimit ) ) {
                        return $rowCount;
@@ -937,7 +910,7 @@ class WatchedItemStore implements StatsdAwareInterface {
         * @param LinkTarget $newTarget
         */
        public function duplicateEntry( LinkTarget $oldTarget, LinkTarget $newTarget ) {
-               $dbw = $this->getConnection( DB_MASTER );
+               $dbw = $this->getConnectionRef( DB_MASTER );
 
                $result = $dbw->select(
                        'watchlist',
@@ -975,8 +948,6 @@ class WatchedItemStore implements StatsdAwareInterface {
                                __METHOD__
                        );
                }
-
-               $this->reuseConnection( $dbw );
        }
 
 }
index 8e57f93..1a42ccc 100644 (file)
@@ -191,8 +191,6 @@ class ApiAuthManagerHelper {
         * @return array
         */
        public function formatAuthenticationResponse( AuthenticationResponse $res ) {
-               $params = $this->module->extractRequestParams();
-
                $ret = [
                        'status' => $res->status,
                ];
index 407ae71..5a0edfc 100644 (file)
@@ -85,7 +85,6 @@ class ApiCSPReport extends ApiBase {
         */
        private function getFlags( $report ) {
                $reportOnly = $this->getParameter( 'reportonly' );
-               $userAgent = $this->getRequest()->getHeader( 'user-agent' );
                $source = $this->getParameter( 'source' );
                $falsePositives = $this->getConfig()->get( 'CSPFalsePositiveUrls' );
 
index f46b5d2..ba60da9 100644 (file)
@@ -24,8 +24,6 @@
  * @file
  */
 
-use MediaWiki\MediaWikiServices;
-
 /**
  * Query module to perform full text search within wiki titles and content
  *
@@ -235,7 +233,7 @@ class ApiQuerySearch extends ApiQueryGeneratorBase {
                                                $vals = [
                                                        'namespace' => $result->getInterwikiNamespaceText(),
                                                        'title' => $title->getText(),
-                                                       'url' => $title->getFullUrl(),
+                                                       'url' => $title->getFullURL(),
                                                ];
 
                                                // Add item to results and see whether it fits
index c93d8ba..874639a 100644 (file)
@@ -2,9 +2,11 @@
        "@metadata": {
                "authors": [
                        "Aftabuzzaman",
-                       "Bodhisattwa"
+                       "Bodhisattwa",
+                       "আজিজ"
                ]
        },
+       "apihelp-main-param-format": "আউটপুটের বিন্যাস",
        "apihelp-block-description": "ব্যবহারকারীকে বাধা দিন।",
        "apihelp-createaccount-param-name": "ব্যবহারকারী নাম।",
        "apihelp-delete-description": "একটি পাতা মুছে ফেলুন।",
diff --git a/includes/api/i18n/hr.json b/includes/api/i18n/hr.json
new file mode 100644 (file)
index 0000000..5f46e73
--- /dev/null
@@ -0,0 +1,9 @@
+{
+       "@metadata": {
+               "authors": [
+                       "Ex13"
+               ]
+       },
+       "apihelp-block-description": "Blokiraj suradnika.",
+       "apihelp-block-param-user": "Suradničko ime, IP adresa ili opseg koje želite blokirati."
+}
index 055d7ea..d274e18 100644 (file)
@@ -81,6 +81,8 @@ class ButtonAuthenticationRequest extends AuthenticationRequest {
 
        /**
         * @codeCoverageIgnore
+        * @param array $data
+        * @return AuthenticationRequest|static
         */
        public static function __set_state( $data ) {
                if ( !isset( $data['label'] ) ) {
index bbc6e8d..88df68d 100644 (file)
@@ -88,8 +88,8 @@ class LocalPasswordPrimaryAuthenticationProvider
                        'user_id', 'user_password', 'user_password_expires',
                ];
 
-               $dbw = wfGetDB( DB_MASTER );
-               $row = $dbw->selectRow(
+               $dbr = wfGetDB( DB_REPLICA );
+               $row = $dbr->selectRow(
                        'user',
                        $fields,
                        [ 'user_name' => $username ],
@@ -99,6 +99,7 @@ class LocalPasswordPrimaryAuthenticationProvider
                        return AuthenticationResponse::newAbstain();
                }
 
+               $oldRow = clone $row;
                // Check for *really* old password hashes that don't even have a type
                // The old hash format was just an md5 hex hash, with no type information
                if ( preg_match( '/^[0-9a-f]{32}$/', $row->user_password ) ) {
@@ -132,12 +133,18 @@ class LocalPasswordPrimaryAuthenticationProvider
                // @codeCoverageIgnoreStart
                if ( $this->getPasswordFactory()->needsUpdate( $pwhash ) ) {
                        $pwhash = $this->getPasswordFactory()->newFromPlaintext( $req->password );
-                       $dbw->update(
-                               'user',
-                               [ 'user_password' => $pwhash->toString() ],
-                               [ 'user_id' => $row->user_id ],
-                               __METHOD__
-                       );
+                       \DeferredUpdates::addCallableUpdate( function () use ( $pwhash, $oldRow ) {
+                               $dbw = wfGetDB( DB_MASTER );
+                               $dbw->update(
+                                       'user',
+                                       [ 'user_password' => $pwhash->toString() ],
+                                       [
+                                               'user_id' => $oldRow->user_id,
+                                               'user_password' => $oldRow->user_password
+                                       ],
+                                       __METHOD__
+                               );
+                       } );
                }
                // @codeCoverageIgnoreEnd
 
@@ -152,8 +159,8 @@ class LocalPasswordPrimaryAuthenticationProvider
                        return false;
                }
 
-               $dbw = wfGetDB( DB_MASTER );
-               $row = $dbw->selectRow(
+               $dbr = wfGetDB( DB_REPLICA );
+               $row = $dbr->selectRow(
                        'user',
                        [ 'user_password' ],
                        [ 'user_name' => $username ],
index ddad54b..3db7e21 100644 (file)
@@ -70,6 +70,8 @@ class PasswordDomainAuthenticationRequest extends PasswordAuthenticationRequest
 
        /**
         * @codeCoverageIgnore
+        * @param array $data
+        * @return AuthenticationRequest|static
         */
        public static function __set_state( $data ) {
                $ret = new static( $data['domainList'] );
index f11a12c..45ac3aa 100644 (file)
@@ -58,6 +58,7 @@ class ResetPasswordSecondaryAuthenticationProvider extends AbstractSecondaryAuth
 
        /**
         * Try to reset the password
+        * @param \User $user
         * @param AuthenticationRequest[] $reqs
         * @return AuthenticationResponse
         */
index f16423d..9962fa3 100644 (file)
@@ -140,7 +140,7 @@ class TemporaryPasswordPrimaryAuthenticationProvider
                }
 
                $status = $this->checkPasswordValidity( $username, $req->password );
-               if ( !$status->isOk() ) {
+               if ( !$status->isOK() ) {
                        // Fatal, can't log in
                        return AuthenticationResponse::newFail( $status->getMessage() );
                }
index 8a4d061..d773fff 100644 (file)
@@ -236,7 +236,7 @@ class LinkBatch {
         * Construct a WHERE clause which will match all the given titles.
         *
         * @param string $prefix The appropriate table's field name prefix ('page', 'pl', etc)
-        * @param IDatabase $db DatabaseBase object to use
+        * @param IDatabase $db DB object to use
         * @return string|bool String with SQL where clause fragment, or false if no items.
         */
        public function constructSet( $prefix, $db ) {
index ca6ba48..15a00c7 100644 (file)
@@ -164,7 +164,7 @@ class ChangesFeed {
 
        /**
         * Generate the feed items given a row from the database, printing the feed.
-        * @param object $rows DatabaseBase resource with recentchanges rows
+        * @param object $rows IDatabase resource with recentchanges rows
         * @param ChannelFeed $feed
         */
        public static function generateFeed( $rows, &$feed ) {
@@ -178,7 +178,7 @@ class ChangesFeed {
 
        /**
         * Generate the feed items given a row from the database.
-        * @param object $rows DatabaseBase resource with recentchanges rows
+        * @param object $rows IDatabase resource with recentchanges rows
         * @return array
         */
        public static function buildItems( $rows ) {
index 794865e..1262f2c 100644 (file)
@@ -90,6 +90,11 @@ class RecentChange {
         */
        public $counter = -1;
 
+       /**
+        * @var array List of tags to apply
+        */
+       private $tags = [];
+
        /**
         * @var array Array of change types
         */
@@ -326,6 +331,11 @@ class RecentChange {
                # Notify extensions
                Hooks::run( 'RecentChange_save', [ &$this ] );
 
+               if ( count( $this->tags ) ) {
+                       ChangeTags::addTags( $this->tags, $this->mAttribs['rc_id'],
+                               $this->mAttribs['rc_this_oldid'], $this->mAttribs['rc_logid'], null, $this );
+               }
+
                # Notify external application via UDP
                if ( !$noudp ) {
                        $this->notifyRCFeeds();
@@ -610,14 +620,11 @@ class RecentChange {
 
                DeferredUpdates::addCallableUpdate(
                        function () use ( $rc, $tags ) {
+                               $rc->addTags( $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 )
@@ -686,14 +693,11 @@ class RecentChange {
 
                DeferredUpdates::addCallableUpdate(
                        function () use ( $rc, $tags ) {
+                               $rc->addTags( $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 )
@@ -1026,4 +1030,20 @@ class RecentChange {
 
                return $unserializedParams;
        }
+
+       /**
+        * Tags to append to the recent change,
+        * and associated revision/log
+        *
+        * @since 1.28
+        *
+        * @param string|array $tags
+        */
+       public function addTags( $tags ) {
+               if ( is_string( $tags ) ) {
+                       $this->tags[] = $tags;
+               } else {
+                       $this->tags = array_merge( $tags, $this->tags );
+               }
+       }
 }
index 6455a3a..76dd754 100644 (file)
@@ -124,14 +124,16 @@ class ChangeTags {
         * @param int|null $rev_id The rev_id of the change to add the tags to
         * @param int|null $log_id The log_id of the change to add the tags to
         * @param string $params Params to put in the ct_params field of table 'change_tag'
+        * @param RecentChange|null $rc Recent change, in case the tagging accompanies the action
+        * (this should normally be the case)
         *
         * @throws MWException
         * @return bool False if no changes are made, otherwise true
         */
        public static function addTags( $tags, $rc_id = null, $rev_id = null,
-               $log_id = null, $params = null
+               $log_id = null, $params = null, RecentChange $rc = null
        ) {
-               $result = self::updateTags( $tags, null, $rc_id, $rev_id, $log_id, $params );
+               $result = self::updateTags( $tags, null, $rc_id, $rev_id, $log_id, $params, $rc );
                return (bool)$result[0];
        }
 
@@ -154,6 +156,9 @@ class ChangeTags {
         * Pass a variable whose value is null if the log_id is not relevant or unknown.
         * @param string $params Params to put in the ct_params field of table
         * 'change_tag' when adding tags
+        * @param RecentChange|null $rc Recent change being tagged, in case the tagging accompanies
+        * the action
+        * @param User|null $user Tagging user, in case the tagging is subsequent to the tagged action
         *
         * @throws MWException When $rc_id, $rev_id and $log_id are all null
         * @return array Index 0 is an array of tags actually added, index 1 is an
@@ -162,9 +167,9 @@ class ChangeTags {
         *
         * @since 1.25
         */
-       public static function updateTags(
-               $tagsToAdd, $tagsToRemove,
-               &$rc_id = null, &$rev_id = null, &$log_id = null, $params = null
+       public static function updateTags( $tagsToAdd, $tagsToRemove, &$rc_id = null,
+               &$rev_id = null, &$log_id = null, $params = null, RecentChange $rc = null,
+               User $user = null
        ) {
 
                $tagsToAdd = array_filter( (array)$tagsToAdd ); // Make sure we're submitting all tags...
@@ -284,6 +289,10 @@ class ChangeTags {
                }
 
                self::purgeTagUsageCache();
+
+               Hooks::run( 'ChangeTagsAfterUpdateTags', [ $tagsToAdd, $tagsToRemove, $prevTags,
+                       $rc_id, $rev_id, $log_id, $params, $rc, $user ] );
+
                return [ $tagsToAdd, $tagsToRemove, $prevTags ];
        }
 
@@ -546,7 +555,7 @@ class ChangeTags {
 
                // do it!
                list( $tagsAdded, $tagsRemoved, $initialTags ) = self::updateTags( $tagsToAdd,
-                       $tagsToRemove, $rc_id, $rev_id, $log_id, $params );
+                       $tagsToRemove, $rc_id, $rev_id, $log_id, $params, null, $user );
                if ( !$tagsAdded && !$tagsRemoved ) {
                        // no-op, don't log it
                        return Status::newGood( (object)[
@@ -608,10 +617,10 @@ class ChangeTags {
         * Handles selecting tags, and filtering.
         * Needs $tables to be set up properly, so we can figure out which join conditions to use.
         *
-        * @param string|array $tables Table names, see DatabaseBase::select
-        * @param string|array $fields Fields used in query, see DatabaseBase::select
-        * @param string|array $conds Conditions used in query, see DatabaseBase::select
-        * @param array $join_conds Join conditions, see DatabaseBase::select
+        * @param string|array $tables Table names, see Database::select
+        * @param string|array $fields Fields used in query, see Database::select
+        * @param string|array $conds Conditions used in query, see Database::select
+        * @param array $join_conds Join conditions, see Database::select
         * @param array $options Options, see Database::select
         * @param bool|string $filter_tag Tag to select on
         *
@@ -656,21 +665,15 @@ class ChangeTags {
         * Build a text box to select a change tag
         *
         * @param string $selected Tag to select by default
-        * @param bool $fullForm Affects return value, see below
-        * @param Title $title Title object to send the form to. Used only if $fullForm is true.
         * @param bool $ooui Use an OOUI TextInputWidget as selector instead of a non-OOUI input field
         *        You need to call OutputPage::enableOOUI() yourself.
-        * @return string|array
-        *        - if $fullForm is false: an array of (label, selector).
-        *        - if $fullForm is true: HTML of entire form built around the selector.
+        * @return array an array of (label, selector)
         */
-       public static function buildTagFilterSelector( $selected = '',
-               $fullForm = false, Title $title = null, $ooui = false
-       ) {
+       public static function buildTagFilterSelector( $selected = '', $ooui = false ) {
                global $wgUseTagFilter;
 
                if ( !$wgUseTagFilter || !count( self::listDefinedTags() ) ) {
-                       return $fullForm ? '' : [];
+                       return [];
                }
 
                $data = [
@@ -697,24 +700,7 @@ class ChangeTags {
                        );
                }
 
-               if ( !$fullForm ) {
-                       return $data;
-               }
-
-               $html = implode( '&#160;', $data );
-               $html .= "\n" .
-                       Xml::element(
-                               'input',
-                               [ 'type' => 'submit', 'value' => wfMessage( 'tag-filter-submit' )->text() ]
-                       );
-               $html .= "\n" . Html::hidden( 'title', $title->getPrefixedText() );
-               $html = Xml::tags(
-                       'form',
-                       [ 'action' => $title->getLocalURL(), 'class' => 'mw-tagfilter-form', 'method' => 'get' ],
-                       $html
-               );
-
-               return $html;
+               return $data;
        }
 
        /**
index 4e50c8e..d709c5c 100644 (file)
@@ -706,7 +706,7 @@ abstract class ContentHandler {
                if ( $title->getNamespace() == NS_MEDIAWIKI ) {
                        // Parse mediawiki messages with correct target language
                        list( /* $unused */, $lang ) = MessageCache::singleton()->figureMessage( $title->getText() );
-                       $pageLang = wfGetLangObj( $lang );
+                       $pageLang = Language::factory( $lang );
                }
 
                Hooks::run( 'PageContentLanguage', [ $title, &$pageLang, $wgLang ] );
diff --git a/includes/content/FileContentHandler.php b/includes/content/FileContentHandler.php
new file mode 100644 (file)
index 0000000..26f1190
--- /dev/null
@@ -0,0 +1,62 @@
+<?php
+
+/**
+ * Content handler for File: files
+ * TODO: this handler s not used directly now,
+ * but instead manually called by WikitextHandler.
+ * This should be fixed in the future.
+ */
+class FileContentHandler extends WikitextContentHandler  {
+
+       public function getFieldsForSearchIndex( SearchEngine $engine ) {
+               $fields['file_media_type'] =
+                       $engine->makeSearchFieldMapping( 'file_media_type', SearchIndexField::INDEX_TYPE_KEYWORD );
+               $fields['file_media_type']->setFlag( SearchIndexField::FLAG_CASEFOLD );
+               $fields['file_mime'] =
+                       $engine->makeSearchFieldMapping( 'file_mime', SearchIndexField::INDEX_TYPE_SHORT_TEXT );
+               $fields['file_mime']->setFlag( SearchIndexField::FLAG_CASEFOLD );
+               $fields['file_size'] =
+                       $engine->makeSearchFieldMapping( 'file_size', SearchIndexField::INDEX_TYPE_INTEGER );
+               $fields['file_width'] =
+                       $engine->makeSearchFieldMapping( 'file_width', SearchIndexField::INDEX_TYPE_INTEGER );
+               $fields['file_height'] =
+                       $engine->makeSearchFieldMapping( 'file_height', SearchIndexField::INDEX_TYPE_INTEGER );
+               $fields['file_bits'] =
+                       $engine->makeSearchFieldMapping( 'file_bits', SearchIndexField::INDEX_TYPE_INTEGER );
+               $fields['file_resolution'] =
+                       $engine->makeSearchFieldMapping( 'file_resolution', SearchIndexField::INDEX_TYPE_INTEGER );
+               $fields['file_text'] =
+                       $engine->makeSearchFieldMapping( 'file_text', SearchIndexField::INDEX_TYPE_TEXT );
+               return $fields;
+       }
+
+       public function getDataForSearchIndex( WikiPage $page, ParserOutput $parserOutput,
+                                              SearchEngine $engine ) {
+               $fields = [];
+
+               $title = $page->getTitle();
+               if ( NS_FILE != $title->getNamespace() ) {
+                       return [];
+               }
+               $file = wfLocalFile( $title );
+               if ( !$file || !$file->exists() ) {
+                       return [];
+               }
+
+               $handler = $file->getHandler();
+               if ( $handler ) {
+                       $fields['file_text'] = $handler->getEntireText( $file );
+               }
+               $fields['file_media_type'] = $file->getMediaType();
+               $fields['file_mime'] = $file->getMimeType();
+               $fields['file_size'] = $file->getSize();
+               $fields['file_width'] = $file->getWidth();
+               $fields['file_height'] = $file->getHeight();
+               $fields['file_bits'] = $file->getBitDepth();
+               $fields['file_resolution'] =
+                       (int)floor( sqrt( $fields['file_width'] * $fields['file_height'] ) );
+
+               return $fields;
+       }
+
+}
index 55c4ad5..fe12ff7 100644 (file)
@@ -1,7 +1,6 @@
 <?php
 
 use HtmlFormatter\HtmlFormatter;
-use MediaWiki\Logger\LoggerFactory;
 
 /**
  * Class allowing to explore structure of parsed wikitext.
index 978ac44..74b2f1a 100644 (file)
@@ -108,6 +108,14 @@ class WikitextContentHandler extends TextContentHandler {
                return true;
        }
 
+       /**
+        * Get file handler
+        * @return FileContentHandler
+        */
+       protected function getFileHandler() {
+               return new FileContentHandler();
+       }
+
        public function getFieldsForSearchIndex( SearchEngine $engine ) {
                $fields = parent::getFieldsForSearchIndex( $engine );
 
@@ -122,34 +130,12 @@ class WikitextContentHandler extends TextContentHandler {
                        $engine->makeSearchFieldMapping( 'opening_text', SearchIndexField::INDEX_TYPE_TEXT );
                $fields['opening_text']->setFlag( SearchIndexField::FLAG_SCORING |
                                                  SearchIndexField::FLAG_NO_HIGHLIGHT );
-
-               // FIXME: this really belongs in separate file handler but files
-               // do not have separate handler. Sadness.
-               $fields['file_text'] =
-                       $engine->makeSearchFieldMapping( 'file_text', SearchIndexField::INDEX_TYPE_TEXT );
+               // Until we have full first-class content handler for files, we invoke it explicitly here
+               $fields = array_merge( $fields, $this->getFileHandler()->getFieldsForSearchIndex( $engine ) );
 
                return $fields;
        }
 
-       /**
-        * Extract text of the file
-        * TODO: probably should go to file handler?
-        * @param Title $title
-        * @return string|null
-        */
-       protected function getFileText( Title $title ) {
-               $file = wfLocalFile( $title );
-               if ( $file && $file->exists() ) {
-                       $handler = $file->getHandler();
-                       if ( !$handler ) {
-                               return null;
-                       }
-                       return $handler->getEntireText( $file );
-               }
-
-               return null;
-       }
-
        public function getDataForSearchIndex( WikiPage $page, ParserOutput $parserOutput,
                                               SearchEngine $engine ) {
                $fields = parent::getDataForSearchIndex( $page, $parserOutput, $engine );
@@ -162,12 +148,10 @@ class WikitextContentHandler extends TextContentHandler {
                $fields['auxiliary_text'] = $structure->getAuxiliaryText();
                $fields['defaultsort'] = $structure->getDefaultSort();
 
-               $title = $page->getTitle();
-               if ( NS_FILE == $title->getNamespace() ) {
-                       $fileText = $this->getFileText( $title );
-                       if ( $fileText ) {
-                               $fields['file_text'] = $fileText;
-                       }
+               // Until we have full first-class content handler for files, we invoke it explicitly here
+               if ( NS_FILE == $page->getTitle()->getNamespace() ) {
+                       $fields = array_merge( $fields,
+                                       $this->getFileHandler()->getDataForSearchIndex( $page, $parserOutput, $engine ) );
                }
                return $fields;
        }
index b617871..829dd73 100644 (file)
@@ -19,7 +19,6 @@
  * @file
  */
 use Liuggio\StatsdClient\Factory\StatsdDataFactory;
-use MediaWiki\MediaWikiServices;
 
 /**
  * The simplest way of implementing IContextSource is to hold a RequestContext as a
index 01814c1..ed617fe 100644 (file)
@@ -68,9 +68,9 @@ abstract class DBAccessBase implements IDBAccessObject {
         *
         * @since 1.21
         *
-        * @param DatabaseBase $db The database connection to release.
+        * @param Database $db The database connection to release.
         */
-       protected function releaseConnection( DatabaseBase $db ) {
+       protected function releaseConnection( Database $db ) {
                if ( $this->wiki !== false ) {
                        $loadBalancer = $this->getLoadBalancer();
                        $loadBalancer->reuseConnection( $db );
index eb061d8..6d07216 100644 (file)
@@ -737,15 +737,15 @@ class DatabaseMssql extends DatabaseBase {
         * UPDATE wrapper. Takes a condition array and a SET array.
         *
         * @param string $table Name of the table to UPDATE. This will be passed through
-        *                DatabaseBase::tableName().
+        *                Database::tableName().
         *
         * @param array $values An array of values to SET. For each array element,
         *                the key gives the field name, and the value gives the data
         *                to set that field to. The data will be quoted by
-        *                DatabaseBase::addQuotes().
+        *                Database::addQuotes().
         *
         * @param array $conds An array of conditions (WHERE). See
-        *                DatabaseBase::select() for the details of the format of
+        *                Database::select() for the details of the format of
         *                condition arrays. Use '*' to update all rows.
         *
         * @param string $fname The function name of the caller (from __METHOD__),
@@ -771,7 +771,7 @@ class DatabaseMssql extends DatabaseBase {
 
                $this->mScrollableCursor = false;
                try {
-                       $ret = $this->query( $sql );
+                       $this->query( $sql );
                } catch ( Exception $e ) {
                        $this->mScrollableCursor = true;
                        throw $e;
@@ -786,7 +786,7 @@ class DatabaseMssql extends DatabaseBase {
         * @param int $mode Constant
         *      - LIST_COMMA:          comma separated, no field names
         *      - LIST_AND:            ANDed WHERE clause (without the WHERE). See
-        *        the documentation for $conds in DatabaseBase::select().
+        *        the documentation for $conds in Database::select().
         *      - LIST_OR:             ORed WHERE clause (without the WHERE)
         *      - LIST_SET:            comma separated with field names, like a SET clause
         *      - LIST_NAMES:          comma separated field names
index e242da3..aba131d 100644 (file)
@@ -172,7 +172,7 @@ class MWExceptionRenderer {
                        } else {
                                // Show any custom GUI message before the details
                                if ( $e instanceof MessageSpecifier ) {
-                                       $wgOut->addHtml( Message::newFromSpecifier( $e )->escaped() );
+                                       $wgOut->addHTML( Message::newFromSpecifier( $e )->escaped() );
                                }
                                $wgOut->addHTML( self::getHTML( $e ) );
                        }
index 524d500..ede73aa 100644 (file)
@@ -168,6 +168,7 @@ class FileBackendGroup {
                                ? FileJournal::factory( $config['fileJournal'], $name )
                                : FileJournal::factory( [ 'class' => 'NullFileJournal' ], $name );
                        $config['wanCache'] = ObjectCache::getMainWANInstance();
+                       $config['srvCache'] = ObjectCache::getLocalServerInstance( 'hash' );
                        $config['statusWrapper'] = [ 'Status', 'wrap' ];
                        $config['tmpDirectory'] = wfTempDir();
                        $config['logger'] = LoggerFactory::getInstance( 'FileOperation' );
diff --git a/includes/filebackend/SwiftFileBackend.php b/includes/filebackend/SwiftFileBackend.php
deleted file mode 100644 (file)
index 0a0e9f5..0000000
+++ /dev/null
@@ -1,1940 +0,0 @@
-<?php
-/**
- * OpenStack Swift based file backend.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @ingroup FileBackend
- * @author Russ Nelson
- * @author Aaron Schulz
- */
-
-/**
- * @brief Class for an OpenStack Swift (or Ceph RGW) based file backend.
- *
- * StatusValue messages should avoid mentioning the Swift account name.
- * Likewise, error suppression should be used to avoid path disclosure.
- *
- * @ingroup FileBackend
- * @since 1.19
- */
-class SwiftFileBackend extends FileBackendStore {
-       /** @var MultiHttpClient */
-       protected $http;
-
-       /** @var int TTL in seconds */
-       protected $authTTL;
-
-       /** @var string Authentication base URL (without version) */
-       protected $swiftAuthUrl;
-
-       /** @var string Swift user (account:user) to authenticate as */
-       protected $swiftUser;
-
-       /** @var string Secret key for user */
-       protected $swiftKey;
-
-       /** @var string Shared secret value for making temp URLs */
-       protected $swiftTempUrlKey;
-
-       /** @var string S3 access key (RADOS Gateway) */
-       protected $rgwS3AccessKey;
-
-       /** @var string S3 authentication key (RADOS Gateway) */
-       protected $rgwS3SecretKey;
-
-       /** @var BagOStuff */
-       protected $srvCache;
-
-       /** @var ProcessCacheLRU Container stat cache */
-       protected $containerStatCache;
-
-       /** @var array */
-       protected $authCreds;
-
-       /** @var int UNIX timestamp */
-       protected $authSessionTimestamp = 0;
-
-       /** @var int UNIX timestamp */
-       protected $authErrorTimestamp = null;
-
-       /** @var bool Whether the server is an Ceph RGW */
-       protected $isRGW = false;
-
-       /**
-        * @see FileBackendStore::__construct()
-        * Additional $config params include:
-        *   - swiftAuthUrl       : Swift authentication server URL
-        *   - swiftUser          : Swift user used by MediaWiki (account:username)
-        *   - swiftKey           : Swift authentication key for the above user
-        *   - swiftAuthTTL       : Swift authentication TTL (seconds)
-        *   - swiftTempUrlKey    : Swift "X-Account-Meta-Temp-URL-Key" value on the account.
-        *                          Do not set this until it has been set in the backend.
-        *   - shardViaHashLevels : Map of container names to sharding config with:
-        *                             - base   : base of hash characters, 16 or 36
-        *                             - levels : the number of hash levels (and digits)
-        *                             - repeat : hash subdirectories are prefixed with all the
-        *                                        parent hash directory names (e.g. "a/ab/abc")
-        *   - cacheAuthInfo      : Whether to cache authentication tokens in APC, XCache, ect.
-        *                          If those are not available, then the main cache will be used.
-        *                          This is probably insecure in shared hosting environments.
-        *   - rgwS3AccessKey     : Rados Gateway S3 "access key" value on the account.
-        *                          Do not set this until it has been set in the backend.
-        *                          This is used for generating expiring pre-authenticated URLs.
-        *                          Only use this when using rgw and to work around
-        *                          http://tracker.newdream.net/issues/3454.
-        *   - rgwS3SecretKey     : Rados Gateway S3 "secret key" value on the account.
-        *                          Do not set this until it has been set in the backend.
-        *                          This is used for generating expiring pre-authenticated URLs.
-        *                          Only use this when using rgw and to work around
-        *                          http://tracker.newdream.net/issues/3454.
-        */
-       public function __construct( array $config ) {
-               parent::__construct( $config );
-               // Required settings
-               $this->swiftAuthUrl = $config['swiftAuthUrl'];
-               $this->swiftUser = $config['swiftUser'];
-               $this->swiftKey = $config['swiftKey'];
-               // Optional settings
-               $this->authTTL = isset( $config['swiftAuthTTL'] )
-                       ? $config['swiftAuthTTL']
-                       : 15 * 60; // some sane number
-               $this->swiftTempUrlKey = isset( $config['swiftTempUrlKey'] )
-                       ? $config['swiftTempUrlKey']
-                       : '';
-               $this->shardViaHashLevels = isset( $config['shardViaHashLevels'] )
-                       ? $config['shardViaHashLevels']
-                       : '';
-               $this->rgwS3AccessKey = isset( $config['rgwS3AccessKey'] )
-                       ? $config['rgwS3AccessKey']
-                       : '';
-               $this->rgwS3SecretKey = isset( $config['rgwS3SecretKey'] )
-                       ? $config['rgwS3SecretKey']
-                       : '';
-               // HTTP helper client
-               $this->http = new MultiHttpClient( [] );
-               // Cache container information to mask latency
-               if ( isset( $config['wanCache'] ) && $config['wanCache'] instanceof WANObjectCache ) {
-                       $this->memCache = $config['wanCache'];
-               }
-               // Process cache for container info
-               $this->containerStatCache = new ProcessCacheLRU( 300 );
-               // Cache auth token information to avoid RTTs
-               if ( !empty( $config['cacheAuthInfo'] ) ) {
-                       if ( PHP_SAPI === 'cli' ) {
-                               // Preferrably memcached
-                               $this->srvCache = ObjectCache::getLocalClusterInstance();
-                       } else {
-                               // Look for APC, XCache, WinCache, ect...
-                               $this->srvCache = ObjectCache::getLocalServerInstance( CACHE_NONE );
-                       }
-               } else {
-                       $this->srvCache = new EmptyBagOStuff();
-               }
-       }
-
-       public function getFeatures() {
-               return ( FileBackend::ATTR_UNICODE_PATHS |
-                       FileBackend::ATTR_HEADERS | FileBackend::ATTR_METADATA );
-       }
-
-       protected function resolveContainerPath( $container, $relStoragePath ) {
-               if ( !mb_check_encoding( $relStoragePath, 'UTF-8' ) ) {
-                       return null; // not UTF-8, makes it hard to use CF and the swift HTTP API
-               } elseif ( strlen( urlencode( $relStoragePath ) ) > 1024 ) {
-                       return null; // too long for Swift
-               }
-
-               return $relStoragePath;
-       }
-
-       public function isPathUsableInternal( $storagePath ) {
-               list( $container, $rel ) = $this->resolveStoragePathReal( $storagePath );
-               if ( $rel === null ) {
-                       return false; // invalid
-               }
-
-               return is_array( $this->getContainerStat( $container ) );
-       }
-
-       /**
-        * Sanitize and filter the custom headers from a $params array.
-        * Only allows certain "standard" Content- and X-Content- headers.
-        *
-        * @param array $params
-        * @return array Sanitized value of 'headers' field in $params
-        */
-       protected function sanitizeHdrs( array $params ) {
-               return isset( $params['headers'] )
-                       ? $this->getCustomHeaders( $params['headers'] )
-                       : [];
-
-       }
-
-       /**
-        * @param array $rawHeaders
-        * @return array Custom non-metadata HTTP headers
-        */
-       protected function getCustomHeaders( array $rawHeaders ) {
-               $headers = [];
-
-               // Normalize casing, and strip out illegal headers
-               foreach ( $rawHeaders as $name => $value ) {
-                       $name = strtolower( $name );
-                       if ( preg_match( '/^content-(type|length)$/', $name ) ) {
-                               continue; // blacklisted
-                       } elseif ( preg_match( '/^(x-)?content-/', $name ) ) {
-                               $headers[$name] = $value; // allowed
-                       } elseif ( preg_match( '/^content-(disposition)/', $name ) ) {
-                               $headers[$name] = $value; // allowed
-                       }
-               }
-               // By default, Swift has annoyingly low maximum header value limits
-               if ( isset( $headers['content-disposition'] ) ) {
-                       $disposition = '';
-                       // @note: assume FileBackend::makeContentDisposition() already used
-                       foreach ( explode( ';', $headers['content-disposition'] ) as $part ) {
-                               $part = trim( $part );
-                               $new = ( $disposition === '' ) ? $part : "{$disposition};{$part}";
-                               if ( strlen( $new ) <= 255 ) {
-                                       $disposition = $new;
-                               } else {
-                                       break; // too long; sigh
-                               }
-                       }
-                       $headers['content-disposition'] = $disposition;
-               }
-
-               return $headers;
-       }
-
-       /**
-        * @param array $rawHeaders
-        * @return array Custom metadata headers
-        */
-       protected function getMetadataHeaders( array $rawHeaders ) {
-               $headers = [];
-               foreach ( $rawHeaders as $name => $value ) {
-                       $name = strtolower( $name );
-                       if ( strpos( $name, 'x-object-meta-' ) === 0 ) {
-                               $headers[$name] = $value;
-                       }
-               }
-
-               return $headers;
-       }
-
-       /**
-        * @param array $rawHeaders
-        * @return array Custom metadata headers with prefix removed
-        */
-       protected function getMetadata( array $rawHeaders ) {
-               $metadata = [];
-               foreach ( $this->getMetadataHeaders( $rawHeaders ) as $name => $value ) {
-                       $metadata[substr( $name, strlen( 'x-object-meta-' ) )] = $value;
-               }
-
-               return $metadata;
-       }
-
-       protected function doCreateInternal( array $params ) {
-               $status = $this->newStatus();
-
-               list( $dstCont, $dstRel ) = $this->resolveStoragePathReal( $params['dst'] );
-               if ( $dstRel === null ) {
-                       $status->fatal( 'backend-fail-invalidpath', $params['dst'] );
-
-                       return $status;
-               }
-
-               $sha1Hash = Wikimedia\base_convert( sha1( $params['content'] ), 16, 36, 31 );
-               $contentType = isset( $params['headers']['content-type'] )
-                       ? $params['headers']['content-type']
-                       : $this->getContentType( $params['dst'], $params['content'], null );
-
-               $reqs = [ [
-                       'method' => 'PUT',
-                       'url' => [ $dstCont, $dstRel ],
-                       'headers' => [
-                               'content-length' => strlen( $params['content'] ),
-                               'etag' => md5( $params['content'] ),
-                               'content-type' => $contentType,
-                               'x-object-meta-sha1base36' => $sha1Hash
-                       ] + $this->sanitizeHdrs( $params ),
-                       'body' => $params['content']
-               ] ];
-
-               $method = __METHOD__;
-               $handler = function ( array $request, StatusValue $status ) use ( $method, $params ) {
-                       list( $rcode, $rdesc, $rhdrs, $rbody, $rerr ) = $request['response'];
-                       if ( $rcode === 201 ) {
-                               // good
-                       } elseif ( $rcode === 412 ) {
-                               $status->fatal( 'backend-fail-contenttype', $params['dst'] );
-                       } else {
-                               $this->onError( $status, $method, $params, $rerr, $rcode, $rdesc );
-                       }
-               };
-
-               $opHandle = new SwiftFileOpHandle( $this, $handler, $reqs );
-               if ( !empty( $params['async'] ) ) { // deferred
-                       $status->value = $opHandle;
-               } else { // actually write the object in Swift
-                       $status->merge( current( $this->doExecuteOpHandlesInternal( [ $opHandle ] ) ) );
-               }
-
-               return $status;
-       }
-
-       protected function doStoreInternal( array $params ) {
-               $status = $this->newStatus();
-
-               list( $dstCont, $dstRel ) = $this->resolveStoragePathReal( $params['dst'] );
-               if ( $dstRel === null ) {
-                       $status->fatal( 'backend-fail-invalidpath', $params['dst'] );
-
-                       return $status;
-               }
-
-               MediaWiki\suppressWarnings();
-               $sha1Hash = sha1_file( $params['src'] );
-               MediaWiki\restoreWarnings();
-               if ( $sha1Hash === false ) { // source doesn't exist?
-                       $status->fatal( 'backend-fail-store', $params['src'], $params['dst'] );
-
-                       return $status;
-               }
-               $sha1Hash = Wikimedia\base_convert( $sha1Hash, 16, 36, 31 );
-               $contentType = isset( $params['headers']['content-type'] )
-                       ? $params['headers']['content-type']
-                       : $this->getContentType( $params['dst'], null, $params['src'] );
-
-               $handle = fopen( $params['src'], 'rb' );
-               if ( $handle === false ) { // source doesn't exist?
-                       $status->fatal( 'backend-fail-store', $params['src'], $params['dst'] );
-
-                       return $status;
-               }
-
-               $reqs = [ [
-                       'method' => 'PUT',
-                       'url' => [ $dstCont, $dstRel ],
-                       'headers' => [
-                               'content-length' => filesize( $params['src'] ),
-                               'etag' => md5_file( $params['src'] ),
-                               'content-type' => $contentType,
-                               'x-object-meta-sha1base36' => $sha1Hash
-                       ] + $this->sanitizeHdrs( $params ),
-                       'body' => $handle // resource
-               ] ];
-
-               $method = __METHOD__;
-               $handler = function ( array $request, StatusValue $status ) use ( $method, $params ) {
-                       list( $rcode, $rdesc, $rhdrs, $rbody, $rerr ) = $request['response'];
-                       if ( $rcode === 201 ) {
-                               // good
-                       } elseif ( $rcode === 412 ) {
-                               $status->fatal( 'backend-fail-contenttype', $params['dst'] );
-                       } else {
-                               $this->onError( $status, $method, $params, $rerr, $rcode, $rdesc );
-                       }
-               };
-
-               $opHandle = new SwiftFileOpHandle( $this, $handler, $reqs );
-               if ( !empty( $params['async'] ) ) { // deferred
-                       $status->value = $opHandle;
-               } else { // actually write the object in Swift
-                       $status->merge( current( $this->doExecuteOpHandlesInternal( [ $opHandle ] ) ) );
-               }
-
-               return $status;
-       }
-
-       protected function doCopyInternal( array $params ) {
-               $status = $this->newStatus();
-
-               list( $srcCont, $srcRel ) = $this->resolveStoragePathReal( $params['src'] );
-               if ( $srcRel === null ) {
-                       $status->fatal( 'backend-fail-invalidpath', $params['src'] );
-
-                       return $status;
-               }
-
-               list( $dstCont, $dstRel ) = $this->resolveStoragePathReal( $params['dst'] );
-               if ( $dstRel === null ) {
-                       $status->fatal( 'backend-fail-invalidpath', $params['dst'] );
-
-                       return $status;
-               }
-
-               $reqs = [ [
-                       'method' => 'PUT',
-                       'url' => [ $dstCont, $dstRel ],
-                       'headers' => [
-                               'x-copy-from' => '/' . rawurlencode( $srcCont ) .
-                                       '/' . str_replace( "%2F", "/", rawurlencode( $srcRel ) )
-                       ] + $this->sanitizeHdrs( $params ), // extra headers merged into object
-               ] ];
-
-               $method = __METHOD__;
-               $handler = function ( array $request, StatusValue $status ) use ( $method, $params ) {
-                       list( $rcode, $rdesc, $rhdrs, $rbody, $rerr ) = $request['response'];
-                       if ( $rcode === 201 ) {
-                               // good
-                       } elseif ( $rcode === 404 ) {
-                               $status->fatal( 'backend-fail-copy', $params['src'], $params['dst'] );
-                       } else {
-                               $this->onError( $status, $method, $params, $rerr, $rcode, $rdesc );
-                       }
-               };
-
-               $opHandle = new SwiftFileOpHandle( $this, $handler, $reqs );
-               if ( !empty( $params['async'] ) ) { // deferred
-                       $status->value = $opHandle;
-               } else { // actually write the object in Swift
-                       $status->merge( current( $this->doExecuteOpHandlesInternal( [ $opHandle ] ) ) );
-               }
-
-               return $status;
-       }
-
-       protected function doMoveInternal( array $params ) {
-               $status = $this->newStatus();
-
-               list( $srcCont, $srcRel ) = $this->resolveStoragePathReal( $params['src'] );
-               if ( $srcRel === null ) {
-                       $status->fatal( 'backend-fail-invalidpath', $params['src'] );
-
-                       return $status;
-               }
-
-               list( $dstCont, $dstRel ) = $this->resolveStoragePathReal( $params['dst'] );
-               if ( $dstRel === null ) {
-                       $status->fatal( 'backend-fail-invalidpath', $params['dst'] );
-
-                       return $status;
-               }
-
-               $reqs = [
-                       [
-                               'method' => 'PUT',
-                               'url' => [ $dstCont, $dstRel ],
-                               'headers' => [
-                                       'x-copy-from' => '/' . rawurlencode( $srcCont ) .
-                                               '/' . str_replace( "%2F", "/", rawurlencode( $srcRel ) )
-                               ] + $this->sanitizeHdrs( $params ) // extra headers merged into object
-                       ]
-               ];
-               if ( "{$srcCont}/{$srcRel}" !== "{$dstCont}/{$dstRel}" ) {
-                       $reqs[] = [
-                               'method' => 'DELETE',
-                               'url' => [ $srcCont, $srcRel ],
-                               'headers' => []
-                       ];
-               }
-
-               $method = __METHOD__;
-               $handler = function ( array $request, StatusValue $status ) use ( $method, $params ) {
-                       list( $rcode, $rdesc, $rhdrs, $rbody, $rerr ) = $request['response'];
-                       if ( $request['method'] === 'PUT' && $rcode === 201 ) {
-                               // good
-                       } elseif ( $request['method'] === 'DELETE' && $rcode === 204 ) {
-                               // good
-                       } elseif ( $rcode === 404 ) {
-                               $status->fatal( 'backend-fail-move', $params['src'], $params['dst'] );
-                       } else {
-                               $this->onError( $status, $method, $params, $rerr, $rcode, $rdesc );
-                       }
-               };
-
-               $opHandle = new SwiftFileOpHandle( $this, $handler, $reqs );
-               if ( !empty( $params['async'] ) ) { // deferred
-                       $status->value = $opHandle;
-               } else { // actually move the object in Swift
-                       $status->merge( current( $this->doExecuteOpHandlesInternal( [ $opHandle ] ) ) );
-               }
-
-               return $status;
-       }
-
-       protected function doDeleteInternal( array $params ) {
-               $status = $this->newStatus();
-
-               list( $srcCont, $srcRel ) = $this->resolveStoragePathReal( $params['src'] );
-               if ( $srcRel === null ) {
-                       $status->fatal( 'backend-fail-invalidpath', $params['src'] );
-
-                       return $status;
-               }
-
-               $reqs = [ [
-                       'method' => 'DELETE',
-                       'url' => [ $srcCont, $srcRel ],
-                       'headers' => []
-               ] ];
-
-               $method = __METHOD__;
-               $handler = function ( array $request, StatusValue $status ) use ( $method, $params ) {
-                       list( $rcode, $rdesc, $rhdrs, $rbody, $rerr ) = $request['response'];
-                       if ( $rcode === 204 ) {
-                               // good
-                       } elseif ( $rcode === 404 ) {
-                               if ( empty( $params['ignoreMissingSource'] ) ) {
-                                       $status->fatal( 'backend-fail-delete', $params['src'] );
-                               }
-                       } else {
-                               $this->onError( $status, $method, $params, $rerr, $rcode, $rdesc );
-                       }
-               };
-
-               $opHandle = new SwiftFileOpHandle( $this, $handler, $reqs );
-               if ( !empty( $params['async'] ) ) { // deferred
-                       $status->value = $opHandle;
-               } else { // actually delete the object in Swift
-                       $status->merge( current( $this->doExecuteOpHandlesInternal( [ $opHandle ] ) ) );
-               }
-
-               return $status;
-       }
-
-       protected function doDescribeInternal( array $params ) {
-               $status = $this->newStatus();
-
-               list( $srcCont, $srcRel ) = $this->resolveStoragePathReal( $params['src'] );
-               if ( $srcRel === null ) {
-                       $status->fatal( 'backend-fail-invalidpath', $params['src'] );
-
-                       return $status;
-               }
-
-               // Fetch the old object headers/metadata...this should be in stat cache by now
-               $stat = $this->getFileStat( [ 'src' => $params['src'], 'latest' => 1 ] );
-               if ( $stat && !isset( $stat['xattr'] ) ) { // older cache entry
-                       $stat = $this->doGetFileStat( [ 'src' => $params['src'], 'latest' => 1 ] );
-               }
-               if ( !$stat ) {
-                       $status->fatal( 'backend-fail-describe', $params['src'] );
-
-                       return $status;
-               }
-
-               // POST clears prior headers, so we need to merge the changes in to the old ones
-               $metaHdrs = [];
-               foreach ( $stat['xattr']['metadata'] as $name => $value ) {
-                       $metaHdrs["x-object-meta-$name"] = $value;
-               }
-               $customHdrs = $this->sanitizeHdrs( $params ) + $stat['xattr']['headers'];
-
-               $reqs = [ [
-                       'method' => 'POST',
-                       'url' => [ $srcCont, $srcRel ],
-                       'headers' => $metaHdrs + $customHdrs
-               ] ];
-
-               $method = __METHOD__;
-               $handler = function ( array $request, StatusValue $status ) use ( $method, $params ) {
-                       list( $rcode, $rdesc, $rhdrs, $rbody, $rerr ) = $request['response'];
-                       if ( $rcode === 202 ) {
-                               // good
-                       } elseif ( $rcode === 404 ) {
-                               $status->fatal( 'backend-fail-describe', $params['src'] );
-                       } else {
-                               $this->onError( $status, $method, $params, $rerr, $rcode, $rdesc );
-                       }
-               };
-
-               $opHandle = new SwiftFileOpHandle( $this, $handler, $reqs );
-               if ( !empty( $params['async'] ) ) { // deferred
-                       $status->value = $opHandle;
-               } else { // actually change the object in Swift
-                       $status->merge( current( $this->doExecuteOpHandlesInternal( [ $opHandle ] ) ) );
-               }
-
-               return $status;
-       }
-
-       protected function doPrepareInternal( $fullCont, $dir, array $params ) {
-               $status = $this->newStatus();
-
-               // (a) Check if container already exists
-               $stat = $this->getContainerStat( $fullCont );
-               if ( is_array( $stat ) ) {
-                       return $status; // already there
-               } elseif ( $stat === null ) {
-                       $status->fatal( 'backend-fail-internal', $this->name );
-                       wfDebugLog( 'SwiftBackend', __METHOD__ . ': cannot get container stat' );
-
-                       return $status;
-               }
-
-               // (b) Create container as needed with proper ACLs
-               if ( $stat === false ) {
-                       $params['op'] = 'prepare';
-                       $status->merge( $this->createContainer( $fullCont, $params ) );
-               }
-
-               return $status;
-       }
-
-       protected function doSecureInternal( $fullCont, $dir, array $params ) {
-               $status = $this->newStatus();
-               if ( empty( $params['noAccess'] ) ) {
-                       return $status; // nothing to do
-               }
-
-               $stat = $this->getContainerStat( $fullCont );
-               if ( is_array( $stat ) ) {
-                       // Make container private to end-users...
-                       $status->merge( $this->setContainerAccess(
-                               $fullCont,
-                               [ $this->swiftUser ], // read
-                               [ $this->swiftUser ] // write
-                       ) );
-               } elseif ( $stat === false ) {
-                       $status->fatal( 'backend-fail-usable', $params['dir'] );
-               } else {
-                       $status->fatal( 'backend-fail-internal', $this->name );
-                       wfDebugLog( 'SwiftBackend', __METHOD__ . ': cannot get container stat' );
-               }
-
-               return $status;
-       }
-
-       protected function doPublishInternal( $fullCont, $dir, array $params ) {
-               $status = $this->newStatus();
-
-               $stat = $this->getContainerStat( $fullCont );
-               if ( is_array( $stat ) ) {
-                       // Make container public to end-users...
-                       $status->merge( $this->setContainerAccess(
-                               $fullCont,
-                               [ $this->swiftUser, '.r:*' ], // read
-                               [ $this->swiftUser ] // write
-                       ) );
-               } elseif ( $stat === false ) {
-                       $status->fatal( 'backend-fail-usable', $params['dir'] );
-               } else {
-                       $status->fatal( 'backend-fail-internal', $this->name );
-                       wfDebugLog( 'SwiftBackend', __METHOD__ . ': cannot get container stat' );
-               }
-
-               return $status;
-       }
-
-       protected function doCleanInternal( $fullCont, $dir, array $params ) {
-               $status = $this->newStatus();
-
-               // Only containers themselves can be removed, all else is virtual
-               if ( $dir != '' ) {
-                       return $status; // nothing to do
-               }
-
-               // (a) Check the container
-               $stat = $this->getContainerStat( $fullCont, true );
-               if ( $stat === false ) {
-                       return $status; // ok, nothing to do
-               } elseif ( !is_array( $stat ) ) {
-                       $status->fatal( 'backend-fail-internal', $this->name );
-                       wfDebugLog( 'SwiftBackend', __METHOD__ . ': cannot get container stat' );
-
-                       return $status;
-               }
-
-               // (b) Delete the container if empty
-               if ( $stat['count'] == 0 ) {
-                       $params['op'] = 'clean';
-                       $status->merge( $this->deleteContainer( $fullCont, $params ) );
-               }
-
-               return $status;
-       }
-
-       protected function doGetFileStat( array $params ) {
-               $params = [ 'srcs' => [ $params['src'] ], 'concurrency' => 1 ] + $params;
-               unset( $params['src'] );
-               $stats = $this->doGetFileStatMulti( $params );
-
-               return reset( $stats );
-       }
-
-       /**
-        * Convert dates like "Tue, 03 Jan 2012 22:01:04 GMT"/"2013-05-11T07:37:27.678360Z".
-        * Dates might also come in like "2013-05-11T07:37:27.678360" from Swift listings,
-        * missing the timezone suffix (though Ceph RGW does not appear to have this bug).
-        *
-        * @param string $ts
-        * @param int $format Output format (TS_* constant)
-        * @return string
-        * @throws FileBackendError
-        */
-       protected function convertSwiftDate( $ts, $format = TS_MW ) {
-               try {
-                       $timestamp = new MWTimestamp( $ts );
-
-                       return $timestamp->getTimestamp( $format );
-               } catch ( Exception $e ) {
-                       throw new FileBackendError( $e->getMessage() );
-               }
-       }
-
-       /**
-        * Fill in any missing object metadata and save it to Swift
-        *
-        * @param array $objHdrs Object response headers
-        * @param string $path Storage path to object
-        * @return array New headers
-        */
-       protected function addMissingMetadata( array $objHdrs, $path ) {
-               if ( isset( $objHdrs['x-object-meta-sha1base36'] ) ) {
-                       return $objHdrs; // nothing to do
-               }
-
-               /** @noinspection PhpUnusedLocalVariableInspection */
-               $ps = Profiler::instance()->scopedProfileIn( __METHOD__ . "-{$this->name}" );
-               wfDebugLog( 'SwiftBackend', __METHOD__ . ": $path was not stored with SHA-1 metadata." );
-
-               $objHdrs['x-object-meta-sha1base36'] = false;
-
-               $auth = $this->getAuthentication();
-               if ( !$auth ) {
-                       return $objHdrs; // failed
-               }
-
-               // Find prior custom HTTP headers
-               $postHeaders = $this->getCustomHeaders( $objHdrs );
-               // Find prior metadata headers
-               $postHeaders += $this->getMetadataHeaders( $objHdrs );
-
-               $status = $this->newStatus();
-               /** @noinspection PhpUnusedLocalVariableInspection */
-               $scopeLockS = $this->getScopedFileLocks( [ $path ], LockManager::LOCK_UW, $status );
-               if ( $status->isOK() ) {
-                       $tmpFile = $this->getLocalCopy( [ 'src' => $path, 'latest' => 1 ] );
-                       if ( $tmpFile ) {
-                               $hash = $tmpFile->getSha1Base36();
-                               if ( $hash !== false ) {
-                                       $objHdrs['x-object-meta-sha1base36'] = $hash;
-                                       // Merge new SHA1 header into the old ones
-                                       $postHeaders['x-object-meta-sha1base36'] = $hash;
-                                       list( $srcCont, $srcRel ) = $this->resolveStoragePathReal( $path );
-                                       list( $rcode ) = $this->http->run( [
-                                               'method' => 'POST',
-                                               'url' => $this->storageUrl( $auth, $srcCont, $srcRel ),
-                                               'headers' => $this->authTokenHeaders( $auth ) + $postHeaders
-                                       ] );
-                                       if ( $rcode >= 200 && $rcode <= 299 ) {
-                                               $this->deleteFileCache( $path );
-
-                                               return $objHdrs; // success
-                                       }
-                               }
-                       }
-               }
-
-               wfDebugLog( 'SwiftBackend', __METHOD__ . ": unable to set SHA-1 metadata for $path" );
-
-               return $objHdrs; // failed
-       }
-
-       protected function doGetFileContentsMulti( array $params ) {
-               $contents = [];
-
-               $auth = $this->getAuthentication();
-
-               $ep = array_diff_key( $params, [ 'srcs' => 1 ] ); // for error logging
-               // Blindly create tmp files and stream to them, catching any exception if the file does
-               // not exist. Doing stats here is useless and will loop infinitely in addMissingMetadata().
-               $reqs = []; // (path => op)
-
-               foreach ( $params['srcs'] as $path ) { // each path in this concurrent batch
-                       list( $srcCont, $srcRel ) = $this->resolveStoragePathReal( $path );
-                       if ( $srcRel === null || !$auth ) {
-                               $contents[$path] = false;
-                               continue;
-                       }
-                       // Create a new temporary memory file...
-                       $handle = fopen( 'php://temp', 'wb' );
-                       if ( $handle ) {
-                               $reqs[$path] = [
-                                       'method'  => 'GET',
-                                       'url'     => $this->storageUrl( $auth, $srcCont, $srcRel ),
-                                       'headers' => $this->authTokenHeaders( $auth )
-                                               + $this->headersFromParams( $params ),
-                                       'stream'  => $handle,
-                               ];
-                       }
-                       $contents[$path] = false;
-               }
-
-               $opts = [ 'maxConnsPerHost' => $params['concurrency'] ];
-               $reqs = $this->http->runMulti( $reqs, $opts );
-               foreach ( $reqs as $path => $op ) {
-                       list( $rcode, $rdesc, $rhdrs, $rbody, $rerr ) = $op['response'];
-                       if ( $rcode >= 200 && $rcode <= 299 ) {
-                               rewind( $op['stream'] ); // start from the beginning
-                               $contents[$path] = stream_get_contents( $op['stream'] );
-                       } elseif ( $rcode === 404 ) {
-                               $contents[$path] = false;
-                       } else {
-                               $this->onError( null, __METHOD__,
-                                       [ 'src' => $path ] + $ep, $rerr, $rcode, $rdesc );
-                       }
-                       fclose( $op['stream'] ); // close open handle
-               }
-
-               return $contents;
-       }
-
-       protected function doDirectoryExists( $fullCont, $dir, array $params ) {
-               $prefix = ( $dir == '' ) ? null : "{$dir}/";
-               $status = $this->objectListing( $fullCont, 'names', 1, null, $prefix );
-               if ( $status->isOK() ) {
-                       return ( count( $status->value ) ) > 0;
-               }
-
-               return null; // error
-       }
-
-       /**
-        * @see FileBackendStore::getDirectoryListInternal()
-        * @param string $fullCont
-        * @param string $dir
-        * @param array $params
-        * @return SwiftFileBackendDirList
-        */
-       public function getDirectoryListInternal( $fullCont, $dir, array $params ) {
-               return new SwiftFileBackendDirList( $this, $fullCont, $dir, $params );
-       }
-
-       /**
-        * @see FileBackendStore::getFileListInternal()
-        * @param string $fullCont
-        * @param string $dir
-        * @param array $params
-        * @return SwiftFileBackendFileList
-        */
-       public function getFileListInternal( $fullCont, $dir, array $params ) {
-               return new SwiftFileBackendFileList( $this, $fullCont, $dir, $params );
-       }
-
-       /**
-        * Do not call this function outside of SwiftFileBackendFileList
-        *
-        * @param string $fullCont Resolved container name
-        * @param string $dir Resolved storage directory with no trailing slash
-        * @param string|null $after Resolved container relative path to list items after
-        * @param int $limit Max number of items to list
-        * @param array $params Parameters for getDirectoryList()
-        * @return array List of container relative resolved paths of directories directly under $dir
-        * @throws FileBackendError
-        */
-       public function getDirListPageInternal( $fullCont, $dir, &$after, $limit, array $params ) {
-               $dirs = [];
-               if ( $after === INF ) {
-                       return $dirs; // nothing more
-               }
-
-               $ps = Profiler::instance()->scopedProfileIn( __METHOD__ . "-{$this->name}" );
-
-               $prefix = ( $dir == '' ) ? null : "{$dir}/";
-               // Non-recursive: only list dirs right under $dir
-               if ( !empty( $params['topOnly'] ) ) {
-                       $status = $this->objectListing( $fullCont, 'names', $limit, $after, $prefix, '/' );
-                       if ( !$status->isOK() ) {
-                               throw new FileBackendError( "Iterator page I/O error: {$status->getMessage()}" );
-                       }
-                       $objects = $status->value;
-                       foreach ( $objects as $object ) { // files and directories
-                               if ( substr( $object, -1 ) === '/' ) {
-                                       $dirs[] = $object; // directories end in '/'
-                               }
-                       }
-               } else {
-                       // Recursive: list all dirs under $dir and its subdirs
-                       $getParentDir = function ( $path ) {
-                               return ( strpos( $path, '/' ) !== false ) ? dirname( $path ) : false;
-                       };
-
-                       // Get directory from last item of prior page
-                       $lastDir = $getParentDir( $after ); // must be first page
-                       $status = $this->objectListing( $fullCont, 'names', $limit, $after, $prefix );
-
-                       if ( !$status->isOK() ) {
-                               throw new FileBackendError( "Iterator page I/O error: {$status->getMessage()}" );
-                       }
-
-                       $objects = $status->value;
-
-                       foreach ( $objects as $object ) { // files
-                               $objectDir = $getParentDir( $object ); // directory of object
-
-                               if ( $objectDir !== false && $objectDir !== $dir ) {
-                                       // Swift stores paths in UTF-8, using binary sorting.
-                                       // See function "create_container_table" in common/db.py.
-                                       // If a directory is not "greater" than the last one,
-                                       // then it was already listed by the calling iterator.
-                                       if ( strcmp( $objectDir, $lastDir ) > 0 ) {
-                                               $pDir = $objectDir;
-                                               do { // add dir and all its parent dirs
-                                                       $dirs[] = "{$pDir}/";
-                                                       $pDir = $getParentDir( $pDir );
-                                               } while ( $pDir !== false // sanity
-                                                       && strcmp( $pDir, $lastDir ) > 0 // not done already
-                                                       && strlen( $pDir ) > strlen( $dir ) // within $dir
-                                               );
-                                       }
-                                       $lastDir = $objectDir;
-                               }
-                       }
-               }
-               // Page on the unfiltered directory listing (what is returned may be filtered)
-               if ( count( $objects ) < $limit ) {
-                       $after = INF; // avoid a second RTT
-               } else {
-                       $after = end( $objects ); // update last item
-               }
-
-               return $dirs;
-       }
-
-       /**
-        * Do not call this function outside of SwiftFileBackendFileList
-        *
-        * @param string $fullCont Resolved container name
-        * @param string $dir Resolved storage directory with no trailing slash
-        * @param string|null $after Resolved container relative path of file to list items after
-        * @param int $limit Max number of items to list
-        * @param array $params Parameters for getDirectoryList()
-        * @return array List of resolved container relative paths of files under $dir
-        * @throws FileBackendError
-        */
-       public function getFileListPageInternal( $fullCont, $dir, &$after, $limit, array $params ) {
-               $files = []; // list of (path, stat array or null) entries
-               if ( $after === INF ) {
-                       return $files; // nothing more
-               }
-
-               $ps = Profiler::instance()->scopedProfileIn( __METHOD__ . "-{$this->name}" );
-
-               $prefix = ( $dir == '' ) ? null : "{$dir}/";
-               // $objects will contain a list of unfiltered names or CF_Object items
-               // Non-recursive: only list files right under $dir
-               if ( !empty( $params['topOnly'] ) ) {
-                       if ( !empty( $params['adviseStat'] ) ) {
-                               $status = $this->objectListing( $fullCont, 'info', $limit, $after, $prefix, '/' );
-                       } else {
-                               $status = $this->objectListing( $fullCont, 'names', $limit, $after, $prefix, '/' );
-                       }
-               } else {
-                       // Recursive: list all files under $dir and its subdirs
-                       if ( !empty( $params['adviseStat'] ) ) {
-                               $status = $this->objectListing( $fullCont, 'info', $limit, $after, $prefix );
-                       } else {
-                               $status = $this->objectListing( $fullCont, 'names', $limit, $after, $prefix );
-                       }
-               }
-
-               // Reformat this list into a list of (name, stat array or null) entries
-               if ( !$status->isOK() ) {
-                       throw new FileBackendError( "Iterator page I/O error: {$status->getMessage()}" );
-               }
-
-               $objects = $status->value;
-               $files = $this->buildFileObjectListing( $params, $dir, $objects );
-
-               // Page on the unfiltered object listing (what is returned may be filtered)
-               if ( count( $objects ) < $limit ) {
-                       $after = INF; // avoid a second RTT
-               } else {
-                       $after = end( $objects ); // update last item
-                       $after = is_object( $after ) ? $after->name : $after;
-               }
-
-               return $files;
-       }
-
-       /**
-        * Build a list of file objects, filtering out any directories
-        * and extracting any stat info if provided in $objects (for CF_Objects)
-        *
-        * @param array $params Parameters for getDirectoryList()
-        * @param string $dir Resolved container directory path
-        * @param array $objects List of CF_Object items or object names
-        * @return array List of (names,stat array or null) entries
-        */
-       private function buildFileObjectListing( array $params, $dir, array $objects ) {
-               $names = [];
-               foreach ( $objects as $object ) {
-                       if ( is_object( $object ) ) {
-                               if ( isset( $object->subdir ) || !isset( $object->name ) ) {
-                                       continue; // virtual directory entry; ignore
-                               }
-                               $stat = [
-                                       // Convert various random Swift dates to TS_MW
-                                       'mtime'  => $this->convertSwiftDate( $object->last_modified, TS_MW ),
-                                       'size'   => (int)$object->bytes,
-                                       'sha1'   => null,
-                                       // Note: manifiest ETags are not an MD5 of the file
-                                       'md5'    => ctype_xdigit( $object->hash ) ? $object->hash : null,
-                                       'latest' => false // eventually consistent
-                               ];
-                               $names[] = [ $object->name, $stat ];
-                       } elseif ( substr( $object, -1 ) !== '/' ) {
-                               // Omit directories, which end in '/' in listings
-                               $names[] = [ $object, null ];
-                       }
-               }
-
-               return $names;
-       }
-
-       /**
-        * Do not call this function outside of SwiftFileBackendFileList
-        *
-        * @param string $path Storage path
-        * @param array $val Stat value
-        */
-       public function loadListingStatInternal( $path, array $val ) {
-               $this->cheapCache->set( $path, 'stat', $val );
-       }
-
-       protected function doGetFileXAttributes( array $params ) {
-               $stat = $this->getFileStat( $params );
-               if ( $stat ) {
-                       if ( !isset( $stat['xattr'] ) ) {
-                               // Stat entries filled by file listings don't include metadata/headers
-                               $this->clearCache( [ $params['src'] ] );
-                               $stat = $this->getFileStat( $params );
-                       }
-
-                       return $stat['xattr'];
-               } else {
-                       return false;
-               }
-       }
-
-       protected function doGetFileSha1base36( array $params ) {
-               $stat = $this->getFileStat( $params );
-               if ( $stat ) {
-                       if ( !isset( $stat['sha1'] ) ) {
-                               // Stat entries filled by file listings don't include SHA1
-                               $this->clearCache( [ $params['src'] ] );
-                               $stat = $this->getFileStat( $params );
-                       }
-
-                       return $stat['sha1'];
-               } else {
-                       return false;
-               }
-       }
-
-       protected function doStreamFile( array $params ) {
-               $status = $this->newStatus();
-
-               $flags = !empty( $params['headless'] ) ? StreamFile::STREAM_HEADLESS : 0;
-
-               list( $srcCont, $srcRel ) = $this->resolveStoragePathReal( $params['src'] );
-               if ( $srcRel === null ) {
-                       StreamFile::send404Message( $params['src'], $flags );
-                       $status->fatal( 'backend-fail-invalidpath', $params['src'] );
-
-                       return $status;
-               }
-
-               $auth = $this->getAuthentication();
-               if ( !$auth || !is_array( $this->getContainerStat( $srcCont ) ) ) {
-                       StreamFile::send404Message( $params['src'], $flags );
-                       $status->fatal( 'backend-fail-stream', $params['src'] );
-
-                       return $status;
-               }
-
-               // If "headers" is set, we only want to send them if the file is there.
-               // Do not bother checking if the file exists if headers are not set though.
-               if ( $params['headers'] && !$this->fileExists( $params ) ) {
-                       StreamFile::send404Message( $params['src'], $flags );
-                       $status->fatal( 'backend-fail-stream', $params['src'] );
-
-                       return $status;
-               }
-
-               // Send the requested additional headers
-               foreach ( $params['headers'] as $header ) {
-                       header( $header ); // aways send
-               }
-
-               if ( empty( $params['allowOB'] ) ) {
-                       // Cancel output buffering and gzipping if set
-                       wfResetOutputBuffers();
-               }
-
-               $handle = fopen( 'php://output', 'wb' );
-               list( $rcode, $rdesc, $rhdrs, $rbody, $rerr ) = $this->http->run( [
-                       'method' => 'GET',
-                       'url' => $this->storageUrl( $auth, $srcCont, $srcRel ),
-                       'headers' => $this->authTokenHeaders( $auth )
-                               + $this->headersFromParams( $params ) + $params['options'],
-                       'stream' => $handle,
-                       'flags'  => [ 'relayResponseHeaders' => empty( $params['headless'] ) ]
-               ] );
-
-               if ( $rcode >= 200 && $rcode <= 299 ) {
-                       // good
-               } elseif ( $rcode === 404 ) {
-                       $status->fatal( 'backend-fail-stream', $params['src'] );
-                       // Per bug 41113, nasty things can happen if bad cache entries get
-                       // stuck in cache. It's also possible that this error can come up
-                       // with simple race conditions. Clear out the stat cache to be safe.
-                       $this->clearCache( [ $params['src'] ] );
-                       $this->deleteFileCache( $params['src'] );
-               } else {
-                       $this->onError( $status, __METHOD__, $params, $rerr, $rcode, $rdesc );
-               }
-
-               return $status;
-       }
-
-       protected function doGetLocalCopyMulti( array $params ) {
-               $tmpFiles = [];
-
-               $auth = $this->getAuthentication();
-
-               $ep = array_diff_key( $params, [ 'srcs' => 1 ] ); // for error logging
-               // Blindly create tmp files and stream to them, catching any exception if the file does
-               // not exist. Doing a stat here is useless causes infinite loops in addMissingMetadata().
-               $reqs = []; // (path => op)
-
-               foreach ( $params['srcs'] as $path ) { // each path in this concurrent batch
-                       list( $srcCont, $srcRel ) = $this->resolveStoragePathReal( $path );
-                       if ( $srcRel === null || !$auth ) {
-                               $tmpFiles[$path] = null;
-                               continue;
-                       }
-                       // Get source file extension
-                       $ext = FileBackend::extensionFromPath( $path );
-                       // Create a new temporary file...
-                       $tmpFile = TempFSFile::factory( 'localcopy_', $ext, $this->tmpDirectory );
-                       if ( $tmpFile ) {
-                               $handle = fopen( $tmpFile->getPath(), 'wb' );
-                               if ( $handle ) {
-                                       $reqs[$path] = [
-                                               'method'  => 'GET',
-                                               'url'     => $this->storageUrl( $auth, $srcCont, $srcRel ),
-                                               'headers' => $this->authTokenHeaders( $auth )
-                                                       + $this->headersFromParams( $params ),
-                                               'stream'  => $handle,
-                                       ];
-                               } else {
-                                       $tmpFile = null;
-                               }
-                       }
-                       $tmpFiles[$path] = $tmpFile;
-               }
-
-               $isLatest = ( $this->isRGW || !empty( $params['latest'] ) );
-               $opts = [ 'maxConnsPerHost' => $params['concurrency'] ];
-               $reqs = $this->http->runMulti( $reqs, $opts );
-               foreach ( $reqs as $path => $op ) {
-                       list( $rcode, $rdesc, $rhdrs, $rbody, $rerr ) = $op['response'];
-                       fclose( $op['stream'] ); // close open handle
-                       if ( $rcode >= 200 && $rcode <= 299 ) {
-                               $size = $tmpFiles[$path] ? $tmpFiles[$path]->getSize() : 0;
-                               // Double check that the disk is not full/broken
-                               if ( $size != $rhdrs['content-length'] ) {
-                                       $tmpFiles[$path] = null;
-                                       $rerr = "Got {$size}/{$rhdrs['content-length']} bytes";
-                                       $this->onError( null, __METHOD__,
-                                               [ 'src' => $path ] + $ep, $rerr, $rcode, $rdesc );
-                               }
-                               // Set the file stat process cache in passing
-                               $stat = $this->getStatFromHeaders( $rhdrs );
-                               $stat['latest'] = $isLatest;
-                               $this->cheapCache->set( $path, 'stat', $stat );
-                       } elseif ( $rcode === 404 ) {
-                               $tmpFiles[$path] = false;
-                       } else {
-                               $tmpFiles[$path] = null;
-                               $this->onError( null, __METHOD__,
-                                       [ 'src' => $path ] + $ep, $rerr, $rcode, $rdesc );
-                       }
-               }
-
-               return $tmpFiles;
-       }
-
-       public function getFileHttpUrl( array $params ) {
-               if ( $this->swiftTempUrlKey != '' ||
-                       ( $this->rgwS3AccessKey != '' && $this->rgwS3SecretKey != '' )
-               ) {
-                       list( $srcCont, $srcRel ) = $this->resolveStoragePathReal( $params['src'] );
-                       if ( $srcRel === null ) {
-                               return null; // invalid path
-                       }
-
-                       $auth = $this->getAuthentication();
-                       if ( !$auth ) {
-                               return null;
-                       }
-
-                       $ttl = isset( $params['ttl'] ) ? $params['ttl'] : 86400;
-                       $expires = time() + $ttl;
-
-                       if ( $this->swiftTempUrlKey != '' ) {
-                               $url = $this->storageUrl( $auth, $srcCont, $srcRel );
-                               // Swift wants the signature based on the unencoded object name
-                               $contPath = parse_url( $this->storageUrl( $auth, $srcCont ), PHP_URL_PATH );
-                               $signature = hash_hmac( 'sha1',
-                                       "GET\n{$expires}\n{$contPath}/{$srcRel}",
-                                       $this->swiftTempUrlKey
-                               );
-
-                               return "{$url}?temp_url_sig={$signature}&temp_url_expires={$expires}";
-                       } else { // give S3 API URL for rgw
-                               // Path for signature starts with the bucket
-                               $spath = '/' . rawurlencode( $srcCont ) . '/' .
-                                       str_replace( '%2F', '/', rawurlencode( $srcRel ) );
-                               // Calculate the hash
-                               $signature = base64_encode( hash_hmac(
-                                       'sha1',
-                                       "GET\n\n\n{$expires}\n{$spath}",
-                                       $this->rgwS3SecretKey,
-                                       true // raw
-                               ) );
-                               // See http://s3.amazonaws.com/doc/s3-developer-guide/RESTAuthentication.html.
-                               // Note: adding a newline for empty CanonicalizedAmzHeaders does not work.
-                               return wfAppendQuery(
-                                       str_replace( '/swift/v1', '', // S3 API is the rgw default
-                                               $this->storageUrl( $auth ) . $spath ),
-                                       [
-                                               'Signature' => $signature,
-                                               'Expires' => $expires,
-                                               'AWSAccessKeyId' => $this->rgwS3AccessKey ]
-                               );
-                       }
-               }
-
-               return null;
-       }
-
-       protected function directoriesAreVirtual() {
-               return true;
-       }
-
-       /**
-        * Get headers to send to Swift when reading a file based
-        * on a FileBackend params array, e.g. that of getLocalCopy().
-        * $params is currently only checked for a 'latest' flag.
-        *
-        * @param array $params
-        * @return array
-        */
-       protected function headersFromParams( array $params ) {
-               $hdrs = [];
-               if ( !empty( $params['latest'] ) ) {
-                       $hdrs['x-newest'] = 'true';
-               }
-
-               return $hdrs;
-       }
-
-       /**
-        * @param FileBackendStoreOpHandle[] $fileOpHandles
-        *
-        * @return StatusValue[]
-        */
-       protected function doExecuteOpHandlesInternal( array $fileOpHandles ) {
-               $statuses = [];
-
-               $auth = $this->getAuthentication();
-               if ( !$auth ) {
-                       foreach ( $fileOpHandles as $index => $fileOpHandle ) {
-                               $statuses[$index] = $this->newStatus( 'backend-fail-connect', $this->name );
-                       }
-
-                       return $statuses;
-               }
-
-               // Split the HTTP requests into stages that can be done concurrently
-               $httpReqsByStage = []; // map of (stage => index => HTTP request)
-               foreach ( $fileOpHandles as $index => $fileOpHandle ) {
-                       $reqs = $fileOpHandle->httpOp;
-                       // Convert the 'url' parameter to an actual URL using $auth
-                       foreach ( $reqs as $stage => &$req ) {
-                               list( $container, $relPath ) = $req['url'];
-                               $req['url'] = $this->storageUrl( $auth, $container, $relPath );
-                               $req['headers'] = isset( $req['headers'] ) ? $req['headers'] : [];
-                               $req['headers'] = $this->authTokenHeaders( $auth ) + $req['headers'];
-                               $httpReqsByStage[$stage][$index] = $req;
-                       }
-                       $statuses[$index] = $this->newStatus();
-               }
-
-               // Run all requests for the first stage, then the next, and so on
-               $reqCount = count( $httpReqsByStage );
-               for ( $stage = 0; $stage < $reqCount; ++$stage ) {
-                       $httpReqs = $this->http->runMulti( $httpReqsByStage[$stage] );
-                       foreach ( $httpReqs as $index => $httpReq ) {
-                               // Run the callback for each request of this operation
-                               $callback = $fileOpHandles[$index]->callback;
-                               call_user_func_array( $callback, [ $httpReq, $statuses[$index] ] );
-                               // On failure, abort all remaining requests for this operation
-                               // (e.g. abort the DELETE request if the COPY request fails for a move)
-                               if ( !$statuses[$index]->isOK() ) {
-                                       $stages = count( $fileOpHandles[$index]->httpOp );
-                                       for ( $s = ( $stage + 1 ); $s < $stages; ++$s ) {
-                                               unset( $httpReqsByStage[$s][$index] );
-                                       }
-                               }
-                       }
-               }
-
-               return $statuses;
-       }
-
-       /**
-        * Set read/write permissions for a Swift container.
-        *
-        * @see http://swift.openstack.org/misc.html#acls
-        *
-        * In general, we don't allow listings to end-users. It's not useful, isn't well-defined
-        * (lists are truncated to 10000 item with no way to page), and is just a performance risk.
-        *
-        * @param string $container Resolved Swift container
-        * @param array $readGrps List of the possible criteria for a request to have
-        * access to read a container. Each item is one of the following formats:
-        *   - account:user        : Grants access if the request is by the given user
-        *   - ".r:<regex>"        : Grants access if the request is from a referrer host that
-        *                           matches the expression and the request is not for a listing.
-        *                           Setting this to '*' effectively makes a container public.
-        *   -".rlistings:<regex>" : Grants access if the request is from a referrer host that
-        *                           matches the expression and the request is for a listing.
-        * @param array $writeGrps A list of the possible criteria for a request to have
-        * access to write to a container. Each item is of the following format:
-        *   - account:user       : Grants access if the request is by the given user
-        * @return StatusValue
-        */
-       protected function setContainerAccess( $container, array $readGrps, array $writeGrps ) {
-               $status = $this->newStatus();
-               $auth = $this->getAuthentication();
-
-               if ( !$auth ) {
-                       $status->fatal( 'backend-fail-connect', $this->name );
-
-                       return $status;
-               }
-
-               list( $rcode, $rdesc, $rhdrs, $rbody, $rerr ) = $this->http->run( [
-                       'method' => 'POST',
-                       'url' => $this->storageUrl( $auth, $container ),
-                       'headers' => $this->authTokenHeaders( $auth ) + [
-                               'x-container-read' => implode( ',', $readGrps ),
-                               'x-container-write' => implode( ',', $writeGrps )
-                       ]
-               ] );
-
-               if ( $rcode != 204 && $rcode !== 202 ) {
-                       $status->fatal( 'backend-fail-internal', $this->name );
-                       wfDebugLog( 'SwiftBackend', __METHOD__ . ': unexpected rcode value (' . $rcode . ')' );
-               }
-
-               return $status;
-       }
-
-       /**
-        * Get a Swift container stat array, possibly from process cache.
-        * Use $reCache if the file count or byte count is needed.
-        *
-        * @param string $container Container name
-        * @param bool $bypassCache Bypass all caches and load from Swift
-        * @return array|bool|null False on 404, null on failure
-        */
-       protected function getContainerStat( $container, $bypassCache = false ) {
-               $ps = Profiler::instance()->scopedProfileIn( __METHOD__ . "-{$this->name}" );
-
-               if ( $bypassCache ) { // purge cache
-                       $this->containerStatCache->clear( $container );
-               } elseif ( !$this->containerStatCache->has( $container, 'stat' ) ) {
-                       $this->primeContainerCache( [ $container ] ); // check persistent cache
-               }
-               if ( !$this->containerStatCache->has( $container, 'stat' ) ) {
-                       $auth = $this->getAuthentication();
-                       if ( !$auth ) {
-                               return null;
-                       }
-
-                       list( $rcode, $rdesc, $rhdrs, $rbody, $rerr ) = $this->http->run( [
-                               'method' => 'HEAD',
-                               'url' => $this->storageUrl( $auth, $container ),
-                               'headers' => $this->authTokenHeaders( $auth )
-                       ] );
-
-                       if ( $rcode === 204 ) {
-                               $stat = [
-                                       'count' => $rhdrs['x-container-object-count'],
-                                       'bytes' => $rhdrs['x-container-bytes-used']
-                               ];
-                               if ( $bypassCache ) {
-                                       return $stat;
-                               } else {
-                                       $this->containerStatCache->set( $container, 'stat', $stat ); // cache it
-                                       $this->setContainerCache( $container, $stat ); // update persistent cache
-                               }
-                       } elseif ( $rcode === 404 ) {
-                               return false;
-                       } else {
-                               $this->onError( null, __METHOD__,
-                                       [ 'cont' => $container ], $rerr, $rcode, $rdesc );
-
-                               return null;
-                       }
-               }
-
-               return $this->containerStatCache->get( $container, 'stat' );
-       }
-
-       /**
-        * Create a Swift container
-        *
-        * @param string $container Container name
-        * @param array $params
-        * @return StatusValue
-        */
-       protected function createContainer( $container, array $params ) {
-               $status = $this->newStatus();
-
-               $auth = $this->getAuthentication();
-               if ( !$auth ) {
-                       $status->fatal( 'backend-fail-connect', $this->name );
-
-                       return $status;
-               }
-
-               // @see SwiftFileBackend::setContainerAccess()
-               if ( empty( $params['noAccess'] ) ) {
-                       $readGrps = [ '.r:*', $this->swiftUser ]; // public
-               } else {
-                       $readGrps = [ $this->swiftUser ]; // private
-               }
-               $writeGrps = [ $this->swiftUser ]; // sanity
-
-               list( $rcode, $rdesc, $rhdrs, $rbody, $rerr ) = $this->http->run( [
-                       'method' => 'PUT',
-                       'url' => $this->storageUrl( $auth, $container ),
-                       'headers' => $this->authTokenHeaders( $auth ) + [
-                               'x-container-read' => implode( ',', $readGrps ),
-                               'x-container-write' => implode( ',', $writeGrps )
-                       ]
-               ] );
-
-               if ( $rcode === 201 ) { // new
-                       // good
-               } elseif ( $rcode === 202 ) { // already there
-                       // this shouldn't really happen, but is OK
-               } else {
-                       $this->onError( $status, __METHOD__, $params, $rerr, $rcode, $rdesc );
-               }
-
-               return $status;
-       }
-
-       /**
-        * Delete a Swift container
-        *
-        * @param string $container Container name
-        * @param array $params
-        * @return StatusValue
-        */
-       protected function deleteContainer( $container, array $params ) {
-               $status = $this->newStatus();
-
-               $auth = $this->getAuthentication();
-               if ( !$auth ) {
-                       $status->fatal( 'backend-fail-connect', $this->name );
-
-                       return $status;
-               }
-
-               list( $rcode, $rdesc, $rhdrs, $rbody, $rerr ) = $this->http->run( [
-                       'method' => 'DELETE',
-                       'url' => $this->storageUrl( $auth, $container ),
-                       'headers' => $this->authTokenHeaders( $auth )
-               ] );
-
-               if ( $rcode >= 200 && $rcode <= 299 ) { // deleted
-                       $this->containerStatCache->clear( $container ); // purge
-               } elseif ( $rcode === 404 ) { // not there
-                       // this shouldn't really happen, but is OK
-               } elseif ( $rcode === 409 ) { // not empty
-                       $this->onError( $status, __METHOD__, $params, $rerr, $rcode, $rdesc ); // race?
-               } else {
-                       $this->onError( $status, __METHOD__, $params, $rerr, $rcode, $rdesc );
-               }
-
-               return $status;
-       }
-
-       /**
-        * Get a list of objects under a container.
-        * Either just the names or a list of stdClass objects with details can be returned.
-        *
-        * @param string $fullCont
-        * @param string $type ('info' for a list of object detail maps, 'names' for names only)
-        * @param int $limit
-        * @param string|null $after
-        * @param string|null $prefix
-        * @param string|null $delim
-        * @return StatusValue With the list as value
-        */
-       private function objectListing(
-               $fullCont, $type, $limit, $after = null, $prefix = null, $delim = null
-       ) {
-               $status = $this->newStatus();
-
-               $auth = $this->getAuthentication();
-               if ( !$auth ) {
-                       $status->fatal( 'backend-fail-connect', $this->name );
-
-                       return $status;
-               }
-
-               $query = [ 'limit' => $limit ];
-               if ( $type === 'info' ) {
-                       $query['format'] = 'json';
-               }
-               if ( $after !== null ) {
-                       $query['marker'] = $after;
-               }
-               if ( $prefix !== null ) {
-                       $query['prefix'] = $prefix;
-               }
-               if ( $delim !== null ) {
-                       $query['delimiter'] = $delim;
-               }
-
-               list( $rcode, $rdesc, $rhdrs, $rbody, $rerr ) = $this->http->run( [
-                       'method' => 'GET',
-                       'url' => $this->storageUrl( $auth, $fullCont ),
-                       'query' => $query,
-                       'headers' => $this->authTokenHeaders( $auth )
-               ] );
-
-               $params = [ 'cont' => $fullCont, 'prefix' => $prefix, 'delim' => $delim ];
-               if ( $rcode === 200 ) { // good
-                       if ( $type === 'info' ) {
-                               $status->value = FormatJson::decode( trim( $rbody ) );
-                       } else {
-                               $status->value = explode( "\n", trim( $rbody ) );
-                       }
-               } elseif ( $rcode === 204 ) {
-                       $status->value = []; // empty container
-               } elseif ( $rcode === 404 ) {
-                       $status->value = []; // no container
-               } else {
-                       $this->onError( $status, __METHOD__, $params, $rerr, $rcode, $rdesc );
-               }
-
-               return $status;
-       }
-
-       protected function doPrimeContainerCache( array $containerInfo ) {
-               foreach ( $containerInfo as $container => $info ) {
-                       $this->containerStatCache->set( $container, 'stat', $info );
-               }
-       }
-
-       protected function doGetFileStatMulti( array $params ) {
-               $stats = [];
-
-               $auth = $this->getAuthentication();
-
-               $reqs = [];
-               foreach ( $params['srcs'] as $path ) {
-                       list( $srcCont, $srcRel ) = $this->resolveStoragePathReal( $path );
-                       if ( $srcRel === null ) {
-                               $stats[$path] = false;
-                               continue; // invalid storage path
-                       } elseif ( !$auth ) {
-                               $stats[$path] = null;
-                               continue;
-                       }
-
-                       // (a) Check the container
-                       $cstat = $this->getContainerStat( $srcCont );
-                       if ( $cstat === false ) {
-                               $stats[$path] = false;
-                               continue; // ok, nothing to do
-                       } elseif ( !is_array( $cstat ) ) {
-                               $stats[$path] = null;
-                               continue;
-                       }
-
-                       $reqs[$path] = [
-                               'method'  => 'HEAD',
-                               'url'     => $this->storageUrl( $auth, $srcCont, $srcRel ),
-                               'headers' => $this->authTokenHeaders( $auth ) + $this->headersFromParams( $params )
-                       ];
-               }
-
-               $opts = [ 'maxConnsPerHost' => $params['concurrency'] ];
-               $reqs = $this->http->runMulti( $reqs, $opts );
-
-               foreach ( $params['srcs'] as $path ) {
-                       if ( array_key_exists( $path, $stats ) ) {
-                               continue; // some sort of failure above
-                       }
-                       // (b) Check the file
-                       list( $rcode, $rdesc, $rhdrs, $rbody, $rerr ) = $reqs[$path]['response'];
-                       if ( $rcode === 200 || $rcode === 204 ) {
-                               // Update the object if it is missing some headers
-                               $rhdrs = $this->addMissingMetadata( $rhdrs, $path );
-                               // Load the stat array from the headers
-                               $stat = $this->getStatFromHeaders( $rhdrs );
-                               if ( $this->isRGW ) {
-                                       $stat['latest'] = true; // strong consistency
-                               }
-                       } elseif ( $rcode === 404 ) {
-                               $stat = false;
-                       } else {
-                               $stat = null;
-                               $this->onError( null, __METHOD__, $params, $rerr, $rcode, $rdesc );
-                       }
-                       $stats[$path] = $stat;
-               }
-
-               return $stats;
-       }
-
-       /**
-        * @param array $rhdrs
-        * @return array
-        */
-       protected function getStatFromHeaders( array $rhdrs ) {
-               // Fetch all of the custom metadata headers
-               $metadata = $this->getMetadata( $rhdrs );
-               // Fetch all of the custom raw HTTP headers
-               $headers = $this->sanitizeHdrs( [ 'headers' => $rhdrs ] );
-
-               return [
-                       // Convert various random Swift dates to TS_MW
-                       'mtime' => $this->convertSwiftDate( $rhdrs['last-modified'], TS_MW ),
-                       // Empty objects actually return no content-length header in Ceph
-                       'size'  => isset( $rhdrs['content-length'] ) ? (int)$rhdrs['content-length'] : 0,
-                       'sha1'  => isset( $metadata['sha1base36'] ) ? $metadata['sha1base36'] : null,
-                       // Note: manifiest ETags are not an MD5 of the file
-                       'md5'   => ctype_xdigit( $rhdrs['etag'] ) ? $rhdrs['etag'] : null,
-                       'xattr' => [ 'metadata' => $metadata, 'headers' => $headers ]
-               ];
-       }
-
-       /**
-        * @return array|null Credential map
-        */
-       protected function getAuthentication() {
-               if ( $this->authErrorTimestamp !== null ) {
-                       if ( ( time() - $this->authErrorTimestamp ) < 60 ) {
-                               return null; // failed last attempt; don't bother
-                       } else { // actually retry this time
-                               $this->authErrorTimestamp = null;
-                       }
-               }
-               // Session keys expire after a while, so we renew them periodically
-               $reAuth = ( ( time() - $this->authSessionTimestamp ) > $this->authTTL );
-               // Authenticate with proxy and get a session key...
-               if ( !$this->authCreds || $reAuth ) {
-                       $this->authSessionTimestamp = 0;
-                       $cacheKey = $this->getCredsCacheKey( $this->swiftUser );
-                       $creds = $this->srvCache->get( $cacheKey ); // credentials
-                       // Try to use the credential cache
-                       if ( isset( $creds['auth_token'] ) && isset( $creds['storage_url'] ) ) {
-                               $this->authCreds = $creds;
-                               // Skew the timestamp for worst case to avoid using stale credentials
-                               $this->authSessionTimestamp = time() - ceil( $this->authTTL / 2 );
-                       } else { // cache miss
-                               list( $rcode, $rdesc, $rhdrs, $rbody, $rerr ) = $this->http->run( [
-                                       'method' => 'GET',
-                                       'url' => "{$this->swiftAuthUrl}/v1.0",
-                                       'headers' => [
-                                               'x-auth-user' => $this->swiftUser,
-                                               'x-auth-key' => $this->swiftKey
-                                       ]
-                               ] );
-
-                               if ( $rcode >= 200 && $rcode <= 299 ) { // OK
-                                       $this->authCreds = [
-                                               'auth_token' => $rhdrs['x-auth-token'],
-                                               'storage_url' => $rhdrs['x-storage-url']
-                                       ];
-                                       $this->srvCache->set( $cacheKey, $this->authCreds, ceil( $this->authTTL / 2 ) );
-                                       $this->authSessionTimestamp = time();
-                               } elseif ( $rcode === 401 ) {
-                                       $this->onError( null, __METHOD__, [], "Authentication failed.", $rcode );
-                                       $this->authErrorTimestamp = time();
-
-                                       return null;
-                               } else {
-                                       $this->onError( null, __METHOD__, [], "HTTP return code: $rcode", $rcode );
-                                       $this->authErrorTimestamp = time();
-
-                                       return null;
-                               }
-                       }
-                       // Ceph RGW does not use <account> in URLs (OpenStack Swift uses "/v1/<account>")
-                       if ( substr( $this->authCreds['storage_url'], -3 ) === '/v1' ) {
-                               $this->isRGW = true; // take advantage of strong consistency in Ceph
-                       }
-               }
-
-               return $this->authCreds;
-       }
-
-       /**
-        * @param array $creds From getAuthentication()
-        * @param string $container
-        * @param string $object
-        * @return array
-        */
-       protected function storageUrl( array $creds, $container = null, $object = null ) {
-               $parts = [ $creds['storage_url'] ];
-               if ( strlen( $container ) ) {
-                       $parts[] = rawurlencode( $container );
-               }
-               if ( strlen( $object ) ) {
-                       $parts[] = str_replace( "%2F", "/", rawurlencode( $object ) );
-               }
-
-               return implode( '/', $parts );
-       }
-
-       /**
-        * @param array $creds From getAuthentication()
-        * @return array
-        */
-       protected function authTokenHeaders( array $creds ) {
-               return [ 'x-auth-token' => $creds['auth_token'] ];
-       }
-
-       /**
-        * Get the cache key for a container
-        *
-        * @param string $username
-        * @return string
-        */
-       private function getCredsCacheKey( $username ) {
-               return 'swiftcredentials:' . md5( $username . ':' . $this->swiftAuthUrl );
-       }
-
-       /**
-        * Log an unexpected exception for this backend.
-        * This also sets the StatusValue object to have a fatal error.
-        *
-        * @param StatusValue|null $status
-        * @param string $func
-        * @param array $params
-        * @param string $err Error string
-        * @param int $code HTTP status
-        * @param string $desc HTTP StatusValue description
-        */
-       public function onError( $status, $func, array $params, $err = '', $code = 0, $desc = '' ) {
-               if ( $status instanceof StatusValue ) {
-                       $status->fatal( 'backend-fail-internal', $this->name );
-               }
-               if ( $code == 401 ) { // possibly a stale token
-                       $this->srvCache->delete( $this->getCredsCacheKey( $this->swiftUser ) );
-               }
-               wfDebugLog( 'SwiftBackend',
-                       "HTTP $code ($desc) in '{$func}' (given '" . FormatJson::encode( $params ) . "')" .
-                       ( $err ? ": $err" : "" )
-               );
-       }
-}
-
-/**
- * @see FileBackendStoreOpHandle
- */
-class SwiftFileOpHandle extends FileBackendStoreOpHandle {
-       /** @var array List of Requests for MultiHttpClient */
-       public $httpOp;
-       /** @var Closure */
-       public $callback;
-
-       /**
-        * @param SwiftFileBackend $backend
-        * @param Closure $callback Function that takes (HTTP request array, status)
-        * @param array $httpOp MultiHttpClient op
-        */
-       public function __construct( SwiftFileBackend $backend, Closure $callback, array $httpOp ) {
-               $this->backend = $backend;
-               $this->callback = $callback;
-               $this->httpOp = $httpOp;
-       }
-}
-
-/**
- * SwiftFileBackend helper class to page through listings.
- * Swift also has a listing limit of 10,000 objects for sanity.
- * Do not use this class from places outside SwiftFileBackend.
- *
- * @ingroup FileBackend
- */
-abstract class SwiftFileBackendList implements Iterator {
-       /** @var array List of path or (path,stat array) entries */
-       protected $bufferIter = [];
-
-       /** @var string List items *after* this path */
-       protected $bufferAfter = null;
-
-       /** @var int */
-       protected $pos = 0;
-
-       /** @var array */
-       protected $params = [];
-
-       /** @var SwiftFileBackend */
-       protected $backend;
-
-       /** @var string Container name */
-       protected $container;
-
-       /** @var string Storage directory */
-       protected $dir;
-
-       /** @var int */
-       protected $suffixStart;
-
-       const PAGE_SIZE = 9000; // file listing buffer size
-
-       /**
-        * @param SwiftFileBackend $backend
-        * @param string $fullCont Resolved container name
-        * @param string $dir Resolved directory relative to container
-        * @param array $params
-        */
-       public function __construct( SwiftFileBackend $backend, $fullCont, $dir, array $params ) {
-               $this->backend = $backend;
-               $this->container = $fullCont;
-               $this->dir = $dir;
-               if ( substr( $this->dir, -1 ) === '/' ) {
-                       $this->dir = substr( $this->dir, 0, -1 ); // remove trailing slash
-               }
-               if ( $this->dir == '' ) { // whole container
-                       $this->suffixStart = 0;
-               } else { // dir within container
-                       $this->suffixStart = strlen( $this->dir ) + 1; // size of "path/to/dir/"
-               }
-               $this->params = $params;
-       }
-
-       /**
-        * @see Iterator::key()
-        * @return int
-        */
-       public function key() {
-               return $this->pos;
-       }
-
-       /**
-        * @see Iterator::next()
-        */
-       public function next() {
-               // Advance to the next file in the page
-               next( $this->bufferIter );
-               ++$this->pos;
-               // Check if there are no files left in this page and
-               // advance to the next page if this page was not empty.
-               if ( !$this->valid() && count( $this->bufferIter ) ) {
-                       $this->bufferIter = $this->pageFromList(
-                               $this->container, $this->dir, $this->bufferAfter, self::PAGE_SIZE, $this->params
-                       ); // updates $this->bufferAfter
-               }
-       }
-
-       /**
-        * @see Iterator::rewind()
-        */
-       public function rewind() {
-               $this->pos = 0;
-               $this->bufferAfter = null;
-               $this->bufferIter = $this->pageFromList(
-                       $this->container, $this->dir, $this->bufferAfter, self::PAGE_SIZE, $this->params
-               ); // updates $this->bufferAfter
-       }
-
-       /**
-        * @see Iterator::valid()
-        * @return bool
-        */
-       public function valid() {
-               if ( $this->bufferIter === null ) {
-                       return false; // some failure?
-               } else {
-                       return ( current( $this->bufferIter ) !== false ); // no paths can have this value
-               }
-       }
-
-       /**
-        * Get the given list portion (page)
-        *
-        * @param string $container Resolved container name
-        * @param string $dir Resolved path relative to container
-        * @param string $after
-        * @param int $limit
-        * @param array $params
-        * @return Traversable|array
-        */
-       abstract protected function pageFromList( $container, $dir, &$after, $limit, array $params );
-}
-
-/**
- * Iterator for listing directories
- */
-class SwiftFileBackendDirList extends SwiftFileBackendList {
-       /**
-        * @see Iterator::current()
-        * @return string|bool String (relative path) or false
-        */
-       public function current() {
-               return substr( current( $this->bufferIter ), $this->suffixStart, -1 );
-       }
-
-       protected function pageFromList( $container, $dir, &$after, $limit, array $params ) {
-               return $this->backend->getDirListPageInternal( $container, $dir, $after, $limit, $params );
-       }
-}
-
-/**
- * Iterator for listing regular files
- */
-class SwiftFileBackendFileList extends SwiftFileBackendList {
-       /**
-        * @see Iterator::current()
-        * @return string|bool String (relative path) or false
-        */
-       public function current() {
-               list( $path, $stat ) = current( $this->bufferIter );
-               $relPath = substr( $path, $this->suffixStart );
-               if ( is_array( $stat ) ) {
-                       $storageDir = rtrim( $this->params['dir'], '/' );
-                       $this->backend->loadListingStatInternal( "$storageDir/$relPath", $stat );
-               }
-
-               return $relPath;
-       }
-
-       protected function pageFromList( $container, $dir, &$after, $limit, array $params ) {
-               return $this->backend->getFileListPageInternal( $container, $dir, $after, $limit, $params );
-       }
-}
index 001800f..be046bd 100644 (file)
@@ -106,7 +106,7 @@ class ForeignDBRepo extends LocalRepo {
                ];
 
                return function ( $index ) use ( $type, $params ) {
-                       return DatabaseBase::factory( $type, $params );
+                       return Database::factory( $type, $params );
                };
        }
 
index 60cfdac..7ffb147 100644 (file)
@@ -2852,7 +2852,7 @@ class LocalFileMoveBatch {
 
        protected $archive;
 
-       /** @var DatabaseBase */
+       /** @var IDatabase */
        protected $db;
 
        /**
index 567e692..c65d97f 100644 (file)
@@ -153,6 +153,9 @@ class HTMLForm extends ContextSource {
                'checkmatrix' => 'HTMLCheckMatrix',
                'cloner' => 'HTMLFormFieldCloner',
                'autocompleteselect' => 'HTMLAutoCompleteSelectField',
+               'date' => 'HTMLDateTimeField',
+               'time' => 'HTMLDateTimeField',
+               'datetime' => 'HTMLDateTimeField',
                // HTMLTextField will output the correct type="" attribute automagically.
                // There are about four zillion other HTML5 input types, like range, but
                // we don't use those at the moment, so no point in adding all of them.
index bbd3473..6fbf15b 100644 (file)
@@ -202,8 +202,8 @@ class OOUIHTMLForm extends HTMLForm {
                        } else {
                                $errors = $elements->getErrorsByType( $elementsType );
                                foreach ( $errors as &$error ) {
-                                       // Input:  array( 'message' => 'foo', 'errors' => array( 'a', 'b', 'c' ) )
-                                       // Output: array( 'foo', 'a', 'b', 'c' )
+                                       // Input:  [ 'message' => 'foo', 'errors' => [ 'a', 'b', 'c' ] ]
+                                       // Output: [ 'foo', 'a', 'b', 'c' ]
                                        $error = array_merge( [ $error['message'] ], $error['params'] );
                                }
                        }
diff --git a/includes/htmlform/fields/HTMLDateTimeField.php b/includes/htmlform/fields/HTMLDateTimeField.php
new file mode 100644 (file)
index 0000000..66f89f9
--- /dev/null
@@ -0,0 +1,190 @@
+<?php
+
+/**
+ * A field that will contain a date and/or time
+ *
+ * Currently recognizes only {YYYY}-{MM}-{DD}T{HH}:{MM}:{SS.S*}Z formatted dates.
+ *
+ * Besides the parameters recognized by HTMLTextField, additional recognized
+ * parameters in the field descriptor array include:
+ *  type - 'date', 'time', or 'datetime'
+ *  min - The minimum date to allow, in any recognized format.
+ *  max - The maximum date to allow, in any recognized format.
+ *  placeholder - The default comes from the htmlform-(date|time|datetime)-placeholder message.
+ *
+ * The result is a formatted date.
+ *
+ * @note This widget is not likely to work well in non-OOUI forms.
+ */
+class HTMLDateTimeField extends HTMLTextField {
+       protected static $patterns = [
+               'date' => '[0-9]{4}-[01][0-9]-[0-3][0-9]',
+               'time' => '[0-2][0-9]:[0-5][0-9]:[0-5][0-9](?:\.[0-9]+)?',
+               'datetime' => '[0-9]{4}-[01][0-9]-[0-3][0-9][T ][0-2][0-9]:[0-5][0-9]:[0-5][0-9](?:\.[0-9]+)?Z?',
+       ];
+
+       protected $mType = 'datetime';
+
+       public function __construct( $params ) {
+               parent::__construct( $params );
+
+               $this->mType = array_key_exists( 'type', $params )
+                       ? $params['type']
+                       : 'datetime';
+
+               if ( !in_array( $this->mType, [ 'date', 'time', 'datetime' ] ) ) {
+                       throw new InvalidArgumentException( "Invalid type '$this->mType'" );
+               }
+
+               $this->mClass .= ' mw-htmlform-datetime-field';
+       }
+
+       public function getAttributes( array $list ) {
+               $parentList = array_diff( $list, [ 'min', 'max' ] );
+               $ret = parent::getAttributes( $parentList );
+
+               if ( in_array( 'placeholder', $list ) && !isset( $ret['placeholder'] ) ) {
+                       // Messages: htmlform-date-placeholder htmlform-time-placeholder htmlform-datetime-placeholder
+                       $ret['placeholder'] = $this->msg( "htmlform-{$this->mType}-placeholder" )->text();
+               }
+
+               if ( in_array( 'min', $list ) && isset( $this->mParams['min'] ) ) {
+                       $min = $this->parseDate( $this->mParams['min'] );
+                       if ( $min ) {
+                               $ret['min'] = $this->formatDate( $min );
+                               // Because Html::expandAttributes filters it out
+                               $ret['data-min'] = $ret['min'];
+                       }
+               }
+               if ( in_array( 'max', $list ) && isset( $this->mParams['max'] ) ) {
+                       $max = $this->parseDate( $this->mParams['max'] );
+                       if ( $max ) {
+                               $ret['max'] = $this->formatDate( $max );
+                               // Because Html::expandAttributes filters it out
+                               $ret['data-max'] = $ret['max'];
+                       }
+               }
+
+               $ret['step'] = 1;
+               // Because Html::expandAttributes filters it out
+               $ret['data-step'] = 1;
+
+               $ret['type'] = $this->mType;
+               $ret['pattern'] = static::$patterns[$this->mType];
+
+               return $ret;
+       }
+
+       function loadDataFromRequest( $request ) {
+               if ( !$request->getCheck( $this->mName ) ) {
+                       return $this->getDefault();
+               }
+
+               $value = $request->getText( $this->mName );
+               $date = $this->parseDate( $value );
+               return $date ? $this->formatDate( $date ) : $value;
+       }
+
+       function validate( $value, $alldata ) {
+               $p = parent::validate( $value, $alldata );
+
+               if ( $p !== true ) {
+                       return $p;
+               }
+
+               if ( $value === '' ) {
+                       // required was already checked by parent::validate
+                       return true;
+               }
+
+               $date = $this->parseDate( $value );
+               if ( !$date ) {
+                       // Messages: htmlform-date-invalid htmlform-time-invalid htmlform-datetime-invalid
+                       return $this->msg( "htmlform-{$this->mType}-invalid" )->parseAsBlock();
+               }
+
+               if ( isset( $this->mParams['min'] ) ) {
+                       $min = $this->parseDate( $this->mParams['min'] );
+                       if ( $min && $date < $min ) {
+                               // Messages: htmlform-date-toolow htmlform-time-toolow htmlform-datetime-toolow
+                               return $this->msg( "htmlform-{$this->mType}-toolow", $this->formatDate( $min ) )
+                                       ->parseAsBlock();
+                       }
+               }
+
+               if ( isset( $this->mParams['max'] ) ) {
+                       $max = $this->parseDate( $this->mParams['max'] );
+                       if ( $max && $date > $max ) {
+                               // Messages: htmlform-date-toohigh htmlform-time-toohigh htmlform-datetime-toohigh
+                               return $this->msg( "htmlform-{$this->mType}-toohigh", $this->formatDate( $max ) )
+                                       ->parseAsBlock();
+                       }
+               }
+
+               return true;
+       }
+
+       protected function parseDate( $value ) {
+               $value = trim( $value );
+
+               if ( $this->mType === 'date' ) {
+                       $value .= ' T00:00:00+0000';
+               }
+               if ( $this->mType === 'time' ) {
+                       $value = '1970-01-01 ' . $value . '+0000';
+               }
+
+               try {
+                       $date = new DateTime( $value, new DateTimeZone( 'GMT' ) );
+                       return $date->getTimestamp();
+               } catch ( Exception $ex ) {
+                       return 0;
+               }
+       }
+
+       protected function formatDate( $value ) {
+               switch ( $this->mType ) {
+                       case 'date':
+                               return gmdate( 'Y-m-d', $value );
+
+                       case 'time':
+                               return gmdate( 'H:i:s', $value );
+
+                       case 'datetime':
+                               return gmdate( 'Y-m-d\\TH:i:s\\Z', $value );
+               }
+       }
+
+       public function getInputOOUI( $value ) {
+               $params = [
+                       'type' => $this->mType,
+                       'value' => $value,
+                       'name' => $this->mName,
+                       'id' => $this->mID,
+               ];
+
+               if ( isset( $this->mParams['min'] ) ) {
+                       $min = $this->parseDate( $this->mParams['min'] );
+                       if ( $min ) {
+                               $params['min'] = $this->formatDate( $min );
+                       }
+               }
+               if ( isset( $this->mParams['max'] ) ) {
+                       $max = $this->parseDate( $this->mParams['max'] );
+                       if ( $max ) {
+                               $params['max'] = $this->formatDate( $max );
+                       }
+               }
+
+               return new MediaWiki\Widget\DateTimeInputWidget( $params );
+       }
+
+       protected function getOOUIModules() {
+               return [ 'mediawiki.widgets.datetime' ];
+       }
+
+       protected function shouldInfuseOOUI() {
+               return true;
+       }
+
+}
index 4f10367..2b84144 100644 (file)
@@ -167,7 +167,7 @@ abstract class DatabaseInstaller {
         *
         * @param string $sourceFileMethod
         * @param string $stepName
-        * @param string $archiveTableMustNotExist
+        * @param bool $archiveTableMustNotExist
         * @return Status
         */
        private function stepApplySourceFile(
@@ -353,10 +353,14 @@ abstract class DatabaseInstaller {
                $up = DatabaseUpdater::newForDB( $this->db );
                try {
                        $up->doUpdates();
-               } catch ( Exception $e ) {
+               } catch ( MWException $e ) {
                        echo "\nAn error occurred:\n";
                        echo $e->getText();
                        $ret = false;
+               } catch ( Exception $e ) {
+                       echo "\nAn error occurred:\n";
+                       echo $e->getMessage();
+                       $ret = false;
                }
                $up->purgeCache();
                ob_end_flush();
index 0d0da08..fbdc934 100644 (file)
@@ -20,6 +20,7 @@
  * @file
  * @ingroup Deployment
  */
+use MediaWiki\MediaWikiServices;
 
 require_once __DIR__ . '/../../maintenance/Maintenance.php';
 
@@ -100,11 +101,11 @@ abstract class DatabaseUpdater {
        /**
         * Constructor
         *
-        * @param DatabaseBase $db To perform updates on
+        * @param Database $db To perform updates on
         * @param bool $shared Whether to perform updates on shared tables
         * @param Maintenance $maintenance Maintenance object which created us
         */
-       protected function __construct( DatabaseBase &$db, $shared, Maintenance $maintenance = null ) {
+       protected function __construct( Database &$db, $shared, Maintenance $maintenance = null ) {
                $this->db = $db;
                $this->db->setFlag( DBO_DDLMODE ); // For Oracle's handling of schema files
                $this->shared = $shared;
@@ -456,6 +457,8 @@ abstract class DatabaseUpdater {
         * @param bool $passSelf Whether to pass this object we calling external functions
         */
        private function runUpdates( array $updates, $passSelf ) {
+               $lbFactory = MediaWikiServices::getInstance()->getDBLoadBalancerFactory();
+
                $updatesDone = [];
                $updatesSkipped = [];
                foreach ( $updates as $params ) {
@@ -470,7 +473,7 @@ abstract class DatabaseUpdater {
                        flush();
                        if ( $ret !== false ) {
                                $updatesDone[] = $origParams;
-                               wfGetLBFactory()->waitForReplication();
+                               $lbFactory->waitForReplication();
                        } else {
                                $updatesSkipped[] = [ $func, $params, $origParams ];
                        }
index 62cd883..739be82 100644 (file)
@@ -212,7 +212,7 @@ class MssqlInstaller extends DatabaseInstaller {
                }
 
                try {
-                       $db = DatabaseBase::factory( 'mssql', [
+                       $db = Database::factory( 'mssql', [
                                'host' => $this->getVar( 'wgDBserver' ),
                                'user' => $user,
                                'password' => $password,
@@ -261,7 +261,7 @@ class MssqlInstaller extends DatabaseInstaller {
                if ( !$status->isOK() ) {
                        return false;
                }
-               /** @var $conn DatabaseBase */
+               /** @var $conn Database */
                $conn = $status->value;
 
                // We need the server-level ALTER ANY LOGIN permission to create new accounts
@@ -457,7 +457,7 @@ class MssqlInstaller extends DatabaseInstaller {
                        }
 
                        try {
-                               DatabaseBase::factory( 'mssql', [
+                               Database::factory( 'mssql', [
                                        'host' => $this->getVar( 'wgDBserver' ),
                                        'user' => $user,
                                        'password' => $password,
@@ -491,7 +491,7 @@ class MssqlInstaller extends DatabaseInstaller {
                if ( !$status->isOK() ) {
                        return $status;
                }
-               /** @var DatabaseBase $conn */
+               /** @var Database $conn */
                $conn = $status->value;
                $dbName = $this->getVar( 'wgDBname' );
                $schemaName = $this->getVar( 'wgDBmwschema' );
index 1bd3f51..812742c 100644 (file)
@@ -143,7 +143,7 @@ class MysqlInstaller extends DatabaseInstaller {
        public function openConnection() {
                $status = Status::newGood();
                try {
-                       $db = DatabaseBase::factory( 'mysql', [
+                       $db = Database::factory( 'mysql', [
                                'host' => $this->getVar( 'wgDBserver' ),
                                'user' => $this->getVar( '_InstallUser' ),
                                'password' => $this->getVar( '_InstallPassword' ),
@@ -261,7 +261,7 @@ class MysqlInstaller extends DatabaseInstaller {
                if ( !$status->isOK() ) {
                        return false;
                }
-               /** @var $conn DatabaseBase */
+               /** @var $conn Database */
                $conn = $status->value;
 
                // Get current account name
@@ -427,7 +427,7 @@ class MysqlInstaller extends DatabaseInstaller {
                if ( !$create ) {
                        // Test the web account
                        try {
-                               DatabaseBase::factory( 'mysql', [
+                               Database::factory( 'mysql', [
                                        'host' => $this->getVar( 'wgDBserver' ),
                                        'user' => $this->getVar( 'wgDBuser' ),
                                        'password' => $this->getVar( 'wgDBpassword' ),
@@ -471,7 +471,7 @@ class MysqlInstaller extends DatabaseInstaller {
                if ( !$status->isOK() ) {
                        return $status;
                }
-               /** @var DatabaseBase $conn */
+               /** @var Database $conn */
                $conn = $status->value;
                $dbName = $this->getVar( 'wgDBname' );
                if ( !$conn->selectDB( $dbName ) ) {
@@ -509,7 +509,7 @@ class MysqlInstaller extends DatabaseInstaller {
                if ( $this->getVar( '_CreateDBAccount' ) ) {
                        // Before we blindly try to create a user that already has access,
                        try { // first attempt to connect to the database
-                               DatabaseBase::factory( 'mysql', [
+                               Database::factory( 'mysql', [
                                        'host' => $server,
                                        'user' => $dbUser,
                                        'password' => $password,
index 0728415..7a2794d 100644 (file)
@@ -154,7 +154,7 @@ class PostgresInstaller extends DatabaseInstaller {
        protected function openConnectionWithParams( $user, $password, $dbName, $schema ) {
                $status = Status::newGood();
                try {
-                       $db = DatabaseBase::factory( 'postgres', [
+                       $db = Database::factory( 'postgres', [
                                'host' => $this->getVar( 'wgDBserver' ),
                                'user' => $user,
                                'password' => $password,
@@ -264,7 +264,7 @@ class PostgresInstaller extends DatabaseInstaller {
                                        'password' => $password,
                                        'dbname' => $db
                                ];
-                               $conn = DatabaseBase::factory( 'postgres', $p );
+                               $conn = Database::factory( 'postgres', $p );
                        } catch ( DBConnectionError $error ) {
                                $conn = false;
                                $status->fatal( 'config-pg-test-error', $db,
@@ -413,7 +413,7 @@ class PostgresInstaller extends DatabaseInstaller {
 
        /**
         * Recursive helper for canCreateObjectsForWebUser().
-        * @param DatabaseBase $conn
+        * @param Database $conn
         * @param int $targetMember Role ID of the member to look for
         * @param int $group Role ID of the group to look for
         * @param int $maxDepth Maximum recursive search depth
index 0adeddf..c5c4a7c 100644 (file)
@@ -184,7 +184,7 @@ class SqliteInstaller extends DatabaseInstaller {
                $dbName = $this->getVar( 'wgDBname' );
                try {
                        # @todo FIXME: Need more sensible constructor parameters, e.g. single associative array
-                       $db = DatabaseBase::factory( 'sqlite', [ 'dbname' => $dbName, 'dbDirectory' => $dir ] );
+                       $db = Database::factory( 'sqlite', [ 'dbname' => $dbName, 'dbDirectory' => $dir ] );
                        $status->value = $db;
                } catch ( DBConnectionError $e ) {
                        $status->fatal( 'config-sqlite-connection-error', $e->getMessage() );
@@ -239,7 +239,7 @@ class SqliteInstaller extends DatabaseInstaller {
 
                # Create the global cache DB
                try {
-                       $conn = DatabaseBase::factory( 'sqlite', [ 'dbname' => 'wikicache', 'dbDirectory' => $dir ] );
+                       $conn = Database::factory( 'sqlite', [ 'dbname' => 'wikicache', 'dbDirectory' => $dir ] );
                        # @todo: don't duplicate objectcache definition, though it's very simple
                        $sql =
 <<<EOT
index 6fa270a..c80d54e 100644 (file)
@@ -13,6 +13,7 @@
        "config-localsettings-key": "Kesay berzkerdin:",
        "config-your-language": "Zıwanê şıma:",
        "config-wiki-language": "Wiki zıwan:",
+       "config-wiki-language-help": "Degmesi zıwanê kı wiki do tey bınusi yo",
        "config-back": "← Peyser",
        "config-continue": "Dewam ke",
        "config-page-language": "Zıwan",
        "config-page-complete": "Temamyayo",
        "config-page-restart": "Barkerdışi fına ser kı",
        "config-page-readme": "Mı bıwane",
+       "config-page-releasenotes": "Notë versiyoni",
        "config-page-copying": "Kopyayeno",
        "config-page-upgradedoc": "Berzkerdış",
+       "config-page-existingwiki": "Mewcud wiki",
        "config-restart": "E, fına dest pekê",
        "config-sidebar": "* [https://www.mediawiki.org MediaWiki keye]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Contents Şınasiya Karberi]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Contents Şınasiya İdarekaran]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ Peşti]\n----\n* <doclink href=Readme>Mı buwanê</doclink>\n* <doclink href=ReleaseNotes>Notê elaqeyıni</doclink>\n* <doclink href=Copying>Kopyakerdış</doclink>\n* <doclink href=UpgradeDoc>Zêdekerdış</doclink>",
        "config-env-php": "PHP $1 i biyo saz.",
        "config-db-type": "Database tipe:",
        "config-db-host": "Database host:",
        "config-db-host-oracle": "Database TNS:",
+       "config-db-wiki-settings": "Ena wikiyer akernë",
        "config-db-name": "Database name:",
+       "config-db-name-oracle": "Şemaya hardata:",
        "config-db-username": "Database nameykarberi:",
        "config-db-password": "Database parola :",
        "config-db-port": "Portê database:",
+       "config-oracle-def-ts": "Hesıbyaye caytabloy:",
+       "config-oracle-temp-ts": "İdareten caytabloy:",
+       "config-type-mysql": "MySQL (yana hewlın)",
        "config-type-mssql": "Microsoft SQL Server",
        "config-header-mysql": "Eyarê MySQL",
+       "config-header-sqlite": "SQLite sazi",
+       "config-header-oracle": "Orqcle sazi",
+       "config-header-mssql": "Sazë Microsoft SQL Serveri",
+       "config-missing-db-name": "\"{{int:config-db-name}}\"nrë jew erc dekerdış gerek keno.",
+       "config-missing-db-host": "\"{{int:config-db-host}}\" rë jew erc gerek keno",
+       "config-missing-db-server-oracle": "\"{{int:config-db-host-oracle}}\" rë jew erc gerek keno",
+       "config-mysql-engine": "Motorë depok kerdışi",
        "config-mysql-innodb": "InnoDB",
        "config-mysql-myisam": "MyISAM",
        "config-mysql-binary": "Dılet",
        "config-mysql-utf8": "UTF-8",
+       "config-mssql-sqlauth": "SQL Server araştnayış",
+       "config-mssql-windowsauth": "Windows kamiye araştnayış",
        "config-site-name": "Namey wiki:",
        "config-site-name-blank": "Yew nameyê sita cıkewe.",
        "config-project-namespace": "Wareyê nameyê proceyi:",
index 29bbb71..a8bc219 100644 (file)
@@ -7,7 +7,8 @@
                        "Danmichaelo",
                        "Jeblad",
                        "Macofe",
-                       "SuperPotato"
+                       "SuperPotato",
+                       "Jon Harald Søby"
                ]
        },
        "config-desc": "Installasjonsprogrammet for MediaWiki",
@@ -55,7 +56,7 @@
        "config-env-hhvm": "HHVM $1 er installert.",
        "config-unicode-using-intl": "Bruker [http://pecl.php.net/intl intl PECL-utvidelsen] for Unicode-normalisering.",
        "config-unicode-pure-php-warning": "'''Advarsel''': [http://pecl.php.net/intl intl PECL-utvidelsen] er ikke tilgjengelig for å håndtere Unicode-normaliseringen, faller tilbake til en langsommere ren-PHP-implementasjon.\nOm du kjører et nettsted med høy trafikk bør du lese litt om [https://www.mediawiki.org/wiki/Special:MyLanguage/Unicode_normalization_considerations Unicode-normalisering].",
-       "config-unicode-update-warning": "'''Advarsel''': Den installerte versjonen av Unicode-normalisereren bruker en eldre versjon av [http://site.icu-project.org/ ICU-prosjektets] bibliotek.\nDu bør [https://www.mediawiki.org/wiki/Special:MyLanguage/Unicode_normalization_considerations oppgradere] om du er bekymret for å bruke Unicode.",
+       "config-unicode-update-warning": "<strong>Advarsel:</strong> Den installerte versjonen av Unicode-normalisereren bruker en eldre versjon av [http://site.icu-project.org/ ICU-prosjektets] bibliotek.\nDu bør [https://www.mediawiki.org/wiki/Special:MyLanguage/Unicode_normalization_considerations oppgradere] om du er bekymret for å bruke Unicode.",
        "config-no-db": "Fant ingen passende databasedriver! Du må installere en databasedriver for PHP.\nFølgende {{PLURAL:$2|databasetype|databasetyper}} støttes: $1\n\nOm du kompilerte PHP selv, rekonfigurer den med en aktivert databaseklient, for eksempel ved å bruke <code>./configure --with-mysql</code>.\nOm du installerte PHP fra en Debian- eller Ubuntu-pakke, må du også installere for eksempel <code>php5-mysql</code>-pakken.",
        "config-outdated-sqlite": "'''Advarsel''': Du har SQLite $1, som er en eldre versjon enn minimumskravet SQLite $2. SQLite vil ikke være tilgjengelig.",
        "config-no-fts3": "'''Advarsel''': SQLite er kompilert uten [//sqlite.org/fts3.html FTS3-modulen], søkefunksjoner vil ikke være tilgjengelig på dette bakstykket.",
        "config-ns-site-name": "Samme som wikinavnet: $1",
        "config-ns-other": "Annet (spesifiser)",
        "config-ns-other-default": "MyWiki",
-       "config-project-namespace-help": "Etter Wikipedias eksempel holder mange wikier deres sider med retningslinjer atskilt fra sine innholdssider, i et «'''prosjektnavnerom'''».\nAlle sidetitler i dette navnerommet starter med et gitt prefiks som du kan angi her.\nTradisjonelt er dette prefikset avledet fra navnet på wikien, men det kan ikke innholde punkttegn som «#» eller «:».",
+       "config-project-namespace-help": "Etter Wikipedias eksempel holder mange wikier deres sider med retningslinjer atskilt fra sine innholdssider, i et «'''prosjektnavnerom'''».\nAlle sidetitler i dette navnerommet starter med et gitt prefiks som du kan angi her.\nVanligvis er dette prefikset avledet fra navnet på wikien, men det kan ikke innholde punkttegn som «#» eller «:».",
        "config-ns-invalid": "Det angitte navnerommet «<nowiki>$1</nowiki>» er ugyldig.\nAngi et annet prosjektnavnerom.",
        "config-ns-conflict": "Det angitte navnerommet «<nowiki>$1</nowiki>» er i konflikt med et standard MediaWiki-navnerom.\nAngi et annet prosjekt-navnerom.",
        "config-admin-box": "Administratorkonto",
        "config-subscribe": "Abonner på [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce e-postlisten for utgivelsesannonseringer].",
        "config-subscribe-help": "Dette er en lav-volums e-postliste brukt til utgivelsesannonseringer, herunder viktige sikkerhetsannonseringer.\nDu bør abonnere på den og oppdatere MediaWikiinstallasjonen din når nye versjoner kommer ut.",
        "config-subscribe-noemail": "Du prøvde å abonnere på epost-meldinger om nye versjoner uten å oppgi en epost-adresse. Vær vennlig å oppgi en epost-adresse om du ønsker dette abonnementet.",
+       "config-pingback": "Del data om denne installasjonen med MediaWiki-utviklerne.",
+       "config-pingback-help": "Om du velger denne vil MediaWiki periodisk pinge https://www.mediawiki.org med grunnleggende data om denne MediaWiki-instansen. Disse dataene inkluderer for eksempel systemtypen, PHP-versjonen og hvilket databasebakstykke som er valgt. Wikimedia Foundation deler disse dataene med MediaWiki-utviklerne for å bestemme framtidige utviklingstiltak. Følgende data vil bli sendt for ditt system:\n<pre>$1</pre>",
        "config-almost-done": "Du er nesten ferdig!\nDu kan velge å hoppe over de siste konfigurasjonstrinnene og installere wikien med en gang.",
        "config-optional-continue": "Still meg flere spørsmål.",
        "config-optional-skip": "Jeg er lei, bare installer wikien.",
        "config-install-extension-tables": "Oppretter tabeller for aktiviserte utvidelser",
        "config-install-mainpage-failed": "Kunne ikke sette inn hovedside: $1",
        "config-install-done": "<strong>Gratulrerer!</strong>\nDu har lykkes i å installere MediaWiki.\n\nInstallasjonsprogrammet har generert en <code>LocalSettings.php</code>-fil.\nDen inneholder alle dine konfigureringer.\n\nDu må laste den ned og legge den på hovedfolderen for din wiki-installasjon (der index.php ligger). Nedlastingen skulle ha startet automatisk.\n\nHvis ingen nedlasting ble tilbudt, eller du avbrøt den, kan du få den i gang ved å klikke på lenken under:\n\n$3\n\n<strong>OBS:</strong> Hvis du ikke gjør dette nå, vil den genererte konfigurasjonsfilen ikke være tilgjengelig for deg senere.\n\nNår dette er gjort, kan du <strong>[$2 gå inn i wikien]</strong>.",
+       "config-install-done-path": "<strong>Gratulerer!</strong>\nDu har installert MediaWiki.\n\nInstallereren har generert en <code>LocalSettings.php</code>-fil.\nDen inneholder all konfigurasjonen for wikien.\n\nDu må laste den ned og legge den i <code>$4</code>. Nedlastingen skal ha startet automatisk.\n\nOm nedlastingen ikke ble startet, eller om du avbrøt den, kan du starte på nytt ved å klikke lenken nedenfor:\n\n$3\n\n<strong>Merk:</strong> Om du ikke gjør dette nå vil den genererte konfigurasjonen ikke være tilgjengelig senere.\n\nNår dette er gjort kan du <strong>[$2 gå til wikien din]</strong>.",
        "config-download-localsettings": "Last ned <code>LocalSettings.php</code>",
        "config-help": "hjelp",
        "config-help-tooltip": "klikk for å utvide",
        "config-nofile": "Filen \"$1\" ble ikke funnet. Kan den være blitt slettet?",
        "config-extension-link": "Visste du at wikien din kan brukes sammen med en mengde [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Extensions utvidelser]?\n\nDu kan sjekke gjennom [https://www.mediawiki.org/wiki/Special:MyLanguage/Category:Extensions_by_category utvidelser per kategori] eller [https://www.mediawiki.org/wiki/Extension_Matrix utvidelsesmatrisen] for å se den komplette listen av utvidelser.",
-       "mainpagetext": "'''MediaWiki-programvaren er nå installert.'''",
+       "mainpagetext": "<strong>MediaWiki har blitt installert.</strong>",
        "mainpagedocfooter": "Sjekk [https://meta.wikimedia.org/wiki/Help:Contents brukerveiledningen] for å få informasjon om hvordan du bruker wiki-programvaren.\n\n==Hvordan komme igang==\n*[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings Innstillingsliste]\n*[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ Ofte stilte spørsmål om MediaWiki]\n*[https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce MediaWiki e-postliste]\n*[https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation#Translation_resources Tilpass MediaWiki for ditt språk]\n*[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Combating_spam Lær deg å beskytte deg mot spam på wikien din]"
 }
index cbde5e4..25a271c 100644 (file)
@@ -254,6 +254,7 @@ class JobQueueRedis extends JobQueue {
                        $args[] = (string)$this->serialize( $item );
                }
                static $script =
+               /** @lang Lua */
 <<<LUA
                local kUnclaimed, kSha1ById, kIdBySha1, kDelayed, kData, kQwJobs = unpack(KEYS)
                -- First argument is the queue ID
@@ -343,6 +344,7 @@ LUA;
         */
        protected function popAndAcquireBlob( RedisConnRef $conn ) {
                static $script =
+               /** @lang Lua */
 <<<LUA
                local kUnclaimed, kSha1ById, kIdBySha1, kClaimed, kAttempts, kData = unpack(KEYS)
                local rTime = unpack(ARGV)
@@ -390,6 +392,7 @@ LUA;
                $conn = $this->getConnection();
                try {
                        static $script =
+                       /** @lang Lua */
 <<<LUA
                        local kClaimed, kAttempts, kData = unpack(KEYS)
                        local id = unpack(ARGV)
index 99184e1..8afdce4 100644 (file)
@@ -592,7 +592,7 @@ class FSFileBackend extends FileBackendStore {
         * @param string $fullCont
         * @param string $dirRel
         * @param array $params
-        * @return array|null
+        * @return array|FSFileBackendDirList|null
         */
        public function getDirectoryListInternal( $fullCont, $dirRel, array $params ) {
                list( , $shortCont, ) = FileBackend::splitStoragePath( $params['dir'] );
index aa25f43..0ef9f63 100644 (file)
@@ -185,7 +185,9 @@ abstract class FileBackend implements LoggerAwareInterface {
                $this->concurrency = isset( $config['concurrency'] )
                        ? (int)$config['concurrency']
                        : 50;
-               $this->obResetFunc = isset( $params['obResetFunc'] ) ? $params['obResetFunc'] : null;
+               $this->obResetFunc = isset( $params['obResetFunc'] )
+                       ? $params['obResetFunc']
+                       : [ $this, 'resetOutputBuffer' ];
                $this->streamMimeFunc = isset( $params['streamMimeFunc'] )
                        ? $params['streamMimeFunc']
                        : null;
@@ -1623,4 +1625,14 @@ abstract class FileBackend implements LoggerAwareInterface {
 
                return null;
        }
+
+       protected function resetOutputBuffer() {
+               while ( ob_get_status() ) {
+                       if ( !ob_end_clean() ) {
+                               // Could not remove output buffer handler; abort now
+                               // to avoid getting in some kind of infinite loop.
+                               break;
+                       }
+               }
+       }
 }
index 66f0737..b1b7652 100644 (file)
@@ -38,6 +38,8 @@
 abstract class FileBackendStore extends FileBackend {
        /** @var WANObjectCache */
        protected $memCache;
+       /** @var BagOStuff */
+       protected $srvCache;
        /** @var ProcessCacheLRU Map of paths to small (RAM/disk) cache items */
        protected $cheapCache;
        /** @var ProcessCacheLRU Map of paths to large (RAM/disk) cache items */
@@ -58,6 +60,7 @@ abstract class FileBackendStore extends FileBackend {
        /**
         * @see FileBackend::__construct()
         * Additional $config params include:
+        *   - srvCache     : BagOStuff cache to APC/XCache or the like.
         *   - wanCache     : WANObjectCache object to use for persistent caching.
         *   - mimeCallback : Callback that takes (storage path, content, file system path) and
         *                    returns the MIME type of the file or 'unknown/unknown'. The file
@@ -70,6 +73,7 @@ abstract class FileBackendStore extends FileBackend {
                $this->mimeCallback = isset( $config['mimeCallback'] )
                        ? $config['mimeCallback']
                        : null;
+               $this->srvCache = new EmptyBagOStuff(); // disabled by default
                $this->memCache = WANObjectCache::newEmpty(); // disabled by default
                $this->cheapCache = new ProcessCacheLRU( self::CACHE_CHEAP_SIZE );
                $this->expensiveCache = new ProcessCacheLRU( self::CACHE_EXPENSIVE_SIZE );
@@ -671,6 +675,7 @@ abstract class FileBackendStore extends FileBackend {
 
        /**
         * @see FileBackendStore::getFileStat()
+        * @param array $params
         */
        abstract protected function doGetFileStat( array $params );
 
@@ -723,6 +728,7 @@ abstract class FileBackendStore extends FileBackend {
 
        /**
         * @see FileBackendStore::getFileXAttributes()
+        * @param array $params
         * @return bool|string
         */
        protected function doGetFileXAttributes( array $params ) {
diff --git a/includes/libs/filebackend/SwiftFileBackend.php b/includes/libs/filebackend/SwiftFileBackend.php
new file mode 100644 (file)
index 0000000..4bc0ce6
--- /dev/null
@@ -0,0 +1,1937 @@
+<?php
+/**
+ * OpenStack Swift based file backend.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup FileBackend
+ * @author Russ Nelson
+ * @author Aaron Schulz
+ */
+
+/**
+ * @brief Class for an OpenStack Swift (or Ceph RGW) based file backend.
+ *
+ * StatusValue messages should avoid mentioning the Swift account name.
+ * Likewise, error suppression should be used to avoid path disclosure.
+ *
+ * @ingroup FileBackend
+ * @since 1.19
+ */
+class SwiftFileBackend extends FileBackendStore {
+       /** @var MultiHttpClient */
+       protected $http;
+
+       /** @var int TTL in seconds */
+       protected $authTTL;
+
+       /** @var string Authentication base URL (without version) */
+       protected $swiftAuthUrl;
+
+       /** @var string Swift user (account:user) to authenticate as */
+       protected $swiftUser;
+
+       /** @var string Secret key for user */
+       protected $swiftKey;
+
+       /** @var string Shared secret value for making temp URLs */
+       protected $swiftTempUrlKey;
+
+       /** @var string S3 access key (RADOS Gateway) */
+       protected $rgwS3AccessKey;
+
+       /** @var string S3 authentication key (RADOS Gateway) */
+       protected $rgwS3SecretKey;
+
+       /** @var BagOStuff */
+       protected $srvCache;
+
+       /** @var ProcessCacheLRU Container stat cache */
+       protected $containerStatCache;
+
+       /** @var array */
+       protected $authCreds;
+
+       /** @var int UNIX timestamp */
+       protected $authSessionTimestamp = 0;
+
+       /** @var int UNIX timestamp */
+       protected $authErrorTimestamp = null;
+
+       /** @var bool Whether the server is an Ceph RGW */
+       protected $isRGW = false;
+
+       /**
+        * @see FileBackendStore::__construct()
+        * Additional $config params include:
+        *   - swiftAuthUrl       : Swift authentication server URL
+        *   - swiftUser          : Swift user used by MediaWiki (account:username)
+        *   - swiftKey           : Swift authentication key for the above user
+        *   - swiftAuthTTL       : Swift authentication TTL (seconds)
+        *   - swiftTempUrlKey    : Swift "X-Account-Meta-Temp-URL-Key" value on the account.
+        *                          Do not set this until it has been set in the backend.
+        *   - shardViaHashLevels : Map of container names to sharding config with:
+        *                             - base   : base of hash characters, 16 or 36
+        *                             - levels : the number of hash levels (and digits)
+        *                             - repeat : hash subdirectories are prefixed with all the
+        *                                        parent hash directory names (e.g. "a/ab/abc")
+        *   - cacheAuthInfo      : Whether to cache authentication tokens in APC, XCache, ect.
+        *                          If those are not available, then the main cache will be used.
+        *                          This is probably insecure in shared hosting environments.
+        *   - rgwS3AccessKey     : Rados Gateway S3 "access key" value on the account.
+        *                          Do not set this until it has been set in the backend.
+        *                          This is used for generating expiring pre-authenticated URLs.
+        *                          Only use this when using rgw and to work around
+        *                          http://tracker.newdream.net/issues/3454.
+        *   - rgwS3SecretKey     : Rados Gateway S3 "secret key" value on the account.
+        *                          Do not set this until it has been set in the backend.
+        *                          This is used for generating expiring pre-authenticated URLs.
+        *                          Only use this when using rgw and to work around
+        *                          http://tracker.newdream.net/issues/3454.
+        */
+       public function __construct( array $config ) {
+               parent::__construct( $config );
+               // Required settings
+               $this->swiftAuthUrl = $config['swiftAuthUrl'];
+               $this->swiftUser = $config['swiftUser'];
+               $this->swiftKey = $config['swiftKey'];
+               // Optional settings
+               $this->authTTL = isset( $config['swiftAuthTTL'] )
+                       ? $config['swiftAuthTTL']
+                       : 15 * 60; // some sane number
+               $this->swiftTempUrlKey = isset( $config['swiftTempUrlKey'] )
+                       ? $config['swiftTempUrlKey']
+                       : '';
+               $this->shardViaHashLevels = isset( $config['shardViaHashLevels'] )
+                       ? $config['shardViaHashLevels']
+                       : '';
+               $this->rgwS3AccessKey = isset( $config['rgwS3AccessKey'] )
+                       ? $config['rgwS3AccessKey']
+                       : '';
+               $this->rgwS3SecretKey = isset( $config['rgwS3SecretKey'] )
+                       ? $config['rgwS3SecretKey']
+                       : '';
+               // HTTP helper client
+               $this->http = new MultiHttpClient( [] );
+               // Cache container information to mask latency
+               if ( isset( $config['wanCache'] ) && $config['wanCache'] instanceof WANObjectCache ) {
+                       $this->memCache = $config['wanCache'];
+               }
+               // Process cache for container info
+               $this->containerStatCache = new ProcessCacheLRU( 300 );
+               // Cache auth token information to avoid RTTs
+               if ( !empty( $config['cacheAuthInfo'] ) && isset( $config['srvCache'] ) ) {
+                       $this->srvCache = $config['srvCache'];
+               } else {
+                       $this->srvCache = new EmptyBagOStuff();
+               }
+       }
+
+       public function getFeatures() {
+               return ( FileBackend::ATTR_UNICODE_PATHS |
+                       FileBackend::ATTR_HEADERS | FileBackend::ATTR_METADATA );
+       }
+
+       protected function resolveContainerPath( $container, $relStoragePath ) {
+               if ( !mb_check_encoding( $relStoragePath, 'UTF-8' ) ) {
+                       return null; // not UTF-8, makes it hard to use CF and the swift HTTP API
+               } elseif ( strlen( urlencode( $relStoragePath ) ) > 1024 ) {
+                       return null; // too long for Swift
+               }
+
+               return $relStoragePath;
+       }
+
+       public function isPathUsableInternal( $storagePath ) {
+               list( $container, $rel ) = $this->resolveStoragePathReal( $storagePath );
+               if ( $rel === null ) {
+                       return false; // invalid
+               }
+
+               return is_array( $this->getContainerStat( $container ) );
+       }
+
+       /**
+        * Sanitize and filter the custom headers from a $params array.
+        * Only allows certain "standard" Content- and X-Content- headers.
+        *
+        * @param array $params
+        * @return array Sanitized value of 'headers' field in $params
+        */
+       protected function sanitizeHdrs( array $params ) {
+               return isset( $params['headers'] )
+                       ? $this->getCustomHeaders( $params['headers'] )
+                       : [];
+
+       }
+
+       /**
+        * @param array $rawHeaders
+        * @return array Custom non-metadata HTTP headers
+        */
+       protected function getCustomHeaders( array $rawHeaders ) {
+               $headers = [];
+
+               // Normalize casing, and strip out illegal headers
+               foreach ( $rawHeaders as $name => $value ) {
+                       $name = strtolower( $name );
+                       if ( preg_match( '/^content-(type|length)$/', $name ) ) {
+                               continue; // blacklisted
+                       } elseif ( preg_match( '/^(x-)?content-/', $name ) ) {
+                               $headers[$name] = $value; // allowed
+                       } elseif ( preg_match( '/^content-(disposition)/', $name ) ) {
+                               $headers[$name] = $value; // allowed
+                       }
+               }
+               // By default, Swift has annoyingly low maximum header value limits
+               if ( isset( $headers['content-disposition'] ) ) {
+                       $disposition = '';
+                       // @note: assume FileBackend::makeContentDisposition() already used
+                       foreach ( explode( ';', $headers['content-disposition'] ) as $part ) {
+                               $part = trim( $part );
+                               $new = ( $disposition === '' ) ? $part : "{$disposition};{$part}";
+                               if ( strlen( $new ) <= 255 ) {
+                                       $disposition = $new;
+                               } else {
+                                       break; // too long; sigh
+                               }
+                       }
+                       $headers['content-disposition'] = $disposition;
+               }
+
+               return $headers;
+       }
+
+       /**
+        * @param array $rawHeaders
+        * @return array Custom metadata headers
+        */
+       protected function getMetadataHeaders( array $rawHeaders ) {
+               $headers = [];
+               foreach ( $rawHeaders as $name => $value ) {
+                       $name = strtolower( $name );
+                       if ( strpos( $name, 'x-object-meta-' ) === 0 ) {
+                               $headers[$name] = $value;
+                       }
+               }
+
+               return $headers;
+       }
+
+       /**
+        * @param array $rawHeaders
+        * @return array Custom metadata headers with prefix removed
+        */
+       protected function getMetadata( array $rawHeaders ) {
+               $metadata = [];
+               foreach ( $this->getMetadataHeaders( $rawHeaders ) as $name => $value ) {
+                       $metadata[substr( $name, strlen( 'x-object-meta-' ) )] = $value;
+               }
+
+               return $metadata;
+       }
+
+       protected function doCreateInternal( array $params ) {
+               $status = $this->newStatus();
+
+               list( $dstCont, $dstRel ) = $this->resolveStoragePathReal( $params['dst'] );
+               if ( $dstRel === null ) {
+                       $status->fatal( 'backend-fail-invalidpath', $params['dst'] );
+
+                       return $status;
+               }
+
+               $sha1Hash = Wikimedia\base_convert( sha1( $params['content'] ), 16, 36, 31 );
+               $contentType = isset( $params['headers']['content-type'] )
+                       ? $params['headers']['content-type']
+                       : $this->getContentType( $params['dst'], $params['content'], null );
+
+               $reqs = [ [
+                       'method' => 'PUT',
+                       'url' => [ $dstCont, $dstRel ],
+                       'headers' => [
+                               'content-length' => strlen( $params['content'] ),
+                               'etag' => md5( $params['content'] ),
+                               'content-type' => $contentType,
+                               'x-object-meta-sha1base36' => $sha1Hash
+                       ] + $this->sanitizeHdrs( $params ),
+                       'body' => $params['content']
+               ] ];
+
+               $method = __METHOD__;
+               $handler = function ( array $request, StatusValue $status ) use ( $method, $params ) {
+                       list( $rcode, $rdesc, $rhdrs, $rbody, $rerr ) = $request['response'];
+                       if ( $rcode === 201 ) {
+                               // good
+                       } elseif ( $rcode === 412 ) {
+                               $status->fatal( 'backend-fail-contenttype', $params['dst'] );
+                       } else {
+                               $this->onError( $status, $method, $params, $rerr, $rcode, $rdesc );
+                       }
+               };
+
+               $opHandle = new SwiftFileOpHandle( $this, $handler, $reqs );
+               if ( !empty( $params['async'] ) ) { // deferred
+                       $status->value = $opHandle;
+               } else { // actually write the object in Swift
+                       $status->merge( current( $this->doExecuteOpHandlesInternal( [ $opHandle ] ) ) );
+               }
+
+               return $status;
+       }
+
+       protected function doStoreInternal( array $params ) {
+               $status = $this->newStatus();
+
+               list( $dstCont, $dstRel ) = $this->resolveStoragePathReal( $params['dst'] );
+               if ( $dstRel === null ) {
+                       $status->fatal( 'backend-fail-invalidpath', $params['dst'] );
+
+                       return $status;
+               }
+
+               MediaWiki\suppressWarnings();
+               $sha1Hash = sha1_file( $params['src'] );
+               MediaWiki\restoreWarnings();
+               if ( $sha1Hash === false ) { // source doesn't exist?
+                       $status->fatal( 'backend-fail-store', $params['src'], $params['dst'] );
+
+                       return $status;
+               }
+               $sha1Hash = Wikimedia\base_convert( $sha1Hash, 16, 36, 31 );
+               $contentType = isset( $params['headers']['content-type'] )
+                       ? $params['headers']['content-type']
+                       : $this->getContentType( $params['dst'], null, $params['src'] );
+
+               $handle = fopen( $params['src'], 'rb' );
+               if ( $handle === false ) { // source doesn't exist?
+                       $status->fatal( 'backend-fail-store', $params['src'], $params['dst'] );
+
+                       return $status;
+               }
+
+               $reqs = [ [
+                       'method' => 'PUT',
+                       'url' => [ $dstCont, $dstRel ],
+                       'headers' => [
+                               'content-length' => filesize( $params['src'] ),
+                               'etag' => md5_file( $params['src'] ),
+                               'content-type' => $contentType,
+                               'x-object-meta-sha1base36' => $sha1Hash
+                       ] + $this->sanitizeHdrs( $params ),
+                       'body' => $handle // resource
+               ] ];
+
+               $method = __METHOD__;
+               $handler = function ( array $request, StatusValue $status ) use ( $method, $params ) {
+                       list( $rcode, $rdesc, $rhdrs, $rbody, $rerr ) = $request['response'];
+                       if ( $rcode === 201 ) {
+                               // good
+                       } elseif ( $rcode === 412 ) {
+                               $status->fatal( 'backend-fail-contenttype', $params['dst'] );
+                       } else {
+                               $this->onError( $status, $method, $params, $rerr, $rcode, $rdesc );
+                       }
+               };
+
+               $opHandle = new SwiftFileOpHandle( $this, $handler, $reqs );
+               if ( !empty( $params['async'] ) ) { // deferred
+                       $status->value = $opHandle;
+               } else { // actually write the object in Swift
+                       $status->merge( current( $this->doExecuteOpHandlesInternal( [ $opHandle ] ) ) );
+               }
+
+               return $status;
+       }
+
+       protected function doCopyInternal( array $params ) {
+               $status = $this->newStatus();
+
+               list( $srcCont, $srcRel ) = $this->resolveStoragePathReal( $params['src'] );
+               if ( $srcRel === null ) {
+                       $status->fatal( 'backend-fail-invalidpath', $params['src'] );
+
+                       return $status;
+               }
+
+               list( $dstCont, $dstRel ) = $this->resolveStoragePathReal( $params['dst'] );
+               if ( $dstRel === null ) {
+                       $status->fatal( 'backend-fail-invalidpath', $params['dst'] );
+
+                       return $status;
+               }
+
+               $reqs = [ [
+                       'method' => 'PUT',
+                       'url' => [ $dstCont, $dstRel ],
+                       'headers' => [
+                               'x-copy-from' => '/' . rawurlencode( $srcCont ) .
+                                       '/' . str_replace( "%2F", "/", rawurlencode( $srcRel ) )
+                       ] + $this->sanitizeHdrs( $params ), // extra headers merged into object
+               ] ];
+
+               $method = __METHOD__;
+               $handler = function ( array $request, StatusValue $status ) use ( $method, $params ) {
+                       list( $rcode, $rdesc, $rhdrs, $rbody, $rerr ) = $request['response'];
+                       if ( $rcode === 201 ) {
+                               // good
+                       } elseif ( $rcode === 404 ) {
+                               $status->fatal( 'backend-fail-copy', $params['src'], $params['dst'] );
+                       } else {
+                               $this->onError( $status, $method, $params, $rerr, $rcode, $rdesc );
+                       }
+               };
+
+               $opHandle = new SwiftFileOpHandle( $this, $handler, $reqs );
+               if ( !empty( $params['async'] ) ) { // deferred
+                       $status->value = $opHandle;
+               } else { // actually write the object in Swift
+                       $status->merge( current( $this->doExecuteOpHandlesInternal( [ $opHandle ] ) ) );
+               }
+
+               return $status;
+       }
+
+       protected function doMoveInternal( array $params ) {
+               $status = $this->newStatus();
+
+               list( $srcCont, $srcRel ) = $this->resolveStoragePathReal( $params['src'] );
+               if ( $srcRel === null ) {
+                       $status->fatal( 'backend-fail-invalidpath', $params['src'] );
+
+                       return $status;
+               }
+
+               list( $dstCont, $dstRel ) = $this->resolveStoragePathReal( $params['dst'] );
+               if ( $dstRel === null ) {
+                       $status->fatal( 'backend-fail-invalidpath', $params['dst'] );
+
+                       return $status;
+               }
+
+               $reqs = [
+                       [
+                               'method' => 'PUT',
+                               'url' => [ $dstCont, $dstRel ],
+                               'headers' => [
+                                       'x-copy-from' => '/' . rawurlencode( $srcCont ) .
+                                               '/' . str_replace( "%2F", "/", rawurlencode( $srcRel ) )
+                               ] + $this->sanitizeHdrs( $params ) // extra headers merged into object
+                       ]
+               ];
+               if ( "{$srcCont}/{$srcRel}" !== "{$dstCont}/{$dstRel}" ) {
+                       $reqs[] = [
+                               'method' => 'DELETE',
+                               'url' => [ $srcCont, $srcRel ],
+                               'headers' => []
+                       ];
+               }
+
+               $method = __METHOD__;
+               $handler = function ( array $request, StatusValue $status ) use ( $method, $params ) {
+                       list( $rcode, $rdesc, $rhdrs, $rbody, $rerr ) = $request['response'];
+                       if ( $request['method'] === 'PUT' && $rcode === 201 ) {
+                               // good
+                       } elseif ( $request['method'] === 'DELETE' && $rcode === 204 ) {
+                               // good
+                       } elseif ( $rcode === 404 ) {
+                               $status->fatal( 'backend-fail-move', $params['src'], $params['dst'] );
+                       } else {
+                               $this->onError( $status, $method, $params, $rerr, $rcode, $rdesc );
+                       }
+               };
+
+               $opHandle = new SwiftFileOpHandle( $this, $handler, $reqs );
+               if ( !empty( $params['async'] ) ) { // deferred
+                       $status->value = $opHandle;
+               } else { // actually move the object in Swift
+                       $status->merge( current( $this->doExecuteOpHandlesInternal( [ $opHandle ] ) ) );
+               }
+
+               return $status;
+       }
+
+       protected function doDeleteInternal( array $params ) {
+               $status = $this->newStatus();
+
+               list( $srcCont, $srcRel ) = $this->resolveStoragePathReal( $params['src'] );
+               if ( $srcRel === null ) {
+                       $status->fatal( 'backend-fail-invalidpath', $params['src'] );
+
+                       return $status;
+               }
+
+               $reqs = [ [
+                       'method' => 'DELETE',
+                       'url' => [ $srcCont, $srcRel ],
+                       'headers' => []
+               ] ];
+
+               $method = __METHOD__;
+               $handler = function ( array $request, StatusValue $status ) use ( $method, $params ) {
+                       list( $rcode, $rdesc, $rhdrs, $rbody, $rerr ) = $request['response'];
+                       if ( $rcode === 204 ) {
+                               // good
+                       } elseif ( $rcode === 404 ) {
+                               if ( empty( $params['ignoreMissingSource'] ) ) {
+                                       $status->fatal( 'backend-fail-delete', $params['src'] );
+                               }
+                       } else {
+                               $this->onError( $status, $method, $params, $rerr, $rcode, $rdesc );
+                       }
+               };
+
+               $opHandle = new SwiftFileOpHandle( $this, $handler, $reqs );
+               if ( !empty( $params['async'] ) ) { // deferred
+                       $status->value = $opHandle;
+               } else { // actually delete the object in Swift
+                       $status->merge( current( $this->doExecuteOpHandlesInternal( [ $opHandle ] ) ) );
+               }
+
+               return $status;
+       }
+
+       protected function doDescribeInternal( array $params ) {
+               $status = $this->newStatus();
+
+               list( $srcCont, $srcRel ) = $this->resolveStoragePathReal( $params['src'] );
+               if ( $srcRel === null ) {
+                       $status->fatal( 'backend-fail-invalidpath', $params['src'] );
+
+                       return $status;
+               }
+
+               // Fetch the old object headers/metadata...this should be in stat cache by now
+               $stat = $this->getFileStat( [ 'src' => $params['src'], 'latest' => 1 ] );
+               if ( $stat && !isset( $stat['xattr'] ) ) { // older cache entry
+                       $stat = $this->doGetFileStat( [ 'src' => $params['src'], 'latest' => 1 ] );
+               }
+               if ( !$stat ) {
+                       $status->fatal( 'backend-fail-describe', $params['src'] );
+
+                       return $status;
+               }
+
+               // POST clears prior headers, so we need to merge the changes in to the old ones
+               $metaHdrs = [];
+               foreach ( $stat['xattr']['metadata'] as $name => $value ) {
+                       $metaHdrs["x-object-meta-$name"] = $value;
+               }
+               $customHdrs = $this->sanitizeHdrs( $params ) + $stat['xattr']['headers'];
+
+               $reqs = [ [
+                       'method' => 'POST',
+                       'url' => [ $srcCont, $srcRel ],
+                       'headers' => $metaHdrs + $customHdrs
+               ] ];
+
+               $method = __METHOD__;
+               $handler = function ( array $request, StatusValue $status ) use ( $method, $params ) {
+                       list( $rcode, $rdesc, $rhdrs, $rbody, $rerr ) = $request['response'];
+                       if ( $rcode === 202 ) {
+                               // good
+                       } elseif ( $rcode === 404 ) {
+                               $status->fatal( 'backend-fail-describe', $params['src'] );
+                       } else {
+                               $this->onError( $status, $method, $params, $rerr, $rcode, $rdesc );
+                       }
+               };
+
+               $opHandle = new SwiftFileOpHandle( $this, $handler, $reqs );
+               if ( !empty( $params['async'] ) ) { // deferred
+                       $status->value = $opHandle;
+               } else { // actually change the object in Swift
+                       $status->merge( current( $this->doExecuteOpHandlesInternal( [ $opHandle ] ) ) );
+               }
+
+               return $status;
+       }
+
+       protected function doPrepareInternal( $fullCont, $dir, array $params ) {
+               $status = $this->newStatus();
+
+               // (a) Check if container already exists
+               $stat = $this->getContainerStat( $fullCont );
+               if ( is_array( $stat ) ) {
+                       return $status; // already there
+               } elseif ( $stat === null ) {
+                       $status->fatal( 'backend-fail-internal', $this->name );
+                       $this->logger->error( __METHOD__ . ': cannot get container stat' );
+
+                       return $status;
+               }
+
+               // (b) Create container as needed with proper ACLs
+               if ( $stat === false ) {
+                       $params['op'] = 'prepare';
+                       $status->merge( $this->createContainer( $fullCont, $params ) );
+               }
+
+               return $status;
+       }
+
+       protected function doSecureInternal( $fullCont, $dir, array $params ) {
+               $status = $this->newStatus();
+               if ( empty( $params['noAccess'] ) ) {
+                       return $status; // nothing to do
+               }
+
+               $stat = $this->getContainerStat( $fullCont );
+               if ( is_array( $stat ) ) {
+                       // Make container private to end-users...
+                       $status->merge( $this->setContainerAccess(
+                               $fullCont,
+                               [ $this->swiftUser ], // read
+                               [ $this->swiftUser ] // write
+                       ) );
+               } elseif ( $stat === false ) {
+                       $status->fatal( 'backend-fail-usable', $params['dir'] );
+               } else {
+                       $status->fatal( 'backend-fail-internal', $this->name );
+                       $this->logger->error( __METHOD__ . ': cannot get container stat' );
+               }
+
+               return $status;
+       }
+
+       protected function doPublishInternal( $fullCont, $dir, array $params ) {
+               $status = $this->newStatus();
+
+               $stat = $this->getContainerStat( $fullCont );
+               if ( is_array( $stat ) ) {
+                       // Make container public to end-users...
+                       $status->merge( $this->setContainerAccess(
+                               $fullCont,
+                               [ $this->swiftUser, '.r:*' ], // read
+                               [ $this->swiftUser ] // write
+                       ) );
+               } elseif ( $stat === false ) {
+                       $status->fatal( 'backend-fail-usable', $params['dir'] );
+               } else {
+                       $status->fatal( 'backend-fail-internal', $this->name );
+                       $this->logger->error( __METHOD__ . ': cannot get container stat' );
+               }
+
+               return $status;
+       }
+
+       protected function doCleanInternal( $fullCont, $dir, array $params ) {
+               $status = $this->newStatus();
+
+               // Only containers themselves can be removed, all else is virtual
+               if ( $dir != '' ) {
+                       return $status; // nothing to do
+               }
+
+               // (a) Check the container
+               $stat = $this->getContainerStat( $fullCont, true );
+               if ( $stat === false ) {
+                       return $status; // ok, nothing to do
+               } elseif ( !is_array( $stat ) ) {
+                       $status->fatal( 'backend-fail-internal', $this->name );
+                       $this->logger->error( __METHOD__ . ': cannot get container stat' );
+
+                       return $status;
+               }
+
+               // (b) Delete the container if empty
+               if ( $stat['count'] == 0 ) {
+                       $params['op'] = 'clean';
+                       $status->merge( $this->deleteContainer( $fullCont, $params ) );
+               }
+
+               return $status;
+       }
+
+       protected function doGetFileStat( array $params ) {
+               $params = [ 'srcs' => [ $params['src'] ], 'concurrency' => 1 ] + $params;
+               unset( $params['src'] );
+               $stats = $this->doGetFileStatMulti( $params );
+
+               return reset( $stats );
+       }
+
+       /**
+        * Convert dates like "Tue, 03 Jan 2012 22:01:04 GMT"/"2013-05-11T07:37:27.678360Z".
+        * Dates might also come in like "2013-05-11T07:37:27.678360" from Swift listings,
+        * missing the timezone suffix (though Ceph RGW does not appear to have this bug).
+        *
+        * @param string $ts
+        * @param int $format Output format (TS_* constant)
+        * @return string
+        * @throws FileBackendError
+        */
+       protected function convertSwiftDate( $ts, $format = TS_MW ) {
+               try {
+                       $timestamp = new MWTimestamp( $ts );
+
+                       return $timestamp->getTimestamp( $format );
+               } catch ( Exception $e ) {
+                       throw new FileBackendError( $e->getMessage() );
+               }
+       }
+
+       /**
+        * Fill in any missing object metadata and save it to Swift
+        *
+        * @param array $objHdrs Object response headers
+        * @param string $path Storage path to object
+        * @return array New headers
+        */
+       protected function addMissingMetadata( array $objHdrs, $path ) {
+               if ( isset( $objHdrs['x-object-meta-sha1base36'] ) ) {
+                       return $objHdrs; // nothing to do
+               }
+
+               /** @noinspection PhpUnusedLocalVariableInspection */
+               $ps = $this->scopedProfileSection( __METHOD__ . "-{$this->name}" );
+               $this->logger->error( __METHOD__ . ": $path was not stored with SHA-1 metadata." );
+
+               $objHdrs['x-object-meta-sha1base36'] = false;
+
+               $auth = $this->getAuthentication();
+               if ( !$auth ) {
+                       return $objHdrs; // failed
+               }
+
+               // Find prior custom HTTP headers
+               $postHeaders = $this->getCustomHeaders( $objHdrs );
+               // Find prior metadata headers
+               $postHeaders += $this->getMetadataHeaders( $objHdrs );
+
+               $status = $this->newStatus();
+               /** @noinspection PhpUnusedLocalVariableInspection */
+               $scopeLockS = $this->getScopedFileLocks( [ $path ], LockManager::LOCK_UW, $status );
+               if ( $status->isOK() ) {
+                       $tmpFile = $this->getLocalCopy( [ 'src' => $path, 'latest' => 1 ] );
+                       if ( $tmpFile ) {
+                               $hash = $tmpFile->getSha1Base36();
+                               if ( $hash !== false ) {
+                                       $objHdrs['x-object-meta-sha1base36'] = $hash;
+                                       // Merge new SHA1 header into the old ones
+                                       $postHeaders['x-object-meta-sha1base36'] = $hash;
+                                       list( $srcCont, $srcRel ) = $this->resolveStoragePathReal( $path );
+                                       list( $rcode ) = $this->http->run( [
+                                               'method' => 'POST',
+                                               'url' => $this->storageUrl( $auth, $srcCont, $srcRel ),
+                                               'headers' => $this->authTokenHeaders( $auth ) + $postHeaders
+                                       ] );
+                                       if ( $rcode >= 200 && $rcode <= 299 ) {
+                                               $this->deleteFileCache( $path );
+
+                                               return $objHdrs; // success
+                                       }
+                               }
+                       }
+               }
+
+               $this->logger->error( __METHOD__ . ": unable to set SHA-1 metadata for $path" );
+
+               return $objHdrs; // failed
+       }
+
+       protected function doGetFileContentsMulti( array $params ) {
+               $contents = [];
+
+               $auth = $this->getAuthentication();
+
+               $ep = array_diff_key( $params, [ 'srcs' => 1 ] ); // for error logging
+               // Blindly create tmp files and stream to them, catching any exception if the file does
+               // not exist. Doing stats here is useless and will loop infinitely in addMissingMetadata().
+               $reqs = []; // (path => op)
+
+               foreach ( $params['srcs'] as $path ) { // each path in this concurrent batch
+                       list( $srcCont, $srcRel ) = $this->resolveStoragePathReal( $path );
+                       if ( $srcRel === null || !$auth ) {
+                               $contents[$path] = false;
+                               continue;
+                       }
+                       // Create a new temporary memory file...
+                       $handle = fopen( 'php://temp', 'wb' );
+                       if ( $handle ) {
+                               $reqs[$path] = [
+                                       'method'  => 'GET',
+                                       'url'     => $this->storageUrl( $auth, $srcCont, $srcRel ),
+                                       'headers' => $this->authTokenHeaders( $auth )
+                                               + $this->headersFromParams( $params ),
+                                       'stream'  => $handle,
+                               ];
+                       }
+                       $contents[$path] = false;
+               }
+
+               $opts = [ 'maxConnsPerHost' => $params['concurrency'] ];
+               $reqs = $this->http->runMulti( $reqs, $opts );
+               foreach ( $reqs as $path => $op ) {
+                       list( $rcode, $rdesc, $rhdrs, $rbody, $rerr ) = $op['response'];
+                       if ( $rcode >= 200 && $rcode <= 299 ) {
+                               rewind( $op['stream'] ); // start from the beginning
+                               $contents[$path] = stream_get_contents( $op['stream'] );
+                       } elseif ( $rcode === 404 ) {
+                               $contents[$path] = false;
+                       } else {
+                               $this->onError( null, __METHOD__,
+                                       [ 'src' => $path ] + $ep, $rerr, $rcode, $rdesc );
+                       }
+                       fclose( $op['stream'] ); // close open handle
+               }
+
+               return $contents;
+       }
+
+       protected function doDirectoryExists( $fullCont, $dir, array $params ) {
+               $prefix = ( $dir == '' ) ? null : "{$dir}/";
+               $status = $this->objectListing( $fullCont, 'names', 1, null, $prefix );
+               if ( $status->isOK() ) {
+                       return ( count( $status->value ) ) > 0;
+               }
+
+               return null; // error
+       }
+
+       /**
+        * @see FileBackendStore::getDirectoryListInternal()
+        * @param string $fullCont
+        * @param string $dir
+        * @param array $params
+        * @return SwiftFileBackendDirList
+        */
+       public function getDirectoryListInternal( $fullCont, $dir, array $params ) {
+               return new SwiftFileBackendDirList( $this, $fullCont, $dir, $params );
+       }
+
+       /**
+        * @see FileBackendStore::getFileListInternal()
+        * @param string $fullCont
+        * @param string $dir
+        * @param array $params
+        * @return SwiftFileBackendFileList
+        */
+       public function getFileListInternal( $fullCont, $dir, array $params ) {
+               return new SwiftFileBackendFileList( $this, $fullCont, $dir, $params );
+       }
+
+       /**
+        * Do not call this function outside of SwiftFileBackendFileList
+        *
+        * @param string $fullCont Resolved container name
+        * @param string $dir Resolved storage directory with no trailing slash
+        * @param string|null $after Resolved container relative path to list items after
+        * @param int $limit Max number of items to list
+        * @param array $params Parameters for getDirectoryList()
+        * @return array List of container relative resolved paths of directories directly under $dir
+        * @throws FileBackendError
+        */
+       public function getDirListPageInternal( $fullCont, $dir, &$after, $limit, array $params ) {
+               $dirs = [];
+               if ( $after === INF ) {
+                       return $dirs; // nothing more
+               }
+
+               $ps = $this->scopedProfileSection( __METHOD__ . "-{$this->name}" );
+
+               $prefix = ( $dir == '' ) ? null : "{$dir}/";
+               // Non-recursive: only list dirs right under $dir
+               if ( !empty( $params['topOnly'] ) ) {
+                       $status = $this->objectListing( $fullCont, 'names', $limit, $after, $prefix, '/' );
+                       if ( !$status->isOK() ) {
+                               throw new FileBackendError( "Iterator page I/O error." );
+                       }
+                       $objects = $status->value;
+                       foreach ( $objects as $object ) { // files and directories
+                               if ( substr( $object, -1 ) === '/' ) {
+                                       $dirs[] = $object; // directories end in '/'
+                               }
+                       }
+               } else {
+                       // Recursive: list all dirs under $dir and its subdirs
+                       $getParentDir = function ( $path ) {
+                               return ( strpos( $path, '/' ) !== false ) ? dirname( $path ) : false;
+                       };
+
+                       // Get directory from last item of prior page
+                       $lastDir = $getParentDir( $after ); // must be first page
+                       $status = $this->objectListing( $fullCont, 'names', $limit, $after, $prefix );
+
+                       if ( !$status->isOK() ) {
+                               throw new FileBackendError( "Iterator page I/O error." );
+                       }
+
+                       $objects = $status->value;
+
+                       foreach ( $objects as $object ) { // files
+                               $objectDir = $getParentDir( $object ); // directory of object
+
+                               if ( $objectDir !== false && $objectDir !== $dir ) {
+                                       // Swift stores paths in UTF-8, using binary sorting.
+                                       // See function "create_container_table" in common/db.py.
+                                       // If a directory is not "greater" than the last one,
+                                       // then it was already listed by the calling iterator.
+                                       if ( strcmp( $objectDir, $lastDir ) > 0 ) {
+                                               $pDir = $objectDir;
+                                               do { // add dir and all its parent dirs
+                                                       $dirs[] = "{$pDir}/";
+                                                       $pDir = $getParentDir( $pDir );
+                                               } while ( $pDir !== false // sanity
+                                                       && strcmp( $pDir, $lastDir ) > 0 // not done already
+                                                       && strlen( $pDir ) > strlen( $dir ) // within $dir
+                                               );
+                                       }
+                                       $lastDir = $objectDir;
+                               }
+                       }
+               }
+               // Page on the unfiltered directory listing (what is returned may be filtered)
+               if ( count( $objects ) < $limit ) {
+                       $after = INF; // avoid a second RTT
+               } else {
+                       $after = end( $objects ); // update last item
+               }
+
+               return $dirs;
+       }
+
+       /**
+        * Do not call this function outside of SwiftFileBackendFileList
+        *
+        * @param string $fullCont Resolved container name
+        * @param string $dir Resolved storage directory with no trailing slash
+        * @param string|null $after Resolved container relative path of file to list items after
+        * @param int $limit Max number of items to list
+        * @param array $params Parameters for getDirectoryList()
+        * @return array List of resolved container relative paths of files under $dir
+        * @throws FileBackendError
+        */
+       public function getFileListPageInternal( $fullCont, $dir, &$after, $limit, array $params ) {
+               $files = []; // list of (path, stat array or null) entries
+               if ( $after === INF ) {
+                       return $files; // nothing more
+               }
+
+               $ps = $this->scopedProfileSection( __METHOD__ . "-{$this->name}" );
+
+               $prefix = ( $dir == '' ) ? null : "{$dir}/";
+               // $objects will contain a list of unfiltered names or CF_Object items
+               // Non-recursive: only list files right under $dir
+               if ( !empty( $params['topOnly'] ) ) {
+                       if ( !empty( $params['adviseStat'] ) ) {
+                               $status = $this->objectListing( $fullCont, 'info', $limit, $after, $prefix, '/' );
+                       } else {
+                               $status = $this->objectListing( $fullCont, 'names', $limit, $after, $prefix, '/' );
+                       }
+               } else {
+                       // Recursive: list all files under $dir and its subdirs
+                       if ( !empty( $params['adviseStat'] ) ) {
+                               $status = $this->objectListing( $fullCont, 'info', $limit, $after, $prefix );
+                       } else {
+                               $status = $this->objectListing( $fullCont, 'names', $limit, $after, $prefix );
+                       }
+               }
+
+               // Reformat this list into a list of (name, stat array or null) entries
+               if ( !$status->isOK() ) {
+                       throw new FileBackendError( "Iterator page I/O error." );
+               }
+
+               $objects = $status->value;
+               $files = $this->buildFileObjectListing( $params, $dir, $objects );
+
+               // Page on the unfiltered object listing (what is returned may be filtered)
+               if ( count( $objects ) < $limit ) {
+                       $after = INF; // avoid a second RTT
+               } else {
+                       $after = end( $objects ); // update last item
+                       $after = is_object( $after ) ? $after->name : $after;
+               }
+
+               return $files;
+       }
+
+       /**
+        * Build a list of file objects, filtering out any directories
+        * and extracting any stat info if provided in $objects (for CF_Objects)
+        *
+        * @param array $params Parameters for getDirectoryList()
+        * @param string $dir Resolved container directory path
+        * @param array $objects List of CF_Object items or object names
+        * @return array List of (names,stat array or null) entries
+        */
+       private function buildFileObjectListing( array $params, $dir, array $objects ) {
+               $names = [];
+               foreach ( $objects as $object ) {
+                       if ( is_object( $object ) ) {
+                               if ( isset( $object->subdir ) || !isset( $object->name ) ) {
+                                       continue; // virtual directory entry; ignore
+                               }
+                               $stat = [
+                                       // Convert various random Swift dates to TS_MW
+                                       'mtime'  => $this->convertSwiftDate( $object->last_modified, TS_MW ),
+                                       'size'   => (int)$object->bytes,
+                                       'sha1'   => null,
+                                       // Note: manifiest ETags are not an MD5 of the file
+                                       'md5'    => ctype_xdigit( $object->hash ) ? $object->hash : null,
+                                       'latest' => false // eventually consistent
+                               ];
+                               $names[] = [ $object->name, $stat ];
+                       } elseif ( substr( $object, -1 ) !== '/' ) {
+                               // Omit directories, which end in '/' in listings
+                               $names[] = [ $object, null ];
+                       }
+               }
+
+               return $names;
+       }
+
+       /**
+        * Do not call this function outside of SwiftFileBackendFileList
+        *
+        * @param string $path Storage path
+        * @param array $val Stat value
+        */
+       public function loadListingStatInternal( $path, array $val ) {
+               $this->cheapCache->set( $path, 'stat', $val );
+       }
+
+       protected function doGetFileXAttributes( array $params ) {
+               $stat = $this->getFileStat( $params );
+               if ( $stat ) {
+                       if ( !isset( $stat['xattr'] ) ) {
+                               // Stat entries filled by file listings don't include metadata/headers
+                               $this->clearCache( [ $params['src'] ] );
+                               $stat = $this->getFileStat( $params );
+                       }
+
+                       return $stat['xattr'];
+               } else {
+                       return false;
+               }
+       }
+
+       protected function doGetFileSha1base36( array $params ) {
+               $stat = $this->getFileStat( $params );
+               if ( $stat ) {
+                       if ( !isset( $stat['sha1'] ) ) {
+                               // Stat entries filled by file listings don't include SHA1
+                               $this->clearCache( [ $params['src'] ] );
+                               $stat = $this->getFileStat( $params );
+                       }
+
+                       return $stat['sha1'];
+               } else {
+                       return false;
+               }
+       }
+
+       protected function doStreamFile( array $params ) {
+               $status = $this->newStatus();
+
+               $flags = !empty( $params['headless'] ) ? StreamFile::STREAM_HEADLESS : 0;
+
+               list( $srcCont, $srcRel ) = $this->resolveStoragePathReal( $params['src'] );
+               if ( $srcRel === null ) {
+                       StreamFile::send404Message( $params['src'], $flags );
+                       $status->fatal( 'backend-fail-invalidpath', $params['src'] );
+
+                       return $status;
+               }
+
+               $auth = $this->getAuthentication();
+               if ( !$auth || !is_array( $this->getContainerStat( $srcCont ) ) ) {
+                       StreamFile::send404Message( $params['src'], $flags );
+                       $status->fatal( 'backend-fail-stream', $params['src'] );
+
+                       return $status;
+               }
+
+               // If "headers" is set, we only want to send them if the file is there.
+               // Do not bother checking if the file exists if headers are not set though.
+               if ( $params['headers'] && !$this->fileExists( $params ) ) {
+                       StreamFile::send404Message( $params['src'], $flags );
+                       $status->fatal( 'backend-fail-stream', $params['src'] );
+
+                       return $status;
+               }
+
+               // Send the requested additional headers
+               foreach ( $params['headers'] as $header ) {
+                       header( $header ); // aways send
+               }
+
+               if ( empty( $params['allowOB'] ) ) {
+                       // Cancel output buffering and gzipping if set
+                       call_user_func( $this->obResetFunc );
+               }
+
+               $handle = fopen( 'php://output', 'wb' );
+               list( $rcode, $rdesc, $rhdrs, $rbody, $rerr ) = $this->http->run( [
+                       'method' => 'GET',
+                       'url' => $this->storageUrl( $auth, $srcCont, $srcRel ),
+                       'headers' => $this->authTokenHeaders( $auth )
+                               + $this->headersFromParams( $params ) + $params['options'],
+                       'stream' => $handle,
+                       'flags'  => [ 'relayResponseHeaders' => empty( $params['headless'] ) ]
+               ] );
+
+               if ( $rcode >= 200 && $rcode <= 299 ) {
+                       // good
+               } elseif ( $rcode === 404 ) {
+                       $status->fatal( 'backend-fail-stream', $params['src'] );
+                       // Per bug 41113, nasty things can happen if bad cache entries get
+                       // stuck in cache. It's also possible that this error can come up
+                       // with simple race conditions. Clear out the stat cache to be safe.
+                       $this->clearCache( [ $params['src'] ] );
+                       $this->deleteFileCache( $params['src'] );
+               } else {
+                       $this->onError( $status, __METHOD__, $params, $rerr, $rcode, $rdesc );
+               }
+
+               return $status;
+       }
+
+       protected function doGetLocalCopyMulti( array $params ) {
+               /** @var TempFSFile[] $tmpFiles */
+               $tmpFiles = [];
+
+               $auth = $this->getAuthentication();
+
+               $ep = array_diff_key( $params, [ 'srcs' => 1 ] ); // for error logging
+               // Blindly create tmp files and stream to them, catching any exception if the file does
+               // not exist. Doing a stat here is useless causes infinite loops in addMissingMetadata().
+               $reqs = []; // (path => op)
+
+               foreach ( $params['srcs'] as $path ) { // each path in this concurrent batch
+                       list( $srcCont, $srcRel ) = $this->resolveStoragePathReal( $path );
+                       if ( $srcRel === null || !$auth ) {
+                               $tmpFiles[$path] = null;
+                               continue;
+                       }
+                       // Get source file extension
+                       $ext = FileBackend::extensionFromPath( $path );
+                       // Create a new temporary file...
+                       $tmpFile = TempFSFile::factory( 'localcopy_', $ext, $this->tmpDirectory );
+                       if ( $tmpFile ) {
+                               $handle = fopen( $tmpFile->getPath(), 'wb' );
+                               if ( $handle ) {
+                                       $reqs[$path] = [
+                                               'method'  => 'GET',
+                                               'url'     => $this->storageUrl( $auth, $srcCont, $srcRel ),
+                                               'headers' => $this->authTokenHeaders( $auth )
+                                                       + $this->headersFromParams( $params ),
+                                               'stream'  => $handle,
+                                       ];
+                               } else {
+                                       $tmpFile = null;
+                               }
+                       }
+                       $tmpFiles[$path] = $tmpFile;
+               }
+
+               $isLatest = ( $this->isRGW || !empty( $params['latest'] ) );
+               $opts = [ 'maxConnsPerHost' => $params['concurrency'] ];
+               $reqs = $this->http->runMulti( $reqs, $opts );
+               foreach ( $reqs as $path => $op ) {
+                       list( $rcode, $rdesc, $rhdrs, $rbody, $rerr ) = $op['response'];
+                       fclose( $op['stream'] ); // close open handle
+                       if ( $rcode >= 200 && $rcode <= 299 ) {
+                               $size = $tmpFiles[$path] ? $tmpFiles[$path]->getSize() : 0;
+                               // Double check that the disk is not full/broken
+                               if ( $size != $rhdrs['content-length'] ) {
+                                       $tmpFiles[$path] = null;
+                                       $rerr = "Got {$size}/{$rhdrs['content-length']} bytes";
+                                       $this->onError( null, __METHOD__,
+                                               [ 'src' => $path ] + $ep, $rerr, $rcode, $rdesc );
+                               }
+                               // Set the file stat process cache in passing
+                               $stat = $this->getStatFromHeaders( $rhdrs );
+                               $stat['latest'] = $isLatest;
+                               $this->cheapCache->set( $path, 'stat', $stat );
+                       } elseif ( $rcode === 404 ) {
+                               $tmpFiles[$path] = false;
+                       } else {
+                               $tmpFiles[$path] = null;
+                               $this->onError( null, __METHOD__,
+                                       [ 'src' => $path ] + $ep, $rerr, $rcode, $rdesc );
+                       }
+               }
+
+               return $tmpFiles;
+       }
+
+       public function getFileHttpUrl( array $params ) {
+               if ( $this->swiftTempUrlKey != '' ||
+                       ( $this->rgwS3AccessKey != '' && $this->rgwS3SecretKey != '' )
+               ) {
+                       list( $srcCont, $srcRel ) = $this->resolveStoragePathReal( $params['src'] );
+                       if ( $srcRel === null ) {
+                               return null; // invalid path
+                       }
+
+                       $auth = $this->getAuthentication();
+                       if ( !$auth ) {
+                               return null;
+                       }
+
+                       $ttl = isset( $params['ttl'] ) ? $params['ttl'] : 86400;
+                       $expires = time() + $ttl;
+
+                       if ( $this->swiftTempUrlKey != '' ) {
+                               $url = $this->storageUrl( $auth, $srcCont, $srcRel );
+                               // Swift wants the signature based on the unencoded object name
+                               $contPath = parse_url( $this->storageUrl( $auth, $srcCont ), PHP_URL_PATH );
+                               $signature = hash_hmac( 'sha1',
+                                       "GET\n{$expires}\n{$contPath}/{$srcRel}",
+                                       $this->swiftTempUrlKey
+                               );
+
+                               return "{$url}?temp_url_sig={$signature}&temp_url_expires={$expires}";
+                       } else { // give S3 API URL for rgw
+                               // Path for signature starts with the bucket
+                               $spath = '/' . rawurlencode( $srcCont ) . '/' .
+                                       str_replace( '%2F', '/', rawurlencode( $srcRel ) );
+                               // Calculate the hash
+                               $signature = base64_encode( hash_hmac(
+                                       'sha1',
+                                       "GET\n\n\n{$expires}\n{$spath}",
+                                       $this->rgwS3SecretKey,
+                                       true // raw
+                               ) );
+                               // See http://s3.amazonaws.com/doc/s3-developer-guide/RESTAuthentication.html.
+                               // Note: adding a newline for empty CanonicalizedAmzHeaders does not work.
+                               // Note: S3 API is the rgw default; remove the /swift/ URL bit.
+                               return str_replace( '/swift/v1', '', $this->storageUrl( $auth ) . $spath ) .
+                                       '?' .
+                                       http_build_query( [
+                                               'Signature' => $signature,
+                                               'Expires' => $expires,
+                                               'AWSAccessKeyId' => $this->rgwS3AccessKey
+                                       ] );
+                       }
+               }
+
+               return null;
+       }
+
+       protected function directoriesAreVirtual() {
+               return true;
+       }
+
+       /**
+        * Get headers to send to Swift when reading a file based
+        * on a FileBackend params array, e.g. that of getLocalCopy().
+        * $params is currently only checked for a 'latest' flag.
+        *
+        * @param array $params
+        * @return array
+        */
+       protected function headersFromParams( array $params ) {
+               $hdrs = [];
+               if ( !empty( $params['latest'] ) ) {
+                       $hdrs['x-newest'] = 'true';
+               }
+
+               return $hdrs;
+       }
+
+       /**
+        * @param FileBackendStoreOpHandle[] $fileOpHandles
+        *
+        * @return StatusValue[]
+        */
+       protected function doExecuteOpHandlesInternal( array $fileOpHandles ) {
+               /** @var $statuses StatusValue[] */
+               $statuses = [];
+
+               $auth = $this->getAuthentication();
+               if ( !$auth ) {
+                       foreach ( $fileOpHandles as $index => $fileOpHandle ) {
+                               $statuses[$index] = $this->newStatus( 'backend-fail-connect', $this->name );
+                       }
+
+                       return $statuses;
+               }
+
+               // Split the HTTP requests into stages that can be done concurrently
+               $httpReqsByStage = []; // map of (stage => index => HTTP request)
+               foreach ( $fileOpHandles as $index => $fileOpHandle ) {
+                       /** @var SwiftFileOpHandle $fileOpHandle */
+                       $reqs = $fileOpHandle->httpOp;
+                       // Convert the 'url' parameter to an actual URL using $auth
+                       foreach ( $reqs as $stage => &$req ) {
+                               list( $container, $relPath ) = $req['url'];
+                               $req['url'] = $this->storageUrl( $auth, $container, $relPath );
+                               $req['headers'] = isset( $req['headers'] ) ? $req['headers'] : [];
+                               $req['headers'] = $this->authTokenHeaders( $auth ) + $req['headers'];
+                               $httpReqsByStage[$stage][$index] = $req;
+                       }
+                       $statuses[$index] = $this->newStatus();
+               }
+
+               // Run all requests for the first stage, then the next, and so on
+               $reqCount = count( $httpReqsByStage );
+               for ( $stage = 0; $stage < $reqCount; ++$stage ) {
+                       $httpReqs = $this->http->runMulti( $httpReqsByStage[$stage] );
+                       foreach ( $httpReqs as $index => $httpReq ) {
+                               // Run the callback for each request of this operation
+                               $callback = $fileOpHandles[$index]->callback;
+                               call_user_func_array( $callback, [ $httpReq, $statuses[$index] ] );
+                               // On failure, abort all remaining requests for this operation
+                               // (e.g. abort the DELETE request if the COPY request fails for a move)
+                               if ( !$statuses[$index]->isOK() ) {
+                                       $stages = count( $fileOpHandles[$index]->httpOp );
+                                       for ( $s = ( $stage + 1 ); $s < $stages; ++$s ) {
+                                               unset( $httpReqsByStage[$s][$index] );
+                                       }
+                               }
+                       }
+               }
+
+               return $statuses;
+       }
+
+       /**
+        * Set read/write permissions for a Swift container.
+        *
+        * @see http://swift.openstack.org/misc.html#acls
+        *
+        * In general, we don't allow listings to end-users. It's not useful, isn't well-defined
+        * (lists are truncated to 10000 item with no way to page), and is just a performance risk.
+        *
+        * @param string $container Resolved Swift container
+        * @param array $readGrps List of the possible criteria for a request to have
+        * access to read a container. Each item is one of the following formats:
+        *   - account:user        : Grants access if the request is by the given user
+        *   - ".r:<regex>"        : Grants access if the request is from a referrer host that
+        *                           matches the expression and the request is not for a listing.
+        *                           Setting this to '*' effectively makes a container public.
+        *   -".rlistings:<regex>" : Grants access if the request is from a referrer host that
+        *                           matches the expression and the request is for a listing.
+        * @param array $writeGrps A list of the possible criteria for a request to have
+        * access to write to a container. Each item is of the following format:
+        *   - account:user       : Grants access if the request is by the given user
+        * @return StatusValue
+        */
+       protected function setContainerAccess( $container, array $readGrps, array $writeGrps ) {
+               $status = $this->newStatus();
+               $auth = $this->getAuthentication();
+
+               if ( !$auth ) {
+                       $status->fatal( 'backend-fail-connect', $this->name );
+
+                       return $status;
+               }
+
+               list( $rcode, $rdesc, $rhdrs, $rbody, $rerr ) = $this->http->run( [
+                       'method' => 'POST',
+                       'url' => $this->storageUrl( $auth, $container ),
+                       'headers' => $this->authTokenHeaders( $auth ) + [
+                               'x-container-read' => implode( ',', $readGrps ),
+                               'x-container-write' => implode( ',', $writeGrps )
+                       ]
+               ] );
+
+               if ( $rcode != 204 && $rcode !== 202 ) {
+                       $status->fatal( 'backend-fail-internal', $this->name );
+                       $this->logger->error( __METHOD__ . ': unexpected rcode value (' . $rcode . ')' );
+               }
+
+               return $status;
+       }
+
+       /**
+        * Get a Swift container stat array, possibly from process cache.
+        * Use $reCache if the file count or byte count is needed.
+        *
+        * @param string $container Container name
+        * @param bool $bypassCache Bypass all caches and load from Swift
+        * @return array|bool|null False on 404, null on failure
+        */
+       protected function getContainerStat( $container, $bypassCache = false ) {
+               $ps = $this->scopedProfileSection( __METHOD__ . "-{$this->name}" );
+
+               if ( $bypassCache ) { // purge cache
+                       $this->containerStatCache->clear( $container );
+               } elseif ( !$this->containerStatCache->has( $container, 'stat' ) ) {
+                       $this->primeContainerCache( [ $container ] ); // check persistent cache
+               }
+               if ( !$this->containerStatCache->has( $container, 'stat' ) ) {
+                       $auth = $this->getAuthentication();
+                       if ( !$auth ) {
+                               return null;
+                       }
+
+                       list( $rcode, $rdesc, $rhdrs, $rbody, $rerr ) = $this->http->run( [
+                               'method' => 'HEAD',
+                               'url' => $this->storageUrl( $auth, $container ),
+                               'headers' => $this->authTokenHeaders( $auth )
+                       ] );
+
+                       if ( $rcode === 204 ) {
+                               $stat = [
+                                       'count' => $rhdrs['x-container-object-count'],
+                                       'bytes' => $rhdrs['x-container-bytes-used']
+                               ];
+                               if ( $bypassCache ) {
+                                       return $stat;
+                               } else {
+                                       $this->containerStatCache->set( $container, 'stat', $stat ); // cache it
+                                       $this->setContainerCache( $container, $stat ); // update persistent cache
+                               }
+                       } elseif ( $rcode === 404 ) {
+                               return false;
+                       } else {
+                               $this->onError( null, __METHOD__,
+                                       [ 'cont' => $container ], $rerr, $rcode, $rdesc );
+
+                               return null;
+                       }
+               }
+
+               return $this->containerStatCache->get( $container, 'stat' );
+       }
+
+       /**
+        * Create a Swift container
+        *
+        * @param string $container Container name
+        * @param array $params
+        * @return StatusValue
+        */
+       protected function createContainer( $container, array $params ) {
+               $status = $this->newStatus();
+
+               $auth = $this->getAuthentication();
+               if ( !$auth ) {
+                       $status->fatal( 'backend-fail-connect', $this->name );
+
+                       return $status;
+               }
+
+               // @see SwiftFileBackend::setContainerAccess()
+               if ( empty( $params['noAccess'] ) ) {
+                       $readGrps = [ '.r:*', $this->swiftUser ]; // public
+               } else {
+                       $readGrps = [ $this->swiftUser ]; // private
+               }
+               $writeGrps = [ $this->swiftUser ]; // sanity
+
+               list( $rcode, $rdesc, $rhdrs, $rbody, $rerr ) = $this->http->run( [
+                       'method' => 'PUT',
+                       'url' => $this->storageUrl( $auth, $container ),
+                       'headers' => $this->authTokenHeaders( $auth ) + [
+                               'x-container-read' => implode( ',', $readGrps ),
+                               'x-container-write' => implode( ',', $writeGrps )
+                       ]
+               ] );
+
+               if ( $rcode === 201 ) { // new
+                       // good
+               } elseif ( $rcode === 202 ) { // already there
+                       // this shouldn't really happen, but is OK
+               } else {
+                       $this->onError( $status, __METHOD__, $params, $rerr, $rcode, $rdesc );
+               }
+
+               return $status;
+       }
+
+       /**
+        * Delete a Swift container
+        *
+        * @param string $container Container name
+        * @param array $params
+        * @return StatusValue
+        */
+       protected function deleteContainer( $container, array $params ) {
+               $status = $this->newStatus();
+
+               $auth = $this->getAuthentication();
+               if ( !$auth ) {
+                       $status->fatal( 'backend-fail-connect', $this->name );
+
+                       return $status;
+               }
+
+               list( $rcode, $rdesc, $rhdrs, $rbody, $rerr ) = $this->http->run( [
+                       'method' => 'DELETE',
+                       'url' => $this->storageUrl( $auth, $container ),
+                       'headers' => $this->authTokenHeaders( $auth )
+               ] );
+
+               if ( $rcode >= 200 && $rcode <= 299 ) { // deleted
+                       $this->containerStatCache->clear( $container ); // purge
+               } elseif ( $rcode === 404 ) { // not there
+                       // this shouldn't really happen, but is OK
+               } elseif ( $rcode === 409 ) { // not empty
+                       $this->onError( $status, __METHOD__, $params, $rerr, $rcode, $rdesc ); // race?
+               } else {
+                       $this->onError( $status, __METHOD__, $params, $rerr, $rcode, $rdesc );
+               }
+
+               return $status;
+       }
+
+       /**
+        * Get a list of objects under a container.
+        * Either just the names or a list of stdClass objects with details can be returned.
+        *
+        * @param string $fullCont
+        * @param string $type ('info' for a list of object detail maps, 'names' for names only)
+        * @param int $limit
+        * @param string|null $after
+        * @param string|null $prefix
+        * @param string|null $delim
+        * @return StatusValue With the list as value
+        */
+       private function objectListing(
+               $fullCont, $type, $limit, $after = null, $prefix = null, $delim = null
+       ) {
+               $status = $this->newStatus();
+
+               $auth = $this->getAuthentication();
+               if ( !$auth ) {
+                       $status->fatal( 'backend-fail-connect', $this->name );
+
+                       return $status;
+               }
+
+               $query = [ 'limit' => $limit ];
+               if ( $type === 'info' ) {
+                       $query['format'] = 'json';
+               }
+               if ( $after !== null ) {
+                       $query['marker'] = $after;
+               }
+               if ( $prefix !== null ) {
+                       $query['prefix'] = $prefix;
+               }
+               if ( $delim !== null ) {
+                       $query['delimiter'] = $delim;
+               }
+
+               list( $rcode, $rdesc, $rhdrs, $rbody, $rerr ) = $this->http->run( [
+                       'method' => 'GET',
+                       'url' => $this->storageUrl( $auth, $fullCont ),
+                       'query' => $query,
+                       'headers' => $this->authTokenHeaders( $auth )
+               ] );
+
+               $params = [ 'cont' => $fullCont, 'prefix' => $prefix, 'delim' => $delim ];
+               if ( $rcode === 200 ) { // good
+                       if ( $type === 'info' ) {
+                               $status->value = FormatJson::decode( trim( $rbody ) );
+                       } else {
+                               $status->value = explode( "\n", trim( $rbody ) );
+                       }
+               } elseif ( $rcode === 204 ) {
+                       $status->value = []; // empty container
+               } elseif ( $rcode === 404 ) {
+                       $status->value = []; // no container
+               } else {
+                       $this->onError( $status, __METHOD__, $params, $rerr, $rcode, $rdesc );
+               }
+
+               return $status;
+       }
+
+       protected function doPrimeContainerCache( array $containerInfo ) {
+               foreach ( $containerInfo as $container => $info ) {
+                       $this->containerStatCache->set( $container, 'stat', $info );
+               }
+       }
+
+       protected function doGetFileStatMulti( array $params ) {
+               $stats = [];
+
+               $auth = $this->getAuthentication();
+
+               $reqs = [];
+               foreach ( $params['srcs'] as $path ) {
+                       list( $srcCont, $srcRel ) = $this->resolveStoragePathReal( $path );
+                       if ( $srcRel === null ) {
+                               $stats[$path] = false;
+                               continue; // invalid storage path
+                       } elseif ( !$auth ) {
+                               $stats[$path] = null;
+                               continue;
+                       }
+
+                       // (a) Check the container
+                       $cstat = $this->getContainerStat( $srcCont );
+                       if ( $cstat === false ) {
+                               $stats[$path] = false;
+                               continue; // ok, nothing to do
+                       } elseif ( !is_array( $cstat ) ) {
+                               $stats[$path] = null;
+                               continue;
+                       }
+
+                       $reqs[$path] = [
+                               'method'  => 'HEAD',
+                               'url'     => $this->storageUrl( $auth, $srcCont, $srcRel ),
+                               'headers' => $this->authTokenHeaders( $auth ) + $this->headersFromParams( $params )
+                       ];
+               }
+
+               $opts = [ 'maxConnsPerHost' => $params['concurrency'] ];
+               $reqs = $this->http->runMulti( $reqs, $opts );
+
+               foreach ( $params['srcs'] as $path ) {
+                       if ( array_key_exists( $path, $stats ) ) {
+                               continue; // some sort of failure above
+                       }
+                       // (b) Check the file
+                       list( $rcode, $rdesc, $rhdrs, $rbody, $rerr ) = $reqs[$path]['response'];
+                       if ( $rcode === 200 || $rcode === 204 ) {
+                               // Update the object if it is missing some headers
+                               $rhdrs = $this->addMissingMetadata( $rhdrs, $path );
+                               // Load the stat array from the headers
+                               $stat = $this->getStatFromHeaders( $rhdrs );
+                               if ( $this->isRGW ) {
+                                       $stat['latest'] = true; // strong consistency
+                               }
+                       } elseif ( $rcode === 404 ) {
+                               $stat = false;
+                       } else {
+                               $stat = null;
+                               $this->onError( null, __METHOD__, $params, $rerr, $rcode, $rdesc );
+                       }
+                       $stats[$path] = $stat;
+               }
+
+               return $stats;
+       }
+
+       /**
+        * @param array $rhdrs
+        * @return array
+        */
+       protected function getStatFromHeaders( array $rhdrs ) {
+               // Fetch all of the custom metadata headers
+               $metadata = $this->getMetadata( $rhdrs );
+               // Fetch all of the custom raw HTTP headers
+               $headers = $this->sanitizeHdrs( [ 'headers' => $rhdrs ] );
+
+               return [
+                       // Convert various random Swift dates to TS_MW
+                       'mtime' => $this->convertSwiftDate( $rhdrs['last-modified'], TS_MW ),
+                       // Empty objects actually return no content-length header in Ceph
+                       'size'  => isset( $rhdrs['content-length'] ) ? (int)$rhdrs['content-length'] : 0,
+                       'sha1'  => isset( $metadata['sha1base36'] ) ? $metadata['sha1base36'] : null,
+                       // Note: manifiest ETags are not an MD5 of the file
+                       'md5'   => ctype_xdigit( $rhdrs['etag'] ) ? $rhdrs['etag'] : null,
+                       'xattr' => [ 'metadata' => $metadata, 'headers' => $headers ]
+               ];
+       }
+
+       /**
+        * @return array|null Credential map
+        */
+       protected function getAuthentication() {
+               if ( $this->authErrorTimestamp !== null ) {
+                       if ( ( time() - $this->authErrorTimestamp ) < 60 ) {
+                               return null; // failed last attempt; don't bother
+                       } else { // actually retry this time
+                               $this->authErrorTimestamp = null;
+                       }
+               }
+               // Session keys expire after a while, so we renew them periodically
+               $reAuth = ( ( time() - $this->authSessionTimestamp ) > $this->authTTL );
+               // Authenticate with proxy and get a session key...
+               if ( !$this->authCreds || $reAuth ) {
+                       $this->authSessionTimestamp = 0;
+                       $cacheKey = $this->getCredsCacheKey( $this->swiftUser );
+                       $creds = $this->srvCache->get( $cacheKey ); // credentials
+                       // Try to use the credential cache
+                       if ( isset( $creds['auth_token'] ) && isset( $creds['storage_url'] ) ) {
+                               $this->authCreds = $creds;
+                               // Skew the timestamp for worst case to avoid using stale credentials
+                               $this->authSessionTimestamp = time() - ceil( $this->authTTL / 2 );
+                       } else { // cache miss
+                               list( $rcode, $rdesc, $rhdrs, $rbody, $rerr ) = $this->http->run( [
+                                       'method' => 'GET',
+                                       'url' => "{$this->swiftAuthUrl}/v1.0",
+                                       'headers' => [
+                                               'x-auth-user' => $this->swiftUser,
+                                               'x-auth-key' => $this->swiftKey
+                                       ]
+                               ] );
+
+                               if ( $rcode >= 200 && $rcode <= 299 ) { // OK
+                                       $this->authCreds = [
+                                               'auth_token' => $rhdrs['x-auth-token'],
+                                               'storage_url' => $rhdrs['x-storage-url']
+                                       ];
+                                       $this->srvCache->set( $cacheKey, $this->authCreds, ceil( $this->authTTL / 2 ) );
+                                       $this->authSessionTimestamp = time();
+                               } elseif ( $rcode === 401 ) {
+                                       $this->onError( null, __METHOD__, [], "Authentication failed.", $rcode );
+                                       $this->authErrorTimestamp = time();
+
+                                       return null;
+                               } else {
+                                       $this->onError( null, __METHOD__, [], "HTTP return code: $rcode", $rcode );
+                                       $this->authErrorTimestamp = time();
+
+                                       return null;
+                               }
+                       }
+                       // Ceph RGW does not use <account> in URLs (OpenStack Swift uses "/v1/<account>")
+                       if ( substr( $this->authCreds['storage_url'], -3 ) === '/v1' ) {
+                               $this->isRGW = true; // take advantage of strong consistency in Ceph
+                       }
+               }
+
+               return $this->authCreds;
+       }
+
+       /**
+        * @param array $creds From getAuthentication()
+        * @param string $container
+        * @param string $object
+        * @return array
+        */
+       protected function storageUrl( array $creds, $container = null, $object = null ) {
+               $parts = [ $creds['storage_url'] ];
+               if ( strlen( $container ) ) {
+                       $parts[] = rawurlencode( $container );
+               }
+               if ( strlen( $object ) ) {
+                       $parts[] = str_replace( "%2F", "/", rawurlencode( $object ) );
+               }
+
+               return implode( '/', $parts );
+       }
+
+       /**
+        * @param array $creds From getAuthentication()
+        * @return array
+        */
+       protected function authTokenHeaders( array $creds ) {
+               return [ 'x-auth-token' => $creds['auth_token'] ];
+       }
+
+       /**
+        * Get the cache key for a container
+        *
+        * @param string $username
+        * @return string
+        */
+       private function getCredsCacheKey( $username ) {
+               return 'swiftcredentials:' . md5( $username . ':' . $this->swiftAuthUrl );
+       }
+
+       /**
+        * Log an unexpected exception for this backend.
+        * This also sets the StatusValue object to have a fatal error.
+        *
+        * @param StatusValue|null $status
+        * @param string $func
+        * @param array $params
+        * @param string $err Error string
+        * @param int $code HTTP status
+        * @param string $desc HTTP StatusValue description
+        */
+       public function onError( $status, $func, array $params, $err = '', $code = 0, $desc = '' ) {
+               if ( $status instanceof StatusValue ) {
+                       $status->fatal( 'backend-fail-internal', $this->name );
+               }
+               if ( $code == 401 ) { // possibly a stale token
+                       $this->srvCache->delete( $this->getCredsCacheKey( $this->swiftUser ) );
+               }
+               $this->logger->error(
+                       "HTTP $code ($desc) in '{$func}' (given '" . FormatJson::encode( $params ) . "')" .
+                       ( $err ? ": $err" : "" )
+               );
+       }
+}
+
+/**
+ * @see FileBackendStoreOpHandle
+ */
+class SwiftFileOpHandle extends FileBackendStoreOpHandle {
+       /** @var array List of Requests for MultiHttpClient */
+       public $httpOp;
+       /** @var Closure */
+       public $callback;
+
+       /**
+        * @param SwiftFileBackend $backend
+        * @param Closure $callback Function that takes (HTTP request array, status)
+        * @param array $httpOp MultiHttpClient op
+        */
+       public function __construct( SwiftFileBackend $backend, Closure $callback, array $httpOp ) {
+               $this->backend = $backend;
+               $this->callback = $callback;
+               $this->httpOp = $httpOp;
+       }
+}
+
+/**
+ * SwiftFileBackend helper class to page through listings.
+ * Swift also has a listing limit of 10,000 objects for sanity.
+ * Do not use this class from places outside SwiftFileBackend.
+ *
+ * @ingroup FileBackend
+ */
+abstract class SwiftFileBackendList implements Iterator {
+       /** @var array List of path or (path,stat array) entries */
+       protected $bufferIter = [];
+
+       /** @var string List items *after* this path */
+       protected $bufferAfter = null;
+
+       /** @var int */
+       protected $pos = 0;
+
+       /** @var array */
+       protected $params = [];
+
+       /** @var SwiftFileBackend */
+       protected $backend;
+
+       /** @var string Container name */
+       protected $container;
+
+       /** @var string Storage directory */
+       protected $dir;
+
+       /** @var int */
+       protected $suffixStart;
+
+       const PAGE_SIZE = 9000; // file listing buffer size
+
+       /**
+        * @param SwiftFileBackend $backend
+        * @param string $fullCont Resolved container name
+        * @param string $dir Resolved directory relative to container
+        * @param array $params
+        */
+       public function __construct( SwiftFileBackend $backend, $fullCont, $dir, array $params ) {
+               $this->backend = $backend;
+               $this->container = $fullCont;
+               $this->dir = $dir;
+               if ( substr( $this->dir, -1 ) === '/' ) {
+                       $this->dir = substr( $this->dir, 0, -1 ); // remove trailing slash
+               }
+               if ( $this->dir == '' ) { // whole container
+                       $this->suffixStart = 0;
+               } else { // dir within container
+                       $this->suffixStart = strlen( $this->dir ) + 1; // size of "path/to/dir/"
+               }
+               $this->params = $params;
+       }
+
+       /**
+        * @see Iterator::key()
+        * @return int
+        */
+       public function key() {
+               return $this->pos;
+       }
+
+       /**
+        * @see Iterator::next()
+        */
+       public function next() {
+               // Advance to the next file in the page
+               next( $this->bufferIter );
+               ++$this->pos;
+               // Check if there are no files left in this page and
+               // advance to the next page if this page was not empty.
+               if ( !$this->valid() && count( $this->bufferIter ) ) {
+                       $this->bufferIter = $this->pageFromList(
+                               $this->container, $this->dir, $this->bufferAfter, self::PAGE_SIZE, $this->params
+                       ); // updates $this->bufferAfter
+               }
+       }
+
+       /**
+        * @see Iterator::rewind()
+        */
+       public function rewind() {
+               $this->pos = 0;
+               $this->bufferAfter = null;
+               $this->bufferIter = $this->pageFromList(
+                       $this->container, $this->dir, $this->bufferAfter, self::PAGE_SIZE, $this->params
+               ); // updates $this->bufferAfter
+       }
+
+       /**
+        * @see Iterator::valid()
+        * @return bool
+        */
+       public function valid() {
+               if ( $this->bufferIter === null ) {
+                       return false; // some failure?
+               } else {
+                       return ( current( $this->bufferIter ) !== false ); // no paths can have this value
+               }
+       }
+
+       /**
+        * Get the given list portion (page)
+        *
+        * @param string $container Resolved container name
+        * @param string $dir Resolved path relative to container
+        * @param string $after
+        * @param int $limit
+        * @param array $params
+        * @return Traversable|array
+        */
+       abstract protected function pageFromList( $container, $dir, &$after, $limit, array $params );
+}
+
+/**
+ * Iterator for listing directories
+ */
+class SwiftFileBackendDirList extends SwiftFileBackendList {
+       /**
+        * @see Iterator::current()
+        * @return string|bool String (relative path) or false
+        */
+       public function current() {
+               return substr( current( $this->bufferIter ), $this->suffixStart, -1 );
+       }
+
+       protected function pageFromList( $container, $dir, &$after, $limit, array $params ) {
+               return $this->backend->getDirListPageInternal( $container, $dir, $after, $limit, $params );
+       }
+}
+
+/**
+ * Iterator for listing regular files
+ */
+class SwiftFileBackendFileList extends SwiftFileBackendList {
+       /**
+        * @see Iterator::current()
+        * @return string|bool String (relative path) or false
+        */
+       public function current() {
+               list( $path, $stat ) = current( $this->bufferIter );
+               $relPath = substr( $path, $this->suffixStart );
+               if ( is_array( $stat ) ) {
+                       $storageDir = rtrim( $this->params['dir'], '/' );
+                       $this->backend->loadListingStatInternal( "$storageDir/$relPath", $stat );
+               }
+
+               return $relPath;
+       }
+
+       protected function pageFromList( $container, $dir, &$after, $limit, array $params ) {
+               return $this->backend->getFileListPageInternal( $container, $dir, $after, $limit, $params );
+       }
+}
index b058146..64a2916 100644 (file)
@@ -148,7 +148,7 @@ abstract class DBLockManager extends QuorumLockManager {
                        } elseif ( is_array( $this->dbServers[$lockDb] ) ) {
                                // Parameters to construct a new database connection
                                $config = $this->dbServers[$lockDb];
-                               $db = DatabaseBase::factory( $config['type'], $config );
+                               $db = Database::factory( $config['type'], $config );
                        } else {
                                throw new UnexpectedValueException( "No server called '$lockDb'." );
                        }
index a9f5ca3..6001705 100644 (file)
@@ -98,6 +98,7 @@ class RedisLockManager extends QuorumLockManager {
 
                try {
                        static $script =
+                       /** @lang Lua */
 <<<LUA
                        local failed = {}
                        -- Load input params (e.g. session, ttl, time of request)
@@ -191,6 +192,7 @@ LUA;
 
                try {
                        static $script =
+                       /** @lang Lua */
 <<<LUA
                        local failed = {}
                        -- Load input params (e.g. session)
diff --git a/includes/libs/objectcache/RedisBagOStuff.php b/includes/libs/objectcache/RedisBagOStuff.php
new file mode 100644 (file)
index 0000000..d852f82
--- /dev/null
@@ -0,0 +1,433 @@
+<?php
+/**
+ * Object caching using Redis (http://redis.io/).
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ */
+
+/**
+ * Redis-based caching module for redis server >= 2.6.12
+ *
+ * @note: avoid use of Redis::MULTI transactions for twemproxy support
+ */
+class RedisBagOStuff extends BagOStuff {
+       /** @var RedisConnectionPool */
+       protected $redisPool;
+       /** @var array List of server names */
+       protected $servers;
+       /** @var array Map of (tag => server name) */
+       protected $serverTagMap;
+       /** @var bool */
+       protected $automaticFailover;
+
+       /**
+        * Construct a RedisBagOStuff object. Parameters are:
+        *
+        *   - servers: An array of server names. A server name may be a hostname,
+        *     a hostname/port combination or the absolute path of a UNIX socket.
+        *     If a hostname is specified but no port, the standard port number
+        *     6379 will be used. Arrays keys can be used to specify the tag to
+        *     hash on in place of the host/port. Required.
+        *
+        *   - connectTimeout: The timeout for new connections, in seconds. Optional,
+        *     default is 1 second.
+        *
+        *   - persistent: Set this to true to allow connections to persist across
+        *     multiple web requests. False by default.
+        *
+        *   - password: The authentication password, will be sent to Redis in
+        *     clear text. Optional, if it is unspecified, no AUTH command will be
+        *     sent.
+        *
+        *   - automaticFailover: If this is false, then each key will be mapped to
+        *     a single server, and if that server is down, any requests for that key
+        *     will fail. If this is true, a connection failure will cause the client
+        *     to immediately try the next server in the list (as determined by a
+        *     consistent hashing algorithm). True by default. This has the
+        *     potential to create consistency issues if a server is slow enough to
+        *     flap, for example if it is in swap death.
+        * @param array $params
+        */
+       function __construct( $params ) {
+               parent::__construct( $params );
+               $redisConf = [ 'serializer' => 'none' ]; // manage that in this class
+               foreach ( [ 'connectTimeout', 'persistent', 'password' ] as $opt ) {
+                       if ( isset( $params[$opt] ) ) {
+                               $redisConf[$opt] = $params[$opt];
+                       }
+               }
+               $this->redisPool = RedisConnectionPool::singleton( $redisConf );
+
+               $this->servers = $params['servers'];
+               foreach ( $this->servers as $key => $server ) {
+                       $this->serverTagMap[is_int( $key ) ? $server : $key] = $server;
+               }
+
+               if ( isset( $params['automaticFailover'] ) ) {
+                       $this->automaticFailover = $params['automaticFailover'];
+               } else {
+                       $this->automaticFailover = true;
+               }
+
+               $this->attrMap[self::ATTR_SYNCWRITES] = self::QOS_SYNCWRITES_NONE;
+       }
+
+       protected function doGet( $key, $flags = 0 ) {
+               list( $server, $conn ) = $this->getConnection( $key );
+               if ( !$conn ) {
+                       return false;
+               }
+               try {
+                       $value = $conn->get( $key );
+                       $result = $this->unserialize( $value );
+               } catch ( RedisException $e ) {
+                       $result = false;
+                       $this->handleException( $conn, $e );
+               }
+
+               $this->logRequest( 'get', $key, $server, $result );
+               return $result;
+       }
+
+       public function set( $key, $value, $expiry = 0, $flags = 0 ) {
+               list( $server, $conn ) = $this->getConnection( $key );
+               if ( !$conn ) {
+                       return false;
+               }
+               $expiry = $this->convertToRelative( $expiry );
+               try {
+                       if ( $expiry ) {
+                               $result = $conn->setex( $key, $expiry, $this->serialize( $value ) );
+                       } else {
+                               // No expiry, that is very different from zero expiry in Redis
+                               $result = $conn->set( $key, $this->serialize( $value ) );
+                       }
+               } catch ( RedisException $e ) {
+                       $result = false;
+                       $this->handleException( $conn, $e );
+               }
+
+               $this->logRequest( 'set', $key, $server, $result );
+               return $result;
+       }
+
+       public function delete( $key ) {
+               list( $server, $conn ) = $this->getConnection( $key );
+               if ( !$conn ) {
+                       return false;
+               }
+               try {
+                       $conn->delete( $key );
+                       // Return true even if the key didn't exist
+                       $result = true;
+               } catch ( RedisException $e ) {
+                       $result = false;
+                       $this->handleException( $conn, $e );
+               }
+
+               $this->logRequest( 'delete', $key, $server, $result );
+               return $result;
+       }
+
+       public function getMulti( array $keys, $flags = 0 ) {
+               $batches = [];
+               $conns = [];
+               foreach ( $keys as $key ) {
+                       list( $server, $conn ) = $this->getConnection( $key );
+                       if ( !$conn ) {
+                               continue;
+                       }
+                       $conns[$server] = $conn;
+                       $batches[$server][] = $key;
+               }
+               $result = [];
+               foreach ( $batches as $server => $batchKeys ) {
+                       $conn = $conns[$server];
+                       try {
+                               $conn->multi( Redis::PIPELINE );
+                               foreach ( $batchKeys as $key ) {
+                                       $conn->get( $key );
+                               }
+                               $batchResult = $conn->exec();
+                               if ( $batchResult === false ) {
+                                       $this->debug( "multi request to $server failed" );
+                                       continue;
+                               }
+                               foreach ( $batchResult as $i => $value ) {
+                                       if ( $value !== false ) {
+                                               $result[$batchKeys[$i]] = $this->unserialize( $value );
+                                       }
+                               }
+                       } catch ( RedisException $e ) {
+                               $this->handleException( $conn, $e );
+                       }
+               }
+
+               $this->debug( "getMulti for " . count( $keys ) . " keys " .
+                       "returned " . count( $result ) . " results" );
+               return $result;
+       }
+
+       /**
+        * @param array $data
+        * @param int $expiry
+        * @return bool
+        */
+       public function setMulti( array $data, $expiry = 0 ) {
+               $batches = [];
+               $conns = [];
+               foreach ( $data as $key => $value ) {
+                       list( $server, $conn ) = $this->getConnection( $key );
+                       if ( !$conn ) {
+                               continue;
+                       }
+                       $conns[$server] = $conn;
+                       $batches[$server][] = $key;
+               }
+
+               $expiry = $this->convertToRelative( $expiry );
+               $result = true;
+               foreach ( $batches as $server => $batchKeys ) {
+                       $conn = $conns[$server];
+                       try {
+                               $conn->multi( Redis::PIPELINE );
+                               foreach ( $batchKeys as $key ) {
+                                       if ( $expiry ) {
+                                               $conn->setex( $key, $expiry, $this->serialize( $data[$key] ) );
+                                       } else {
+                                               $conn->set( $key, $this->serialize( $data[$key] ) );
+                                       }
+                               }
+                               $batchResult = $conn->exec();
+                               if ( $batchResult === false ) {
+                                       $this->debug( "setMulti request to $server failed" );
+                                       continue;
+                               }
+                               foreach ( $batchResult as $value ) {
+                                       if ( $value === false ) {
+                                               $result = false;
+                                       }
+                               }
+                       } catch ( RedisException $e ) {
+                               $this->handleException( $server, $conn, $e );
+                               $result = false;
+                       }
+               }
+
+               return $result;
+       }
+
+       public function add( $key, $value, $expiry = 0 ) {
+               list( $server, $conn ) = $this->getConnection( $key );
+               if ( !$conn ) {
+                       return false;
+               }
+               $expiry = $this->convertToRelative( $expiry );
+               try {
+                       if ( $expiry ) {
+                               $result = $conn->set(
+                                       $key,
+                                       $this->serialize( $value ),
+                                       [ 'nx', 'ex' => $expiry ]
+                               );
+                       } else {
+                               $result = $conn->setnx( $key, $this->serialize( $value ) );
+                       }
+               } catch ( RedisException $e ) {
+                       $result = false;
+                       $this->handleException( $conn, $e );
+               }
+
+               $this->logRequest( 'add', $key, $server, $result );
+               return $result;
+       }
+
+       /**
+        * Non-atomic implementation of incr().
+        *
+        * Probably all callers actually want incr() to atomically initialise
+        * values to zero if they don't exist, as provided by the Redis INCR
+        * command. But we are constrained by the memcached-like interface to
+        * return null in that case. Once the key exists, further increments are
+        * atomic.
+        * @param string $key Key to increase
+        * @param int $value Value to add to $key (Default 1)
+        * @return int|bool New value or false on failure
+        */
+       public function incr( $key, $value = 1 ) {
+               list( $server, $conn ) = $this->getConnection( $key );
+               if ( !$conn ) {
+                       return false;
+               }
+               try {
+                       if ( !$conn->exists( $key ) ) {
+                               return null;
+                       }
+                       // @FIXME: on races, the key may have a 0 TTL
+                       $result = $conn->incrBy( $key, $value );
+               } catch ( RedisException $e ) {
+                       $result = false;
+                       $this->handleException( $conn, $e );
+               }
+
+               $this->logRequest( 'incr', $key, $server, $result );
+               return $result;
+       }
+
+       public function changeTTL( $key, $expiry = 0 ) {
+               list( $server, $conn ) = $this->getConnection( $key );
+               if ( !$conn ) {
+                       return false;
+               }
+
+               $expiry = $this->convertToRelative( $expiry );
+               try {
+                       $result = $conn->expire( $key, $expiry );
+               } catch ( RedisException $e ) {
+                       $result = false;
+                       $this->handleException( $conn, $e );
+               }
+
+               $this->logRequest( 'expire', $key, $server, $result );
+               return $result;
+       }
+
+       public function modifySimpleRelayEvent( array $event ) {
+               if ( array_key_exists( 'val', $event ) ) {
+                       $event['val'] = serialize( $event['val'] ); // this class uses PHP serialization
+               }
+
+               return $event;
+       }
+
+       /**
+        * @param mixed $data
+        * @return string
+        */
+       protected function serialize( $data ) {
+               // Serialize anything but integers so INCR/DECR work
+               // Do not store integer-like strings as integers to avoid type confusion (bug 60563)
+               return is_int( $data ) ? $data : serialize( $data );
+       }
+
+       /**
+        * @param string $data
+        * @return mixed
+        */
+       protected function unserialize( $data ) {
+               $int = intval( $data );
+               return $data === (string)$int ? $int : unserialize( $data );
+       }
+
+       /**
+        * Get a Redis object with a connection suitable for fetching the specified key
+        * @param string $key
+        * @return array (server, RedisConnRef) or (false, false)
+        */
+       protected function getConnection( $key ) {
+               $candidates = array_keys( $this->serverTagMap );
+
+               if ( count( $this->servers ) > 1 ) {
+                       ArrayUtils::consistentHashSort( $candidates, $key, '/' );
+                       if ( !$this->automaticFailover ) {
+                               $candidates = array_slice( $candidates, 0, 1 );
+                       }
+               }
+
+               while ( ( $tag = array_shift( $candidates ) ) !== null ) {
+                       $server = $this->serverTagMap[$tag];
+                       $conn = $this->redisPool->getConnection( $server, $this->logger );
+                       if ( !$conn ) {
+                               continue;
+                       }
+
+                       // If automatic failover is enabled, check that the server's link
+                       // to its master (if any) is up -- but only if there are other
+                       // viable candidates left to consider. Also, getMasterLinkStatus()
+                       // does not work with twemproxy, though $candidates will be empty
+                       // by now in such cases.
+                       if ( $this->automaticFailover && $candidates ) {
+                               try {
+                                       if ( $this->getMasterLinkStatus( $conn ) === 'down' ) {
+                                               // If the master cannot be reached, fail-over to the next server.
+                                               // If masters are in data-center A, and replica DBs in data-center B,
+                                               // this helps avoid the case were fail-over happens in A but not
+                                               // to the corresponding server in B (e.g. read/write mismatch).
+                                               continue;
+                                       }
+                               } catch ( RedisException $e ) {
+                                       // Server is not accepting commands
+                                       $this->handleException( $conn, $e );
+                                       continue;
+                               }
+                       }
+
+                       return [ $server, $conn ];
+               }
+
+               $this->setLastError( BagOStuff::ERR_UNREACHABLE );
+
+               return [ false, false ];
+       }
+
+       /**
+        * Check the master link status of a Redis server that is configured as a replica DB.
+        * @param RedisConnRef $conn
+        * @return string|null Master link status (either 'up' or 'down'), or null
+        *  if the server is not a replica DB.
+        */
+       protected function getMasterLinkStatus( RedisConnRef $conn ) {
+               $info = $conn->info();
+               return isset( $info['master_link_status'] )
+                       ? $info['master_link_status']
+                       : null;
+       }
+
+       /**
+        * Log a fatal error
+        * @param string $msg
+        */
+       protected function logError( $msg ) {
+               $this->logger->error( "Redis error: $msg" );
+       }
+
+       /**
+        * The redis extension throws an exception in response to various read, write
+        * and protocol errors. Sometimes it also closes the connection, sometimes
+        * not. The safest response for us is to explicitly destroy the connection
+        * object and let it be reopened during the next request.
+        * @param RedisConnRef $conn
+        * @param Exception $e
+        */
+       protected function handleException( RedisConnRef $conn, $e ) {
+               $this->setLastError( BagOStuff::ERR_UNEXPECTED );
+               $this->redisPool->handleError( $conn, $e );
+       }
+
+       /**
+        * Send information about a single request to the debug log
+        * @param string $method
+        * @param string $key
+        * @param string $server
+        * @param bool $result
+        */
+       public function logRequest( $method, $key, $server, $result ) {
+               $this->debug( "$method $key on $server: " .
+                       ( $result === false ? "failure" : "success" ) );
+       }
+}
index 5c9976d..4d2b28f 100644 (file)
@@ -29,7 +29,7 @@ use Psr\Log\NullLogger;
 /**
  * Helper class that detects high-contention DB queries via profiling calls
  *
- * This class is meant to work with a DatabaseBase object, which manages queries
+ * This class is meant to work with an IDatabase object, which manages queries
  *
  * @since 1.24
  */
index 897e55f..2b058e9 100644 (file)
@@ -128,7 +128,7 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
         * Either a short hexidecimal string if a transaction is active or ""
         *
         * @var string
-        * @see DatabaseBase::mTrxLevel
+        * @see Database::mTrxLevel
         */
        protected $mTrxShortId = '';
        /**
@@ -137,7 +137,7 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
         * point (possibly more up-to-date since the first SELECT defines the snapshot).
         *
         * @var float|null
-        * @see DatabaseBase::mTrxLevel
+        * @see Database::mTrxLevel
         */
        private $mTrxTimestamp = null;
        /** @var float Lag estimate at the time of BEGIN */
@@ -147,21 +147,21 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
         * Used to provide additional context for error reporting.
         *
         * @var string
-        * @see DatabaseBase::mTrxLevel
+        * @see Database::mTrxLevel
         */
        private $mTrxFname = null;
        /**
         * Record if possible write queries were done in the last transaction started
         *
         * @var bool
-        * @see DatabaseBase::mTrxLevel
+        * @see Database::mTrxLevel
         */
        private $mTrxDoneWrites = false;
        /**
         * Record if the current transaction was started implicitly due to DBO_TRX being set.
         *
         * @var bool
-        * @see DatabaseBase::mTrxLevel
+        * @see Database::mTrxLevel
         */
        private $mTrxAutomatic = false;
        /**
@@ -171,7 +171,7 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
         */
        private $mTrxAtomicLevels = [];
        /**
-        * Record if the current transaction was started implicitly by DatabaseBase::startAtomic
+        * Record if the current transaction was started implicitly by Database::startAtomic
         *
         * @var bool
         */
@@ -1101,7 +1101,7 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
         * @param array $options Associative array of options to be turned into
         *   an SQL query, valid keys are listed in the function.
         * @return array
-        * @see DatabaseBase::select()
+        * @see Database::select()
         */
        protected function makeSelectOptions( $options ) {
                $preLimitTail = $postLimitTail = '';
@@ -1189,7 +1189,7 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
         *
         * @param array $options Associative array of options
         * @return string
-        * @see DatabaseBase::select()
+        * @see Database::select()
         * @since 1.21
         */
        protected function makeGroupByWithHaving( $options ) {
@@ -1215,7 +1215,7 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
         *
         * @param array $options Associative array of options
         * @return string
-        * @see DatabaseBase::select()
+        * @see Database::select()
         * @since 1.21
         */
        protected function makeOrderBy( $options ) {
@@ -1420,7 +1420,7 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
        }
 
        /**
-        * Helper for DatabaseBase::insert().
+        * Helper for Database::insert().
         *
         * @param array $options
         * @return string
@@ -1482,7 +1482,7 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
        }
 
        /**
-        * Make UPDATE options array for DatabaseBase::makeUpdateOptions
+        * Make UPDATE options array for Database::makeUpdateOptions
         *
         * @param array $options
         * @return array
@@ -1502,9 +1502,9 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
        }
 
        /**
-        * Make UPDATE options for the DatabaseBase::update function
+        * Make UPDATE options for the Database::update function
         *
-        * @param array $options The options passed to DatabaseBase::update
+        * @param array $options The options passed to Database::update
         * @return string
         */
        protected function makeUpdateOptions( $options ) {
@@ -2701,7 +2701,7 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
        /**
         * Issues the BEGIN command to the database server.
         *
-        * @see DatabaseBase::begin()
+        * @see Database::begin()
         * @param string $fname
         */
        protected function doBegin( $fname ) {
@@ -2760,7 +2760,7 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
        /**
         * Issues the COMMIT command to the database server.
         *
-        * @see DatabaseBase::commit()
+        * @see Database::commit()
         * @param string $fname
         */
        protected function doCommit( $fname ) {
@@ -2807,7 +2807,7 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
        /**
         * Issues the ROLLBACK command to the database server.
         *
-        * @see DatabaseBase::rollback()
+        * @see Database::rollback()
         * @param string $fname
         */
        protected function doRollback( $fname ) {
@@ -2884,7 +2884,7 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
         * necessary. Boolean values are passed through as is, to indicate success
         * of write queries or failure.
         *
-        * Once upon a time, DatabaseBase::query() returned a bare MySQL result
+        * Once upon a time, Database::query() returned a bare MySQL result
         * resource, and it was necessary to call this function to convert it to
         * a wrapper. Nowadays, raw database objects are never exposed to external
         * callers, so this is unnecessary in external code.
index e008705..71e5f93 100644 (file)
  * @ingroup Database
  */
 abstract class DatabaseBase extends Database {
-       /**
-        * Get search engine class. All subclasses of this need to implement this
-        * if they wish to use searching.
-        *
-        * @return string
-        * @deprecated since 1.27; use SearchEngineFactory::getSearchEngineClass()
-        */
-       public function getSearchEngine() {
-               return 'SearchEngineDummy';
-       }
+       // Backwards-compatibility alias for type-hints
 }
index c33d3b3..156e525 100644 (file)
@@ -117,7 +117,7 @@ class DatabaseSqlite extends DatabaseBase {
                $p['schema'] = false;
                $p['tablePrefix'] = '';
 
-               return DatabaseBase::factory( 'sqlite', $p );
+               return Database::factory( 'sqlite', $p );
        }
 
        /**
index 0396ec8..c32a7ff 100644 (file)
@@ -613,7 +613,7 @@ interface IDatabase {
         * for use in field names (e.g. a.user_name).
         *
         * All of the table names given here are automatically run through
-        * DatabaseBase::tableName(), which causes the table prefix (if any) to be
+        * Database::tableName(), which causes the table prefix (if any) to be
         * added, and various other table name mappings to be performed.
         *
         * Do not use untrusted user input as a table name. Alias names should
@@ -895,7 +895,7 @@ interface IDatabase {
         *     IDatabase::affectedRows().
         *
         * @param string $table Table name. This will be passed through
-        *   DatabaseBase::tableName().
+        *   Database::tableName().
         * @param array $a Array of rows to insert
         * @param string $fname Calling function name (use __METHOD__) for logs/profiling
         * @param array $options Array of options
@@ -908,7 +908,7 @@ interface IDatabase {
         * UPDATE wrapper. Takes a condition array and a SET array.
         *
         * @param string $table Name of the table to UPDATE. This will be passed through
-        *   DatabaseBase::tableName().
+        *   Database::tableName().
         * @param array $values An array of values to SET. For each array element,
         *   the key gives the field name, and the value gives the data to set
         *   that field to. The data will be quoted by IDatabase::addQuotes().
@@ -1149,7 +1149,7 @@ interface IDatabase {
         *
         * @since 1.22
         *
-        * @param string $table Table name. This will be passed through DatabaseBase::tableName().
+        * @param string $table Table name. This will be passed through Database::tableName().
         * @param array $rows A single row or list of rows to insert
         * @param array $uniqueIndexes List of single field names or field name tuples
         * @param array $set An array of values to SET. For each array element, the
@@ -1463,8 +1463,8 @@ interface IDatabase {
         *
         * This can be an alternative to explicit startAtomic()/endAtomic() calls.
         *
-        * @see DatabaseBase::startAtomic
-        * @see DatabaseBase::endAtomic
+        * @see Database::startAtomic
+        * @see Database::endAtomic
         *
         * @param string $fname Caller name (usually __METHOD__)
         * @param callable $callback Callback that issues DB updates
index 5dee884..b0b3c87 100644 (file)
@@ -1,8 +1,8 @@
 <?php
 /**
- * Used by DatabaseBase::buildLike() to represent characters that have special
+ * Used by Database::buildLike() to represent characters that have special
  * meaning in SQL LIKE clauses and thus need no escaping. Don't instantiate it
- * manually, use DatabaseBase::anyChar() and anyString() instead.
+ * manually, use Database::anyChar() and anyString() instead.
  */
 class LikeMatch {
        /** @var string */
index ac9217d..002d253 100644 (file)
@@ -40,7 +40,7 @@ class DBQueryError extends DBExpectedError {
         * @param string $fname
         */
        function __construct( IDatabase $db, $error, $errno, $sql, $fname ) {
-               if ( $db instanceof DatabaseBase && $db->wasConnectionError( $errno ) ) {
+               if ( $db instanceof Database && $db->wasConnectionError( $errno ) ) {
                        $message = "A connection error occured. \n" .
                                "Query: $sql\n" .
                                "Function: $fname\n" .
index 7ad275a..37c028b 100644 (file)
@@ -1024,7 +1024,7 @@ class LoadBalancer implements ILoadBalancer {
        }
 
        public function finalizeMasterChanges() {
-               $this->forEachOpenMasterConnection( function ( DatabaseBase $conn ) {
+               $this->forEachOpenMasterConnection( function ( Database $conn ) {
                        // Any error should cause all DB transactions to be rolled back together
                        $conn->setTrxEndCallbackSuppression( false );
                        $conn->runOnTransactionPreCommitCallbacks();
@@ -1077,7 +1077,7 @@ class LoadBalancer implements ILoadBalancer {
 
                $failures = [];
                $this->forEachOpenMasterConnection(
-                       function ( DatabaseBase $conn ) use ( $fname, &$failures ) {
+                       function ( Database $conn ) use ( $fname, &$failures ) {
                                $conn->setTrxEndCallbackSuppression( true );
                                try {
                                        $conn->flushSnapshot( $fname );
@@ -1134,7 +1134,7 @@ class LoadBalancer implements ILoadBalancer {
 
        public function runMasterPostTrxCallbacks( $type ) {
                $e = null; // first exception
-               $this->forEachOpenMasterConnection( function ( DatabaseBase $conn ) use ( $type, &$e ) {
+               $this->forEachOpenMasterConnection( function ( Database $conn ) use ( $type, &$e ) {
                        $conn->setTrxEndCallbackSuppression( false );
                        if ( $conn->writesOrCallbacksPending() ) {
                                // This happens if onTransactionIdle() callbacks leave callbacks on *another* DB
@@ -1181,7 +1181,7 @@ class LoadBalancer implements ILoadBalancer {
        }
 
        public function suppressTransactionEndCallbacks() {
-               $this->forEachOpenMasterConnection( function ( DatabaseBase $conn ) {
+               $this->forEachOpenMasterConnection( function ( Database $conn ) {
                        $conn->setTrxEndCallbackSuppression( true );
                } );
        }
index 0864e5c..1b7545a 100644 (file)
@@ -304,7 +304,7 @@ class VirtualRESTServiceClient {
         */
        private function getInstance( $prefix ) {
                if ( !isset( $this->instances[$prefix] ) ) {
-                       throw new RunTimeException( "No service registered at prefix '{$prefix}'." );
+                       throw new RuntimeException( "No service registered at prefix '{$prefix}'." );
                }
 
                if ( !( $this->instances[$prefix] instanceof VirtualRESTService ) ) {
index 7746d99..21864ee 100644 (file)
@@ -714,6 +714,12 @@ class ManualLogEntry extends LogEntryBase {
                                        $rc = $this->getRecentChange( $newId );
 
                                        if ( $to === 'rc' || $to === 'rcandudp' ) {
+                                               // save RC, passing tags so they are applied there
+                                               $tags = $this->getTags();
+                                               if ( is_null( $tags ) ) {
+                                                       $tags = [];
+                                               }
+                                               $rc->addTags( $tags );
                                                $rc->save( 'pleasedontudp' );
                                        }
 
@@ -727,14 +733,6 @@ class ManualLogEntry extends LogEntryBase {
                                        ) {
                                                PatrolLog::record( $rc, true, $this->getPerformer() );
                                        }
-
-                                       // Add change tags to the log entry and (if applicable) the associated revision
-                                       $tags = $this->getTags();
-                                       if ( !is_null( $tags ) ) {
-                                               $rcId = $rc->getAttribute( 'rc_id' );
-                                               $revId = $this->getAssociatedRevId(); // Use null if $revId is 0
-                                               ChangeTags::addTags( $tags, $rcId, $revId > 0 ? $revId : null, $newId );
-                                       }
                                }
                        },
                        DeferredUpdates::POSTSEND,
index f29c9e4..0cf584b 100644 (file)
@@ -310,7 +310,7 @@ class LogEventsList extends ContextSource {
                        return '';
                }
                $html = '';
-               $html .= xml::label( wfMessage( 'log-action-filter-' . $types[0] )->text(),
+               $html .= Xml::label( wfMessage( 'log-action-filter-' . $types[0] )->text(),
                        'action-filter-' .$types[0] ) . "\n";
                $select = new XmlSelect( 'subtype' );
                $select->addOption( wfMessage( 'log-action-filter-all' )->text(), '' );
@@ -319,7 +319,7 @@ class LogEventsList extends ContextSource {
                        $select->addOption( wfMessage( $msgKey )->text(), $value );
                }
                $select->setDefault( $action );
-               $html .= $select->getHtml();
+               $html .= $select->getHTML();
                return $html;
        }
 
index ccd345c..c86eabd 100644 (file)
@@ -276,7 +276,7 @@ class BitmapHandler extends TransformationalImageHandler {
         */
        protected function transformImageMagickExt( $image, $params ) {
                global $wgSharpenReductionThreshold, $wgSharpenParameter, $wgMaxAnimatedGifArea,
-                       $wgMaxInterlacingAreas, $wgJpegPixelFormat;
+                       $wgJpegPixelFormat;
 
                try {
                        $im = new Imagick();
index 4ca2663..4bc36ba 100644 (file)
@@ -463,16 +463,16 @@ abstract class MediaHandler {
        /**
         * Get an array structure that looks like this:
         *
-        * array(
-        *    'visible' => array(
+        * [
+        *    'visible' => [
         *       'Human-readable name' => 'Human readable value',
         *       ...
-        *    ),
-        *    'collapsed' => array(
+        *    ],
+        *    'collapsed' => [
         *       'Human-readable name' => 'Human readable value',
         *       ...
-        *    )
-        * )
+        *    ]
+        * ]
         * The UI will format this into a table where the visible fields are always
         * visible, and the collapsed fields are optionally visible.
         *
@@ -843,11 +843,11 @@ abstract class MediaHandler {
        /**
         * Gets configuration for the file warning message. Return value of
         * the following structure:
-        *   array(
+        *   [
         *     // Required, module with messages loaded for the client
         *     'module' => 'example.filewarning.messages',
         *     // Required, array of names of messages
-        *     'messages' => array(
+        *     'messages' => [
         *       // Required, main warning message
         *       'main' => 'example-filewarning-main',
         *       // Optional, header for warning dialog
@@ -856,10 +856,10 @@ abstract class MediaHandler {
         *       'footer' => 'example-filewarning-footer',
         *       // Optional, text for more-information link (see below)
         *       'info' => 'example-filewarning-info',
-        *     ),
+        *     ],
         *     // Optional, link for more information
         *     'link' => 'http://example.com',
-        *   )
+        *   ]
         *
         * Returns null if no warning is necessary.
         * @param File $file
index 3287fac..3ebda75 100644 (file)
@@ -302,7 +302,7 @@ abstract class TransformationalImageHandler extends ImageHandler {
         * Values can be one of client, im, custom, gd, imext, or an array
         * of object, method-name to call that specific method.
         *
-        * If specifying a custom scaler command with array( Obj, method ),
+        * If specifying a custom scaler command with [ Obj, method ],
         * the method in question should take 2 parameters, a File object,
         * and a $scalerParams array with various options (See doTransform
         * for what is in $scalerParams). On error it should return a
diff --git a/includes/objectcache/RedisBagOStuff.php b/includes/objectcache/RedisBagOStuff.php
deleted file mode 100644 (file)
index d852f82..0000000
+++ /dev/null
@@ -1,433 +0,0 @@
-<?php
-/**
- * Object caching using Redis (http://redis.io/).
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- */
-
-/**
- * Redis-based caching module for redis server >= 2.6.12
- *
- * @note: avoid use of Redis::MULTI transactions for twemproxy support
- */
-class RedisBagOStuff extends BagOStuff {
-       /** @var RedisConnectionPool */
-       protected $redisPool;
-       /** @var array List of server names */
-       protected $servers;
-       /** @var array Map of (tag => server name) */
-       protected $serverTagMap;
-       /** @var bool */
-       protected $automaticFailover;
-
-       /**
-        * Construct a RedisBagOStuff object. Parameters are:
-        *
-        *   - servers: An array of server names. A server name may be a hostname,
-        *     a hostname/port combination or the absolute path of a UNIX socket.
-        *     If a hostname is specified but no port, the standard port number
-        *     6379 will be used. Arrays keys can be used to specify the tag to
-        *     hash on in place of the host/port. Required.
-        *
-        *   - connectTimeout: The timeout for new connections, in seconds. Optional,
-        *     default is 1 second.
-        *
-        *   - persistent: Set this to true to allow connections to persist across
-        *     multiple web requests. False by default.
-        *
-        *   - password: The authentication password, will be sent to Redis in
-        *     clear text. Optional, if it is unspecified, no AUTH command will be
-        *     sent.
-        *
-        *   - automaticFailover: If this is false, then each key will be mapped to
-        *     a single server, and if that server is down, any requests for that key
-        *     will fail. If this is true, a connection failure will cause the client
-        *     to immediately try the next server in the list (as determined by a
-        *     consistent hashing algorithm). True by default. This has the
-        *     potential to create consistency issues if a server is slow enough to
-        *     flap, for example if it is in swap death.
-        * @param array $params
-        */
-       function __construct( $params ) {
-               parent::__construct( $params );
-               $redisConf = [ 'serializer' => 'none' ]; // manage that in this class
-               foreach ( [ 'connectTimeout', 'persistent', 'password' ] as $opt ) {
-                       if ( isset( $params[$opt] ) ) {
-                               $redisConf[$opt] = $params[$opt];
-                       }
-               }
-               $this->redisPool = RedisConnectionPool::singleton( $redisConf );
-
-               $this->servers = $params['servers'];
-               foreach ( $this->servers as $key => $server ) {
-                       $this->serverTagMap[is_int( $key ) ? $server : $key] = $server;
-               }
-
-               if ( isset( $params['automaticFailover'] ) ) {
-                       $this->automaticFailover = $params['automaticFailover'];
-               } else {
-                       $this->automaticFailover = true;
-               }
-
-               $this->attrMap[self::ATTR_SYNCWRITES] = self::QOS_SYNCWRITES_NONE;
-       }
-
-       protected function doGet( $key, $flags = 0 ) {
-               list( $server, $conn ) = $this->getConnection( $key );
-               if ( !$conn ) {
-                       return false;
-               }
-               try {
-                       $value = $conn->get( $key );
-                       $result = $this->unserialize( $value );
-               } catch ( RedisException $e ) {
-                       $result = false;
-                       $this->handleException( $conn, $e );
-               }
-
-               $this->logRequest( 'get', $key, $server, $result );
-               return $result;
-       }
-
-       public function set( $key, $value, $expiry = 0, $flags = 0 ) {
-               list( $server, $conn ) = $this->getConnection( $key );
-               if ( !$conn ) {
-                       return false;
-               }
-               $expiry = $this->convertToRelative( $expiry );
-               try {
-                       if ( $expiry ) {
-                               $result = $conn->setex( $key, $expiry, $this->serialize( $value ) );
-                       } else {
-                               // No expiry, that is very different from zero expiry in Redis
-                               $result = $conn->set( $key, $this->serialize( $value ) );
-                       }
-               } catch ( RedisException $e ) {
-                       $result = false;
-                       $this->handleException( $conn, $e );
-               }
-
-               $this->logRequest( 'set', $key, $server, $result );
-               return $result;
-       }
-
-       public function delete( $key ) {
-               list( $server, $conn ) = $this->getConnection( $key );
-               if ( !$conn ) {
-                       return false;
-               }
-               try {
-                       $conn->delete( $key );
-                       // Return true even if the key didn't exist
-                       $result = true;
-               } catch ( RedisException $e ) {
-                       $result = false;
-                       $this->handleException( $conn, $e );
-               }
-
-               $this->logRequest( 'delete', $key, $server, $result );
-               return $result;
-       }
-
-       public function getMulti( array $keys, $flags = 0 ) {
-               $batches = [];
-               $conns = [];
-               foreach ( $keys as $key ) {
-                       list( $server, $conn ) = $this->getConnection( $key );
-                       if ( !$conn ) {
-                               continue;
-                       }
-                       $conns[$server] = $conn;
-                       $batches[$server][] = $key;
-               }
-               $result = [];
-               foreach ( $batches as $server => $batchKeys ) {
-                       $conn = $conns[$server];
-                       try {
-                               $conn->multi( Redis::PIPELINE );
-                               foreach ( $batchKeys as $key ) {
-                                       $conn->get( $key );
-                               }
-                               $batchResult = $conn->exec();
-                               if ( $batchResult === false ) {
-                                       $this->debug( "multi request to $server failed" );
-                                       continue;
-                               }
-                               foreach ( $batchResult as $i => $value ) {
-                                       if ( $value !== false ) {
-                                               $result[$batchKeys[$i]] = $this->unserialize( $value );
-                                       }
-                               }
-                       } catch ( RedisException $e ) {
-                               $this->handleException( $conn, $e );
-                       }
-               }
-
-               $this->debug( "getMulti for " . count( $keys ) . " keys " .
-                       "returned " . count( $result ) . " results" );
-               return $result;
-       }
-
-       /**
-        * @param array $data
-        * @param int $expiry
-        * @return bool
-        */
-       public function setMulti( array $data, $expiry = 0 ) {
-               $batches = [];
-               $conns = [];
-               foreach ( $data as $key => $value ) {
-                       list( $server, $conn ) = $this->getConnection( $key );
-                       if ( !$conn ) {
-                               continue;
-                       }
-                       $conns[$server] = $conn;
-                       $batches[$server][] = $key;
-               }
-
-               $expiry = $this->convertToRelative( $expiry );
-               $result = true;
-               foreach ( $batches as $server => $batchKeys ) {
-                       $conn = $conns[$server];
-                       try {
-                               $conn->multi( Redis::PIPELINE );
-                               foreach ( $batchKeys as $key ) {
-                                       if ( $expiry ) {
-                                               $conn->setex( $key, $expiry, $this->serialize( $data[$key] ) );
-                                       } else {
-                                               $conn->set( $key, $this->serialize( $data[$key] ) );
-                                       }
-                               }
-                               $batchResult = $conn->exec();
-                               if ( $batchResult === false ) {
-                                       $this->debug( "setMulti request to $server failed" );
-                                       continue;
-                               }
-                               foreach ( $batchResult as $value ) {
-                                       if ( $value === false ) {
-                                               $result = false;
-                                       }
-                               }
-                       } catch ( RedisException $e ) {
-                               $this->handleException( $server, $conn, $e );
-                               $result = false;
-                       }
-               }
-
-               return $result;
-       }
-
-       public function add( $key, $value, $expiry = 0 ) {
-               list( $server, $conn ) = $this->getConnection( $key );
-               if ( !$conn ) {
-                       return false;
-               }
-               $expiry = $this->convertToRelative( $expiry );
-               try {
-                       if ( $expiry ) {
-                               $result = $conn->set(
-                                       $key,
-                                       $this->serialize( $value ),
-                                       [ 'nx', 'ex' => $expiry ]
-                               );
-                       } else {
-                               $result = $conn->setnx( $key, $this->serialize( $value ) );
-                       }
-               } catch ( RedisException $e ) {
-                       $result = false;
-                       $this->handleException( $conn, $e );
-               }
-
-               $this->logRequest( 'add', $key, $server, $result );
-               return $result;
-       }
-
-       /**
-        * Non-atomic implementation of incr().
-        *
-        * Probably all callers actually want incr() to atomically initialise
-        * values to zero if they don't exist, as provided by the Redis INCR
-        * command. But we are constrained by the memcached-like interface to
-        * return null in that case. Once the key exists, further increments are
-        * atomic.
-        * @param string $key Key to increase
-        * @param int $value Value to add to $key (Default 1)
-        * @return int|bool New value or false on failure
-        */
-       public function incr( $key, $value = 1 ) {
-               list( $server, $conn ) = $this->getConnection( $key );
-               if ( !$conn ) {
-                       return false;
-               }
-               try {
-                       if ( !$conn->exists( $key ) ) {
-                               return null;
-                       }
-                       // @FIXME: on races, the key may have a 0 TTL
-                       $result = $conn->incrBy( $key, $value );
-               } catch ( RedisException $e ) {
-                       $result = false;
-                       $this->handleException( $conn, $e );
-               }
-
-               $this->logRequest( 'incr', $key, $server, $result );
-               return $result;
-       }
-
-       public function changeTTL( $key, $expiry = 0 ) {
-               list( $server, $conn ) = $this->getConnection( $key );
-               if ( !$conn ) {
-                       return false;
-               }
-
-               $expiry = $this->convertToRelative( $expiry );
-               try {
-                       $result = $conn->expire( $key, $expiry );
-               } catch ( RedisException $e ) {
-                       $result = false;
-                       $this->handleException( $conn, $e );
-               }
-
-               $this->logRequest( 'expire', $key, $server, $result );
-               return $result;
-       }
-
-       public function modifySimpleRelayEvent( array $event ) {
-               if ( array_key_exists( 'val', $event ) ) {
-                       $event['val'] = serialize( $event['val'] ); // this class uses PHP serialization
-               }
-
-               return $event;
-       }
-
-       /**
-        * @param mixed $data
-        * @return string
-        */
-       protected function serialize( $data ) {
-               // Serialize anything but integers so INCR/DECR work
-               // Do not store integer-like strings as integers to avoid type confusion (bug 60563)
-               return is_int( $data ) ? $data : serialize( $data );
-       }
-
-       /**
-        * @param string $data
-        * @return mixed
-        */
-       protected function unserialize( $data ) {
-               $int = intval( $data );
-               return $data === (string)$int ? $int : unserialize( $data );
-       }
-
-       /**
-        * Get a Redis object with a connection suitable for fetching the specified key
-        * @param string $key
-        * @return array (server, RedisConnRef) or (false, false)
-        */
-       protected function getConnection( $key ) {
-               $candidates = array_keys( $this->serverTagMap );
-
-               if ( count( $this->servers ) > 1 ) {
-                       ArrayUtils::consistentHashSort( $candidates, $key, '/' );
-                       if ( !$this->automaticFailover ) {
-                               $candidates = array_slice( $candidates, 0, 1 );
-                       }
-               }
-
-               while ( ( $tag = array_shift( $candidates ) ) !== null ) {
-                       $server = $this->serverTagMap[$tag];
-                       $conn = $this->redisPool->getConnection( $server, $this->logger );
-                       if ( !$conn ) {
-                               continue;
-                       }
-
-                       // If automatic failover is enabled, check that the server's link
-                       // to its master (if any) is up -- but only if there are other
-                       // viable candidates left to consider. Also, getMasterLinkStatus()
-                       // does not work with twemproxy, though $candidates will be empty
-                       // by now in such cases.
-                       if ( $this->automaticFailover && $candidates ) {
-                               try {
-                                       if ( $this->getMasterLinkStatus( $conn ) === 'down' ) {
-                                               // If the master cannot be reached, fail-over to the next server.
-                                               // If masters are in data-center A, and replica DBs in data-center B,
-                                               // this helps avoid the case were fail-over happens in A but not
-                                               // to the corresponding server in B (e.g. read/write mismatch).
-                                               continue;
-                                       }
-                               } catch ( RedisException $e ) {
-                                       // Server is not accepting commands
-                                       $this->handleException( $conn, $e );
-                                       continue;
-                               }
-                       }
-
-                       return [ $server, $conn ];
-               }
-
-               $this->setLastError( BagOStuff::ERR_UNREACHABLE );
-
-               return [ false, false ];
-       }
-
-       /**
-        * Check the master link status of a Redis server that is configured as a replica DB.
-        * @param RedisConnRef $conn
-        * @return string|null Master link status (either 'up' or 'down'), or null
-        *  if the server is not a replica DB.
-        */
-       protected function getMasterLinkStatus( RedisConnRef $conn ) {
-               $info = $conn->info();
-               return isset( $info['master_link_status'] )
-                       ? $info['master_link_status']
-                       : null;
-       }
-
-       /**
-        * Log a fatal error
-        * @param string $msg
-        */
-       protected function logError( $msg ) {
-               $this->logger->error( "Redis error: $msg" );
-       }
-
-       /**
-        * The redis extension throws an exception in response to various read, write
-        * and protocol errors. Sometimes it also closes the connection, sometimes
-        * not. The safest response for us is to explicitly destroy the connection
-        * object and let it be reopened during the next request.
-        * @param RedisConnRef $conn
-        * @param Exception $e
-        */
-       protected function handleException( RedisConnRef $conn, $e ) {
-               $this->setLastError( BagOStuff::ERR_UNEXPECTED );
-               $this->redisPool->handleError( $conn, $e );
-       }
-
-       /**
-        * Send information about a single request to the debug log
-        * @param string $method
-        * @param string $key
-        * @param string $server
-        * @param bool $result
-        */
-       public function logRequest( $method, $key, $server, $result ) {
-               $this->debug( "$method $key on $server: " .
-                       ( $result === false ? "failure" : "success" ) );
-       }
-}
index d06213f..47dae78 100644 (file)
@@ -182,7 +182,7 @@ class SqlBagOStuff extends BagOStuff {
                                $this->logger->debug( __CLASS__ . ": connecting to $host" );
                                // Use a blank trx profiler to ignore expections as this is a cache
                                $info['trxProfiler'] = new TransactionProfiler();
-                               $db = DatabaseBase::factory( $type, $info );
+                               $db = Database::factory( $type, $info );
                                $db->clearFlag( DBO_TRX );
                        } else {
                                $index = $this->replicaOnly ? DB_REPLICA : DB_MASTER;
index 50c5030..41e9e4f 100644 (file)
@@ -3502,7 +3502,7 @@ class WikiPage implements Page, IDBAccessObject {
                $dbr = wfGetDB( DB_REPLICA );
                $res = $dbr->select( 'categorylinks',
                        [ 'cl_to AS page_title, ' . NS_CATEGORY . ' AS page_namespace' ],
-                       // Have to do that since DatabaseBase::fieldNamesWithAlias treats numeric indexes
+                       // Have to do that since Database::fieldNamesWithAlias treats numeric indexes
                        // as not being aliases, and NS_CATEGORY is numeric
                        [ 'cl_from' => $id ],
                        __METHOD__ );
index 7c18798..590d51e 100644 (file)
@@ -251,7 +251,7 @@ class Parser {
        protected $mProfiler;
 
        /**
-        * @var \MediaWiki\Linker\LinkRenderer
+        * @var LinkRenderer
         */
        protected $mLinkRenderer;
 
@@ -887,10 +887,10 @@ class Parser {
        }
 
        /**
-        * Get a \MediaWiki\Linker\LinkRenderer instance to make links with
+        * Get a LinkRenderer instance to make links with
         *
         * @since 1.28
-        * @return \MediaWiki\Linker\LinkRenderer
+        * @return LinkRenderer
         */
        public function getLinkRenderer() {
                if ( !$this->mLinkRenderer ) {
index 99556ed..5a15ddf 100644 (file)
@@ -155,6 +155,7 @@ class PoolCounterRedis extends PoolCounter {
 
                // @codingStandardsIgnoreStart Generic.Files.LineLength
                static $script =
+               /** @lang Lua */
 <<<LUA
                local kSlots,kSlotsNextRelease,kWakeup,kWaiting = unpack(KEYS)
                local rMaxWorkers,rExpiry,rSlot,rSlotTime,rAwakeAll,rTime = unpack(ARGV)
@@ -291,6 +292,7 @@ LUA;
         */
        protected function initAndPopPoolSlotList( RedisConnRef $conn, $now ) {
                static $script =
+               /** @lang Lua */
 <<<LUA
                local kSlots,kSlotsNextRelease,kSlotWaits = unpack(KEYS)
                local rMaxWorkers,rMaxQueue,rTimeout,rExpiry,rSess,rTime = unpack(ARGV)
@@ -359,6 +361,7 @@ LUA;
         */
        protected function registerAcquisitionTime( RedisConnRef $conn, $slot, $now ) {
                static $script =
+               /** @lang Lua */
 <<<LUA
                local kSlots,kSlotsNextRelease,kSlotWaits = unpack(KEYS)
                local rSlot,rExpiry,rSess,rTime = unpack(ARGV)
index 6806ee5..6b5316f 100644 (file)
@@ -14,6 +14,15 @@ interface SearchIndexField {
        const INDEX_TYPE_DATETIME = 4;
        const INDEX_TYPE_NESTED = 5;
        const INDEX_TYPE_BOOL = 6;
+
+       /**
+        * SHORT_TEXT is meant to be used with short text made of mostly ascii
+        * technical information. Generally a language agnostic analysis chain
+        * is used and aggressive splitting to increase recall.
+        * E.g suited for mime/type
+        */
+       const INDEX_TYPE_SHORT_TEXT = 7;
+
        /**
         * Generic field flags.
         */
index 3adf5a6..bdf7638 100644 (file)
@@ -43,7 +43,7 @@ abstract class AuthManagerSpecialPage extends SpecialPage {
         * Change the form descriptor that determines how a field will look in the authentication form.
         * Called from fieldInfoToFormDescriptor().
         * @param AuthenticationRequest[] $requests
-        * @param string $fieldInfo Field information array (union of all
+        * @param array $fieldInfo Field information array (union of all
         *    AuthenticationRequest::getFieldInfo() responses).
         * @param array $formDescriptor HTMLForm descriptor. The special key 'weight' can be set to
         *    change the order of the fields.
@@ -205,6 +205,7 @@ abstract class AuthManagerSpecialPage extends SpecialPage {
        /**
         * Return custom message key.
         * Allows subclasses to customize messages.
+        * @param string $defaultKey
         * @return string
         */
        protected function messageKey( $defaultKey ) {
@@ -668,6 +669,7 @@ abstract class AuthManagerSpecialPage extends SpecialPage {
         * Maps an authentication field configuration for a single field (as returned by
         * AuthenticationRequest::getFieldInfo()) to a HTMLForm field descriptor.
         * @param array $singleFieldInfo
+        * @param string $fieldName
         * @return array
         */
        protected static function mapSingleFieldInfo( $singleFieldInfo, $fieldName ) {
index 3697e5d..eee5b64 100644 (file)
@@ -59,7 +59,7 @@ class SpecialPreferences extends SpecialPage {
                        $session->remove( 'specialPreferencesSaveSuccess' );
                        $out->addModuleStyles( 'mediawiki.notification.convertmessagebox.styles' );
 
-                       $out->addHtml(
+                       $out->addHTML(
                                Html::rawElement(
                                        'div',
                                        [
index fc924a4..adf12d4 100644 (file)
@@ -272,7 +272,7 @@ class SpecialRandomInCategory extends FormSpecialPage {
                                'high' => 'MAX( cl_timestamp )'
                        ],
                        [
-                               'cl_to' => $this->category->getDBKey(),
+                               'cl_to' => $this->category->getDBkey(),
                        ],
                        __METHOD__,
                        [
index 8a06abf..433dcab 100644 (file)
@@ -156,7 +156,7 @@ class UserrightsPage extends SpecialPage {
                if ( $request->getCheck( 'success' ) && $this->mFetchedUser !== null ) {
                        $out->addModules( [ 'mediawiki.special.userrights' ] );
                        $out->addModuleStyles( 'mediawiki.notification.convertmessagebox.styles' );
-                       $out->addHtml(
+                       $out->addHTML(
                                Html::rawElement(
                                        'div',
                                        [
index 666f3f9..069b460 100644 (file)
@@ -729,7 +729,7 @@ class BalanceStack implements IteratorAggregate {
                        $this->config['tidyCompat'] && !$isComment &&
                        $this->currentNode->isA( BalanceSets::$tidyPWrapSet )
                ) {
-                       $this->insertHTMLELement( 'mw:p-wrap', [] );
+                       $this->insertHTMLElement( 'mw:p-wrap', [] );
                        return $this->insertText( $value );
                } else {
                        $this->currentNode->appendChild( $value );
index 0d06c7b..6083db9 100644 (file)
@@ -1434,11 +1434,11 @@ class User implements IDBAccessObject {
         * protected against race conditions using a compare-and-set (CAS) mechanism
         * based on comparing $this->mTouched with the user_touched field.
         *
-        * @param DatabaseBase $db
-        * @param array $conditions WHERE conditions for use with DatabaseBase::update
-        * @return array WHERE conditions for use with DatabaseBase::update
+        * @param Database $db
+        * @param array $conditions WHERE conditions for use with Database::update
+        * @return array WHERE conditions for use with Database::update
         */
-       protected function makeUpdateConditions( DatabaseBase $db, array $conditions ) {
+       protected function makeUpdateConditions( Database $db, array $conditions ) {
                if ( $this->mTouched ) {
                        // CAS check: only update if the row wasn't changed sicne it was loaded.
                        $conditions['user_touched'] = $db->timestamp( $this->mTouched );
index b91596b..ca188ba 100644 (file)
@@ -2,6 +2,7 @@ Authors (alphabetically)
 
 Alex Monk <krenair@wikimedia.org>
 Bartosz Dziewoński <bdziewonski@wikimedia.org>
+Brad Jorsch <bjorsch@wikimedia.org>
 Ed Sanders <esanders@wikimedia.org>
 Florian Schmidt <florian.schmidt.welzow@t-online.de>
 James D. Forrester <jforrester@wikimedia.org>
diff --git a/includes/widget/DateTimeInputWidget.php b/includes/widget/DateTimeInputWidget.php
new file mode 100644 (file)
index 0000000..f0d5cdb
--- /dev/null
@@ -0,0 +1,76 @@
+<?php
+/**
+ * MediaWiki Widgets – DateTimeInputWidget class.
+ *
+ * @copyright 2016 MediaWiki Widgets Team and others; see AUTHORS.txt
+ * @license The MIT License (MIT); see LICENSE.txt
+ */
+namespace MediaWiki\Widget;
+
+use OOUI\Tag;
+
+/**
+ * Date-time input widget.
+ */
+class DateTimeInputWidget extends \OOUI\InputWidget {
+
+       protected $type = null;
+       protected $min = null;
+       protected $max = null;
+       protected $clearable = null;
+
+       /**
+        * @param array $config Configuration options
+        * @param string $config['type'] 'date', 'time', or 'datetime'
+        * @param string $config['min'] Minimum date, time, or datetime
+        * @param string $config['max'] Maximum date, time, or datetime
+        * @param bool $config['clearable'] Whether to provide for blanking the value.
+        */
+       public function __construct( array $config = [] ) {
+               // We need $this->type set before calling the parent constructor
+               if ( isset( $config['type'] ) ) {
+                       $this->type = $config['type'];
+               } else {
+                       throw new \InvalidArgumentException( '$config[\'type\'] must be specified' );
+               }
+
+               // Parent constructor
+               parent::__construct( $config );
+
+               // Properties, which are ignored in PHP and just shipped back to JS
+               if ( isset( $config['min'] ) ) {
+                       $this->min = $config['min'];
+               }
+               if ( isset( $config['max'] ) ) {
+                       $this->max = $config['max'];
+               }
+               if ( isset( $config['clearable'] ) ) {
+                       $this->clearable = $config['clearable'];
+               }
+
+               // Initialization
+               $this->addClasses( [ 'mw-widgets-datetime-dateTimeInputWidget' ] );
+       }
+
+       protected function getJavaScriptClassName() {
+               return 'mw.widgets.datetime.DateTimeInputWidget';
+       }
+
+       public function getConfig( &$config ) {
+               $config['type'] = $this->type;
+               if ( $this->min !== null ) {
+                       $config['min'] = $this->min;
+               }
+               if ( $this->max !== null ) {
+                       $config['max'] = $this->max;
+               }
+               if ( $this->clearable !== null ) {
+                       $config['clearable'] = $this->clearable;
+               }
+               return parent::getConfig( $config );
+       }
+
+       protected function getInputElement( $config ) {
+               return ( new Tag( 'input' ) )->setAttributes( [ 'type' => $this->type ] );
+       }
+}
index db71c5c..3e28759 100644 (file)
@@ -2303,7 +2303,7 @@ class Language {
 
        /**
         * Takes a number of seconds and returns an array with a set of corresponding intervals.
-        * For example 65 will be turned into array( minutes => 1, seconds => 5 ).
+        * For example 65 will be turned into [ minutes => 1, seconds => 5 ].
         *
         * @since 1.20
         *
index b31b10f..13ba7e8 100644 (file)
@@ -1086,11 +1086,11 @@ class LanguageConverter {
                        //  -{zh-hans:<span style="font-size:120%;">xxx</span>;zh-hant:\
                        //      <span style="font-size:120%;">yyy</span>;}-
                        // we should split it as:
-                       //  array(
+                       //  [
                        //        [0] => 'zh-hans:<span style="font-size:120%;">xxx</span>'
                        //        [1] => 'zh-hant:<span style="font-size:120%;">yyy</span>'
                        //        [2] => ''
-                       //       )
+                       //  ]
                        $pat = '/;\s*(?=';
                        foreach ( $this->mVariants as $variant ) {
                                // zh-hans:xxx;zh-hant:yyy
index 1e0bb00..87d2127 100644 (file)
@@ -35,7 +35,7 @@ class LanguageKm extends Language {
         */
        function commafy( $_ ) {
                /* NO-op for Khmer. Cannot use
-                * $separatorTransformTable = array( ',' => '' )
+                * $separatorTransformTable = [ ',' => '' ]
                 * That would break when parsing and doing strstr '' => 'foo';
                 */
                return $_;
index 236ae4f..f8b50fc 100644 (file)
@@ -35,7 +35,7 @@ class LanguageMy extends Language {
         */
        function commafy( $_ ) {
                /* NO-op. Cannot use
-                * $separatorTransformTable = array( ',' => '' )
+                * $separatorTransformTable = [ ',' => '' ]
                 * That would break when parsing and doing strstr '' => 'foo';
                 */
                return $_;
index 699185e..88eb4bf 100644 (file)
        "yourpasswordagain": "Pasoë lom lageuëm rahsia:",
        "createacct-yourpasswordagain": "Peunyo lageuëm rahsia",
        "createacct-yourpasswordagain-ph": "Pasoë lom lageuëm rahsia",
-       "remembermypassword": "Ingat lôn tamöng bak peuramban nyoë (keu paléng trép $1 {{PLURAL:$1|uroë|days}})",
        "userlogin-remembermypassword": "Peubiyeuë lôn tamöng",
        "userlogin-signwithsecure": "Ngui server aman",
        "yourdomainname": "Domain droeneuh:",
        "post-expand-template-inclusion-category": "Laman ngön seunipat seunaleuëk nyang leubèh bataih",
        "post-expand-template-argument-warning": "'''Ingat:''' Laman nyoe na paléng h'an saboh alasan seunaleuëk nyang na sunipat èkspansi nyang raya that.\nAlasan-alasan nyan hana geupeureumeuën.",
        "post-expand-template-argument-category": "Laman ngön dalèh seunaleuëk nyang hana geupeureumeuën",
-       "cantcreateaccounttitle": "Han jeut peugöt nan ureueng ngui",
        "cantcreateaccount-text": "Peuneugöt nan ureueng ngui nibak alamat IP ('''$1''') ka geutheun lé [[User:$3|$3]].\n\nDalèh $3 nyoe nakeuh ''$2''",
        "viewpagelogs": "Eu log laman nyoë",
        "nohistory": "Hana riwayat neuandam awai keu ôn nyoe.",
        "search-interwiki-more": "(lom)",
        "searchrelated": "meusambat",
        "searchall": "ban dum",
+       "search-showingresults": "{{PLURAL:$4|Hasé <strong>$1</strong> nibak <strong>$3</strong>|Hasé <strong>$1 - $2</strong> nibak <strong>$3</strong>}}",
        "search-nonefound": "Hana hasé nyang paih lagèë neulakèë",
        "powersearch-legend": "Mita lanjut",
        "powersearch-ns": "Mita bak ruweuëng nan:",
        "exif-orientation": "Orientasi",
        "exif-xresolution": "Resolusi linteuëng",
        "exif-yresolution": "Rèsolusi buju",
+       "exif-datetime": "Uroë buleuën ngön watèë neuubah beureukaih",
        "exif-software": "Software geungui",
        "exif-exifversion": "Versi Exif",
        "exif-colorspace": "Ruweuëng wareuna",
index 5049946..380a919 100644 (file)
        "unlinkaccounts-success": "الحساب تم فك وصله.",
        "authenticationdatachange-ignored": "تغيير بيانات التحقق لم يتم التعامل معه. ربما لم يتم ضبط موفر؟",
        "userjsispublic": "من فضلك لاحظ: صفحات الجافاسكريبت الفرعية لا ينبغي أن تحتوي غلى بيانات سرية بما أنها يمكن رؤيتها بواسطة المستخدمين الآخرين.",
-       "usercssispublic": "من فضل لاحظ: صفحات الCSS الفرعية لا ينبغي أن تحتوي على بيانات سرية بما أنها يمكن رؤيتها بواسطة المستخدمين الآخرين."
+       "usercssispublic": "من فضل لاحظ: صفحات الCSS الفرعية لا ينبغي أن تحتوي على بيانات سرية بما أنها يمكن رؤيتها بواسطة المستخدمين الآخرين.",
+       "restrictionsfield-badip": "عنوان أيبي أو نطاق غير صحيح: $1",
+       "restrictionsfield-label": "نطاقات الأيبي المسموح بها:",
+       "restrictionsfield-help": "عنوان أيبي أو نطاق CIDR واحد لكل سطر. لتفعيل كل شيء، استخدم<br><code>0.0.0.0/0</code><br><code>::/0</code>"
 }
index 1dd05c7..7a4ccf1 100644 (file)
        "yourpasswordagain": "Серһүҙҙе ҡабаттан яҙыу",
        "createacct-yourpasswordagain": "Серһүҙҙе раҫлағыҙ",
        "createacct-yourpasswordagain-ph": "Серһүҙҙе тағы бер тапҡыр яҙығыҙ",
-       "remembermypassword": "Был браузерҙа (иң күбендә $1 {{PLURAL:$1|көнгә}}) иҫәп яҙыуым хәтерләнһен",
        "userlogin-remembermypassword": "Системала ҡалырға",
        "userlogin-signwithsecure": "Һаҡланыулы тоташыу",
        "cannotloginnow-title": "Хәҙер үк инеп булмай",
        "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 исемле роботты өҫтәп булманы. Бәлки өҫтәлгән булғандыр?",
        "undo-failure": "Ара үҙгәртеүҙәр тура килмәү сәбәпле төҙәтеүҙе кире алып булмай.",
        "undo-norev": "Үҙгәртеүҙе кире алып булмай, сөнки юҡ йәки юйылған.",
        "undo-nochange": "Төҙәтеү кире ҡайтарылған.",
-       "undo-summary": "[[Special:Contributions/$2|$2]] ҡулланыусыһының ([[User talk:$2|фекер алышыу]]) $1 үҙгәртеүенән баш тартыу",
+       "undo-summary": "Ҡулланыусы [[Special:Contributions/$2|$2]] ([[User talk:$2|фекер алышыу]]) $1 үҙгәртеүенән баш тартты",
        "undo-summary-username-hidden": "Исеме йәшерелгән ҡатнашыусының төҙәтеүен  $1 кире ҡағыу",
        "cantcreateaccount-text": "Был IP-адрестан (<b>$1</b>) иҫәп яҙыуҙары булдырыу [[User:$3|$3]] тарафынан тыйылған.\n\n$3 белдергән сәбәп: ''$2''",
        "cantcreateaccount-range-text": "{{GENDER:$3|Ҡатнашыусы}} [[User:$3|$3]] һеҙҙең IP-адрес ингән (<strong>$4</strong>) <strong>$1</strong> диапозонында иҫәп яҙмаһын булдырмаҫҡа {{GENDER:$3|тыйыу}} ҡуйҙы.\n\nОшо сәбәп күһәтелгән: $2.",
        "htmlform-title-not-exists": "$1 юҡ",
        "htmlform-user-not-exists": "<strong>$1</strong> ғәмәлдә юҡ",
        "htmlform-user-not-valid": "<strong>$1</strong> — ярамаған иҫәп яҙмаһы",
-       "sqlite-has-fts": "$1, тулы текст буйынса эҙләү мөмкинлеге менән",
-       "sqlite-no-fts": "$1, тулы текст буйынса эҙләү мөмкинлекһеҙ",
        "logentry-delete-delete": "$1 $3 битен {{GENDER:$2|юйҙы}}",
        "logentry-delete-restore": "$1 $3 битен {{GENDER:$2|тергеҙҙе}}",
        "logentry-delete-event": "$1 журналдағы {{PLURAL:$5|яҙманы}} $3: $4 {{GENDER:$2|үҙгәртте}}",
index 5de3609..61fcf51 100644 (file)
        "upload-dialog-disabled": "Загрузка файлаў з дапамогай гэтага дыялёгу адключаная ў гэтай вікі.",
        "upload-dialog-title": "Загрузка файла",
        "upload-dialog-button-cancel": "Адмяніць",
+       "upload-dialog-button-back": "Назад",
        "upload-dialog-button-done": "Зроблена",
        "upload-dialog-button-save": "Захаваць",
        "upload-dialog-button-upload": "Загрузіць",
        "htmlform-cloner-create": "Дадаць больш",
        "htmlform-cloner-delete": "Выдаліць",
        "htmlform-cloner-required": "Патрабуецца як мінімум яшчэ адно значэньне.",
+       "htmlform-date-placeholder": "ГГГГ-ММ-ДД",
        "htmlform-title-badnamespace": "[[:$1]] знаходзіцца не ў прасторы назваў «{{ns:$2}}».",
        "htmlform-title-not-creatable": "«$1» — немагчымы загаловак для старонкі",
        "htmlform-title-not-exists": "$1 не існуе.",
        "log-action-filter-patrol": "Тып патруляваньня:",
        "log-action-filter-protect": "Тып абароны:",
        "log-action-filter-rights": "Тып зьмены правоў:",
+       "log-action-filter-suppress": "Тып хаваньня:",
+       "log-action-filter-upload": "Тып загрузкі:",
        "log-action-filter-all": "Усе",
        "log-action-filter-block-block": "Заблякаваць",
        "log-action-filter-block-reblock": "Зьмяненьне блякаваньня",
index 2a86fbe..e76bb88 100644 (file)
        "eauthentsent": "মনোনীত ই-মেইল ঠিকানায় একটি নিশ্চিতকরণ ই-মেইল পাঠানো হয়েছে।\nঐ অ্যাকাউন্টটে অন্য কোন ই-মেইল পাঠানোর আগে আপনাকে ই-মেইলের নির্দেশগুলি অনুসরণ করতে হবে, যাতে অ্যাকাউন্টটি যে আসলেই আপনার, তা নিশ্চিত হয়।",
        "throttled-mailpassword": "বিগত {{PLURAL:$1|ঘণ্টার|$1 ঘণ্টার}} মধ্যে ইতিমধ্যেই একবার পাসওয়ার্ড বদলের তথ্য পাঠানো হয়েছে। অপব্যবহার রোধে প্রতি {{PLURAL:$1|ঘণ্টায়|$1 ঘণ্টায়}} কেবল একবার পাসওয়ার্ড বদলের তথ্য পাঠানো যাবে।",
        "mailerror": "ইমেইল পাঠাতে সমস্যা: $1",
-       "acct_creation_throttle_hit": "কেউ আপনার আইপি ঠিকানা ব্যবহার করে বিগত সময়ে {{PLURAL:$1|১টি অ্যাকাউন্ট|$1টি অ্যাকাউন্ট}} তৈরি করেছেন, যা এই সময়ের জন্য সর্বোচ্চ অনুমোদনকৃত। ফলে, এই আইপি ঠিকানা থেকে কেউ এই মুহুর্তে নতুন অ্যাকাউন্ট তৈরি করতে পারবে না।",
+       "acct_creation_throttle_hit": "কেউ আপনার আইপি ঠিকানা ব্যবহার করে বিগত $2 {{PLURAL:$1|১টি অ্যাকাউন্ট|$1টি অ্যাকাউন্ট}} তৈরি করেছেন, যা এই সময়ের জন্য সর্বোচ্চ অনুমোদনকৃত। ফলে, এই আইপি ঠিকানা থেকে কেউ এই মুহুর্তে নতুন অ্যাকাউন্ট তৈরি করতে পারবে না।",
        "emailauthenticated": "আপনার ইমেইল ঠিকানাটি $2 তারিখের $3 এ নিশ্চিত করা হয়েছে।",
        "emailnotauthenticated": "আপনার ই-মেইলের ঠিকানা এখনও যাচাই করা হয়নি।\nনিচের বৈশিষ্ট্যগুলোর (features) জন্য কোনো ই-মেইল পাঠানো হবে না।",
        "noemailprefs": "এই বৈশিষ্টটি কাজ করাতে হলে একটি ই-মেইল ঠিকানা নির্ধারণ করতে হবে।",
        "botpasswords-no-central-id": "বট পাসওয়ার্ড ব্যবহার করার জন্য, আপনাকে একটি কেন্দ্রীভূত অ্যাকাউন্টে প্রবেশ করতে হবে।",
        "botpasswords-existing": "বিদ্যমান বট শব্দচাবি",
        "botpasswords-createnew": "একটি নতুন বট পাসওয়ার্ড তৈরি করুন",
-       "botpasswords-editexisting": "à¦\8fà¦\95à¦\9fি à¦¬à¦¿à¦¦à§\8dযমান à¦¬à¦\9f à¦¶à¦¬à§\8dদà¦\9aাবি পরিবর্তন করুন",
+       "botpasswords-editexisting": "à¦\8fà¦\95à¦\9fি à¦¬à¦¿à¦¦à§\8dযমান à¦¬à¦\9f à¦ªà¦¾à¦¸à¦\93য়ারà§\8dড পরিবর্তন করুন",
        "botpasswords-label-appid": "বটের নাম:",
        "botpasswords-label-create": "তৈরি করো",
        "botpasswords-label-update": "হালনাগাদ",
        "grant-group-other": "বিবিধ কার্যকলাপ",
        "grant-createaccount": "অ্যাকাউন্ট তৈরি করুন",
        "grant-createeditmovepage": "পাতা তৈরি, সম্পাদনা এবং স্থানান্তর করুন",
+       "grant-editinterface": "মিডিয়াউইকি নামস্থান এবং ব্যবহারকারীর সিএসএস/জাভাস্ক্রিপ্ট সম্পাদনা করে",
        "grant-editmycssjs": "আপনার সিএসএস/জাভাস্ক্রিপ্ট সম্পাদনা করুন",
        "grant-editmyoptions": "আপনার ব্যবহারকারী পছন্দসমূহ সম্পাদনা করুন",
        "grant-editmywatchlist": "আপনার নজরতালিকা সম্পাদনা করুন",
        "upload-dialog-disabled": "এই ডায়ালগ ব্যবহার করে ফাইল আপলোড করা এই উইকিতে নিষ্ক্রিয় করা হয়েছে।",
        "upload-dialog-title": "ফাইল আপলোড করুন",
        "upload-dialog-button-cancel": "বাতিল",
+       "upload-dialog-button-back": "পিছনে",
        "upload-dialog-button-done": "সম্পন্ন",
        "upload-dialog-button-save": "সংরক্ষণ",
        "upload-dialog-button-upload": "আপলোড",
        "htmlform-cloner-create": "আরও যোগ করুন",
        "htmlform-cloner-delete": "অপসারণ",
        "htmlform-cloner-required": "অন্তত একটি মূল্য আবশ্যক।",
+       "htmlform-date-placeholder": "বববব-মম-দদ",
+       "htmlform-time-placeholder": "ঘঘ:মম:সস",
+       "htmlform-datetime-placeholder": "বববব-মম-দদ ঘঘ:মম:সস",
        "htmlform-title-badnamespace": "[[:$1]] \"{{ns:$2}}\" নামস্থানে খুঁজে পাওয়া যায়নি।",
        "htmlform-title-not-creatable": "\"$1\" সৃষ্টিযোগ্য পাতার শিরোনাম নয়",
        "htmlform-title-not-exists": "$1-এর অস্তিত্ব নেই।",
        "log-action-filter-upload-upload": "নতুন আপলোড",
        "log-action-filter-upload-overwrite": "পুনঃআপলোড",
        "authmanager-authn-no-primary": "সরবরাহকৃত পরিচয়পত্রের অনুমোদন যাচাই করা যায়নি।",
+       "authmanager-authn-autocreate-failed": "একটি স্থানীয় অ্যাকাউন্টের স্বয়ংক্রিয়-সৃষ্টি ব্যর্থ হয়েছে: $1",
        "authmanager-create-disabled": "অ্যাকাউন্ট সৃষ্টিকরণ নিষ্ক্রিয় করা হয়েছে।",
        "authmanager-create-from-login": "আপনার একাউন্ট তৈরি করতে, নীচের ক্ষেত্রগুলি পূরণ করুন।",
        "authmanager-authplugin-setpass-failed-title": "পাসওয়ার্ড পরিবর্তন ব্যর্থ হয়েছে",
        "authmanager-authplugin-setpass-bad-domain": "অবৈধ ডোমেইন।",
        "authmanager-autocreate-noperm": "স্বয়ংক্রিয় অ্যাকাউন্ট সৃষ্টি মঞ্জুরিপ্রাপ্ত নয়।",
        "authmanager-userdoesnotexist": "ব্যবহারকারী অ্যাকাউন্ট \"$1\" অনিবন্ধিত।",
+       "authmanager-username-help": "প্রমাণীকরণের জন্য ব্যবহারকারী নাম।",
+       "authmanager-password-help": "প্রমাণীকরণের জন্য পাসওয়ার্ড।",
+       "authmanager-domain-help": "বহিঃস্থ প্রমাণীকরণের জন্য ডোমেইন।",
+       "authmanager-retype-help": "নিশ্চিত করার জন্য আবার পাসওয়ার্ড লিখুন।",
        "authmanager-email-label": "ইমেইল",
        "authmanager-email-help": "ইমেইল ঠিকানা",
        "authmanager-realname-label": "প্রকৃত নাম",
        "authmanager-realname-help": "ব্যবহারকারীর প্রকৃত নাম",
+       "authmanager-provider-password": "পাসওয়ার্ড-ভিত্তিক প্রমাণীকরণ।",
+       "authmanager-provider-password-domain": "পাসওয়ার্ড ও ডোমেইন-ভিত্তিক প্রমাণীকরণ।",
        "authmanager-provider-temporarypassword": "অস্থায়ী পাসওয়ার্ড",
        "authprovider-confirmlink-success-line": "$1: সংযোগ করা সফল হয়েছে।",
        "authprovider-resetpass-skip-label": "উপেক্ষা করো",
        "credentialsform-provider": "পরিচয়পত্রের ধরন:",
        "credentialsform-account": "অ্যাকাউন্টের নাম:",
        "linkaccounts": "অ্যাকাউন্ট সংযোগ করুন",
+       "linkaccounts-success-text": "অ্যাকাউন্টটি সংযোগ করা হয়েছে।",
        "linkaccounts-submit": "অ্যাকাউন্ট সংযুক্ত করুন",
        "unlinkaccounts": "অ্যাকাউন্ট সংযোগ বিচ্ছিন্ন করুন",
        "unlinkaccounts-success": "অ্যাকাউন্টের সংযোগ বিচ্ছিন্ন করা হয়েছে।",
+       "authenticationdatachange-ignored": "প্রমাণীকরণ উপাত্তের পরিবর্তন পরিচালনা করা হয়নি। হয়তো কোন প্রদানকারী কনফিগার করা হয়নি?",
        "userjsispublic": "অনুগ্রহ করে লক্ষ্য করুন: জাভাস্ক্রিপ্টের উপপাতাগুলিতে গোপনীয় তথ্য থাকা উচিত নয় যেহেতু অন্যান্য ব্যবহারকারীও এগুলি দেখতে পান।",
-       "usercssispublic": "অনুগ্রহ করে লক্ষ্য করুন: সিএসএসের উপপাতাগুলিতে গোপনীয় তথ্য থাকা উচিত নয় যেহেতু অন্যান্য ব্যবহারকারীও এগুলি দেখতে পান।"
+       "usercssispublic": "অনুগ্রহ করে লক্ষ্য করুন: সিএসএসের উপপাতাগুলিতে গোপনীয় তথ্য থাকা উচিত নয় যেহেতু অন্যান্য ব্যবহারকারীও এগুলি দেখতে পান।",
+       "restrictionsfield-badip": "আইপি ঠিকানা অথবা পরিসীমা অবৈধ: $1",
+       "restrictionsfield-label": "অনুমোদিত আইপি পরিসীমা:",
+       "restrictionsfield-help": "লাইন প্রতি একটি আইপি ঠিকানা বা CIDR পরিসীমা। সবকিছু সক্রিয় করতে<br><code>0.0.0.0/0</code><br><code>::/0</code><br>ব্যবহার করুন"
 }
index 92c4cb3..c2b1d88 100644 (file)
        "timezoneregion-indian": "Indijski okean",
        "timezoneregion-pacific": "Tihi okean",
        "allowemail": "Dozvoli e-poštu od ostalih korisnika",
-       "prefs-searchoptions": "Traži",
+       "prefs-searchoptions": "Pretraga",
        "prefs-namespaces": "Imenski prostori",
        "default": "predodređeno",
        "prefs-files": "Datoteke",
index 088c746..d4671b6 100644 (file)
        "botpasswords-label-update": "Карлаяккха",
        "botpasswords-label-cancel": "Юхаяккха",
        "botpasswords-label-delete": "ДӀаяккхар",
-       "botpasswords-label-restrictions": "Лелоран доза тохар:",
        "botpasswords-label-grants-column": "Магийна",
        "botpasswords-bad-appid": "«$1» ботан цӀе магийна яц.",
        "botpasswords-created-body": "Ботан «$1» пароль кхиамца кхоьллина.",
        "upload-http-error": "Даьлла гӀалат HTTP: $1",
        "upload-dialog-title": "Файл чуяккхар",
        "upload-dialog-button-cancel": "Цаоьшу",
+       "upload-dialog-button-back": "Юха",
        "upload-dialog-button-done": "Кийчча ю",
        "upload-dialog-button-save": "Ӏалашъян",
        "upload-dialog-button-upload": "Чуяккха",
        "htmlform-chosen-placeholder": "Харжа кеп",
        "htmlform-cloner-create": "ТӀетоха кхин",
        "htmlform-cloner-delete": "ДӀаяккха",
+       "htmlform-datetime-placeholder": "ШШШШ-ББ-ДД СС:ММ:СС",
        "htmlform-title-not-exists": "«$1» яц.",
        "htmlform-user-not-exists": "<strong>$1</strong> яц.",
        "htmlform-user-not-valid": "<strong>$1</strong> — декъашхочун магийна йоцу цӀе.",
        "special-characters-group-ipa": "ДАЭ (IPA)",
        "special-characters-group-symbols": "Символаш",
        "special-characters-group-greek": "Грекийн",
+       "special-characters-group-greekextended": "Грекийн алсам",
        "special-characters-group-cyrillic": "Кирилан",
        "special-characters-group-arabic": "Ӏарбийн",
-       "special-characters-group-arabicextended": "Iаьрбийн шординарш",
+       "special-characters-group-arabicextended": "Ӏаьрбийн алсам",
        "special-characters-group-persian": "Пхьарсхойн",
        "special-characters-group-hebrew": "Жуьгтийн",
        "special-characters-group-bangla": "Бангалойн",
        "special-characters-group-tamil": "Тамилхойн",
        "special-characters-group-telugu": "Телугойн",
        "special-characters-group-sinhala": "Синхалойн",
-       "special-characters-group-gujarati": "Ð\93Ñ\83жаÑ\80аÑ\82ойн",
+       "special-characters-group-gujarati": "Ð\93Ñ\83джаÑ\80аÑ\82и",
        "special-characters-group-devanagari": "Деванагари",
        "special-characters-group-thai": "Тайхойн",
        "special-characters-group-lao": "Лаохойн",
index d12fe17..b897410 100644 (file)
        "upload-dialog-disabled": "Načítání souborů pomocí tohoto dialogu je na této wiki vypnuto.",
        "upload-dialog-title": "Načtení souboru",
        "upload-dialog-button-cancel": "Storno",
+       "upload-dialog-button-back": "Zpět",
        "upload-dialog-button-done": "Hotovo",
        "upload-dialog-button-save": "Uložit",
        "upload-dialog-button-upload": "Načíst",
        "unlinkaccounts-success": "Propojení účtu bylo zrušeno.",
        "authenticationdatachange-ignored": "Změna autentizačních údajů nebyla zpracována. Možná není nakonfigurován žádný poskytovatel?",
        "userjsispublic": "Uvědomte si prosím, že podstránky s JavaScriptem by neměly obsahovat tajné údaje, protože jsou viditelné ostatním uživatelům.",
-       "usercssispublic": "Uvědomte si prosím, že podstránky s CSS by neměly obsahovat tajné údaje, protože jsou viditelné ostatním uživatelům."
+       "usercssispublic": "Uvědomte si prosím, že podstránky s CSS by neměly obsahovat tajné údaje, protože jsou viditelné ostatním uživatelům.",
+       "restrictionsfield-badip": "Neplatná IP adresa nebo rozsah: $1",
+       "restrictionsfield-label": "Povolené rozsahy IP adres:",
+       "restrictionsfield-help": "Jedna IP adresa nebo CIDR rozsah na řádek. Všechno povolíte pomocí<br><code>0.0.0.0/0</code><br><code>::/0</code>"
 }
index a4df1d5..b764fc0 100644 (file)
        "upload-dialog-disabled": "Dateiuploads mit diesem Dialog sind auf diesem Wiki deaktiviert.",
        "upload-dialog-title": "Datei hochladen",
        "upload-dialog-button-cancel": "Abbrechen",
+       "upload-dialog-button-back": "Zurück",
        "upload-dialog-button-done": "Schließen",
        "upload-dialog-button-save": "Speichern",
        "upload-dialog-button-upload": "Hochladen",
        "htmlform-cloner-create": "Weitere hinzufügen",
        "htmlform-cloner-delete": "Entfernen",
        "htmlform-cloner-required": "Es ist mindestens ein Wert erforderlich.",
+       "htmlform-date-placeholder": "JJJJ-MM-TT",
+       "htmlform-time-placeholder": "HH:MM:SS",
+       "htmlform-datetime-placeholder": "JJJJ-MM-TT HH:MM:SS",
+       "htmlform-date-invalid": "Der eingegebene Wert ist kein erkanntes Datum. Versuche die Verwendung des Formats JJJJ-MM-TT.",
+       "htmlform-time-invalid": "Der eingegebene Wert ist keine erkannte Zeit. Versuche die Verwendung des Formats HH:MM:SS.",
+       "htmlform-datetime-invalid": "Der eingegebene Wert ist kein erkanntes Datum und keine Zeit. Versuche die Verwendung des Formats JJJJ-MM-TT HH:MM:SS.",
+       "htmlform-date-toolow": "Der eingegebene Wert liegt vor dem frühesten erlaubten Datum $1.",
+       "htmlform-date-toohigh": "Der eingegebene Wert liegt nach dem spätesten erlaubten Datum $1.",
+       "htmlform-time-toolow": "Der eingegebene Wert liegt vor der frühesten erlaubten Zeit $1.",
+       "htmlform-time-toohigh": "Der eingegebene Wert liegt nach der spätesten erlaubten Zeit $1.",
+       "htmlform-datetime-toolow": "Der eingegebene Wert liegt vor dem frühesten erlaubten Datum und der Zeit $1.",
+       "htmlform-datetime-toohigh": "Der eingegebene Wert liegt nach dem spätesten erlaubten Datum und der Zeit $1.",
        "htmlform-title-badnamespace": "[[:$1]] ist nicht im Namensraum „{{ns:$2}}“.",
        "htmlform-title-not-creatable": "„$1“ ist kein erstellbarer Seitentitel",
        "htmlform-title-not-exists": "$1 ist nicht vorhanden.",
        "unlinkaccounts-success": "Das Benutzerkonto wurde getrennt.",
        "authenticationdatachange-ignored": "Die Änderung der Authentifizierungsdaten wurde nicht bearbeitet. Vielleicht wurde kein Anbieter konfiguriert?",
        "userjsispublic": "Bitte beachten: JavaScript-Unterseiten sollten keine vertraulichen Daten enthalten, da sie von anderen Benutzern eingesehen werden können.",
-       "usercssispublic": "Bitte beachten: CSS-Unterseiten sollten keine vertraulichen Daten enthalten, da sie von anderen Benutzern eingesehen werden können."
+       "usercssispublic": "Bitte beachten: CSS-Unterseiten sollten keine vertraulichen Daten enthalten, da sie von anderen Benutzern eingesehen werden können.",
+       "restrictionsfield-badip": "Ungültige IP-Adresse oder ungültiger IP-Adressbereich: $1",
+       "restrictionsfield-label": "Erlaubte IP-Adressbereiche:",
+       "restrictionsfield-help": "Eine IP-Adresse oder ein CIDR-Bereich pro Zeile. Um alles zu aktivieren, verwende<br><code>0.0.0.0/0</code><br><code>::/0</code>"
 }
index fa1e589..ad786d5 100644 (file)
@@ -42,6 +42,7 @@
        "tog-watchdefault": "Pel u dosyeyê ke mı vurnayê lista mına seyrkerdışi ke",
        "tog-watchmoves": "Pel u dosyeyê ke mı kırıştê lista mına seyrkerdışi ke",
        "tog-watchdeletion": "Pel u dosyeyê ke mı esterıtê lista mına seyrkerdışi ke",
+       "tog-watchuploads": "Dosya yë kı mı kerdë bar lista seyran kı",
        "tog-watchrollback": "Pelê ke mı peyser ardi inan lista mına seyrkerdışi ke",
        "tog-minordefault": "Vurnayışanê xo pêrune ''vurnayışo qıckek'' nışan bıde",
        "tog-previewontop": "Verqayti pela nuştışi ser de bımocne",
@@ -51,7 +52,7 @@
        "tog-enotifminoredits": "Pelan de vurnayışanê qıckekan u dosyan de ki mı rê e-mail bırışe",
        "tog-enotifrevealaddr": "Adresa e-posteyê mı posteyê xeberan de bımocne",
        "tog-shownumberswatching": "Amarê karberanê seyrkerdoğan bımocne",
-       "tog-oldsig": "İmzaya mewcude:",
+       "tog-oldsig": "İmzaya mewcud:",
        "tog-fancysig": "İmza rê mameleyê wikimeqaley bıke (bê gıreyo otomatik)",
        "tog-uselivepreview": "Verqayto giyane bıgureyne",
        "tog-forceeditsummary": "Mı ke xulasa veng verdaye, hay a mı ser de",
@@ -59,6 +60,7 @@
        "tog-watchlisthidebots": "Lista seyrkerdışi ra vurnayışanê boti bınımne",
        "tog-watchlisthideminor": "Vurnayışanê qıckekan lista mına seyrkerdışi de bınımne",
        "tog-watchlisthideliu": "Lista seyrkerdışi ra vurnayışanê karberanê cıkewteyan bınımne",
+       "tog-watchlistreloadautomatically": "Filtra vıriyayış dı listey seyri otomatikman anewe kı",
        "tog-watchlisthideanons": "Lista seyrkerdışi ra vurnayışanê karberanê anoniman bınımne",
        "tog-watchlisthidepatrolled": "Lista seyrkerdışi ra vurnayışanê qontrolkerdeyan bınımne",
        "tog-watchlisthidecategorization": "Pera kategorizasyoni bınımne",
@@ -67,7 +69,7 @@
        "tog-showhiddencats": "Kategoriyanê nımneya bıasne",
        "tog-norollbackdiff": "Peyser ardışi ra dıme ferqi measne",
        "tog-useeditwarning": "Wexto ke mı yew pela nizami be vurnayışanê nêqeydbiyayeyan caverdê, hay be mı ser de",
-       "tog-prefershttps": "Ronışten akerden de  greyo itimadın bıkarne",
+       "tog-prefershttps": "Ronışten akerden de tım greyo itimadın bıkarne",
        "underline-always": "Tım",
        "underline-never": "Qet",
        "underline-default": "Cild ya zi cıgeyrayoğo hesebiyaye",
        "category-file-count-limited": "{{PLURAL:$1|Dosya cêrêne|$1 Dosyê cêrêni}} na kategoriye derê.",
        "listingcontinuesabbrev": "dewam...",
        "index-category": "Pelê endeksıni",
-       "noindex-category": "Pelê ke zerrekê cı çıniyo",
+       "noindex-category": "Bê indeksın perri",
        "broken-file-category": "Peleye ke gıreyê dosyeyanê ğeletan muhtewa kenê",
        "categoryviewer-pagedlinks": "($1) ($2)",
        "about": "Heqa cı de",
        "article": "Pela zerreki",
        "newwindow": "(pençereyê newey de beno a)",
-       "cancel": "Bıterkın",
+       "cancel": "İbtal",
        "moredotdotdot": "Vêşi...",
-       "morenotlisted": "Vêşi lista nêbi...",
+       "morenotlisted": "Na lista qay kemi ya.",
        "mypage": "Pele",
        "mytalk": "Mesac",
        "anontalk": "Werênayış",
        "newpage": "Pela newiye",
        "talkpage": "Ena pele sero werêne",
        "talkpagelinktext": "werênayış",
-       "specialpage": "Perrê Hısusi",
+       "specialpage": "Perra bağsi",
        "personaltools": "Hacetê şexsiy",
        "articlepage": "Pera zerreki bıvin",
-       "talk": "Hurênayış",
+       "talk": "Vaten",
        "views": "Asayışi",
        "toolbox": "Haceti",
+       "tool-link-userrights": "Grubanê {{GENDER:$1|karberi}} bıvırnë",
+       "tool-link-emailuser": "E-posta ya në{{GENDER:$1|karberi}}",
        "userpage": "Pela karberi bıvêne",
        "projectpage": "Pela proceyi bıvêne",
        "imagepage": "Pera dosya bıasne",
        "jumptonavigation": "Pusula",
        "jumptosearch": "cı geyre",
        "view-pool-error": "Qaytê qısuri mekerên, serverê ma enıka zêde bar gırewto xo ser.\nHedê xo ra zêde karberi kenê ke seyrê na pele bıkerê.\nŞıma rê zehmet, tenê vınderên, heta ke reyna kenê ke ena pele kewê.\n\n$1",
+       "generic-pool-error": "Üzgünüz, şu an sunucular aşırı yüklendi.\nÇok fazla kullanıcı bu sayfayı görüntülemeye çalışıyor.\nLütfen bu sayfaya  tekrar erişmeyi denemeden önce biraz bekleyin.",
        "pool-timeout": "Kılitbiyayışi sero wextê vınetışi",
        "pool-queuefull": "Rêza hewze pırra",
        "pool-errorunknown": "Xeta nêzanıtiye",
+       "pool-servererror": "Amordoğa xızmeti ya istifade nëbena $1",
        "poolcounter-usage-error": "Xırab karyayış:$1",
        "aboutsite": "Heqa {{SITENAME}} de",
        "aboutpage": "Project:Heqa",
        "mainpage": "Pela Seri",
        "mainpage-description": "Pela seri",
        "policy-url": "Project:Terzê hereketi",
-       "portal": "Portalê cemaeti",
-       "portal-url": "Project:Portalê cemaeti",
+       "portal": "Portalë Å\9fëlıgi",
+       "portal-url": "Project:Portalë Å\9fëlıgi",
        "privacy": "Politikaya nımıteyiye",
        "privacypage": "Project:Xısusiyetê nımıtışi",
        "badaccess": "Xeta mısadey",
        "readonly_lag": "Daegeh (database) otomatikmen kılit bi, sureo ke  daegehê bınêni resay daegehê serêni.",
        "internalerror": "Xeta zerreki",
        "internalerror_info": "Xeta zerreki: $1",
+       "internalerror-fatal-exception": "Babet da \"$1\" dı xırab xeta",
        "filecopyerror": "\"$1\" qaydê na \"$2\" dosya nêbeno.",
        "filerenameerror": "nameyê \"$1\" dosya nêvuriya no name \"$2\" ri.",
        "filedeleteerror": "Na \"$1\" dosya hewn a nêşi .",
        "directorycreateerror": "\"$1\" rêzkiyê ey nêvırazya",
+       "directoryreadonlyerror": "Rëzena \"$1\" salt-wanëna.",
+       "directorynotreadableerror": "Rëzena $1 wanebıyayi niya",
        "filenotfound": "Na \"$1\" dosya nêasena.",
        "unexpected": "Endek texmin nêbeni: \"$1\"=\"$2\".",
        "formerror": "Xeta: Form nêerşawiyeno",
        "no-null-revision": "Qandé \"$1\" zew rewizyono newe névıraziya.",
        "badtitle": "Sernameyo xırabın",
        "badtitletext": "Sernameyê pela ke şıma waşt, nêvêrd, vengo ya zi zıwano miyanêno ğelet gırêdaye ya zi sernameyê wiki.\nBeno ke, tede yew ya zi zêdê işareti estê ke sernameyan de nêxebetiyenê.",
+       "title-invalid-empty": "Waziyaye sernamey perrer  venonyana teyna canamey nami sero esto.",
        "perfcached": "Datay cı ver hazır biye. No semedê ra nıkayin niyo! tewr zaf {{PLURAL:$1|netice|$1 netice}} debêno de",
        "perfcachedts": "Cêr de malumatê nımıteyi esti, demdê newe kerdışo peyın: $1. Tewr zaf {{PLURAL:$4|netice|$4 neticey cı}} debyayo de",
        "querypage-no-updates": "Rocanebiyayışê na pele nıka cadayiyê.\nDayiyi tiya nıka newe nêbenê.",
        "createacct-yourpasswordagain-ph": "Parola fına cıkewe",
        "userlogin-remembermypassword": "Mı biya xo viri",
        "userlogin-signwithsecure": "Ebe teqdimkerê asayişın cıkewe",
+       "cannotlogin-title": "Cı nëkewtë",
        "cannotloginnow-title": "Enewke ronıştışo nêabeno",
        "cannotloginnow-text": "$1 karkerdışa ronıştış akerdış mıkum niyo.",
+       "cannotcreateaccount-title": "Nêşenay hesab rakerê",
        "yourdomainname": "Yewdestê şıma:",
        "password-change-forbidden": "Şıma na wiki de nêşenê parola bıvurnê.",
        "externaldberror": "Ya database de xeta esta ya zi heqê şıma çino şıma no hesab bıvurni.",
        "wrongpasswordempty": "Parola tola, venga. tekrar bınuse.",
        "passwordtooshort": "Paroley gani tewr senık be {{PLURAL:$1|1 karakter|$1 karakteran}} derg bê.",
        "passwordtoolong": "Paroleyi be {{PLURAL:$1|1 karakter|$1 karakteran}} ra derg nêbenê.",
+       "passwordtoopopular": "Parolay kehana ker kerıdşi rë mısade nëdeyë no.  Ju parolaya xas bıweçinë",
        "password-name-match": "Parola u nameyê şıma gani zeypê (seypê) nêbo.",
        "password-login-forbidden": "Nameyê nê karberi û gurenayışê parola biyo qedeğen.",
        "mailmypassword": "Parola reset ke",
        "eauthentsent": "Adresok şıma qeyd kerdo wıcayré e-posta rışiyé.\nHetana şıma ne e-posta néwweyniyé, şımaé zewbi e-posta do nérışiyo.",
        "throttled-mailpassword": "Eyarkerdışê parola xora zerreyê {{PLURAL:$1|yew saete|$1 saetan}} erşawiya.\nSeba xırabgurenayışê xızmete ra, her {{PLURAL:$1|yew saete|$1 saetan}} de rey tenya yew eyarkerdışê parola erşawiyeno.",
        "mailerror": "Erşawıtışe xetayê e-posta: $1",
-       "acct_creation_throttle_hit": "Yew ten IP adresê şıma xebıtnayo u kewto no wiki, roco peyin de {{PLURAL:$1|1 hesab|$1 hesab}} vıraşto.\nxulasa ney kesê ke IP adresê şıma xebıtneni hini nêeşkeni ney ra zêdêr hesab akeri.",
+       "acct_creation_throttle_hit": "Yew ten IP adresê şıma xebıtnayo u kewto no wiki, $2roco peyin de {{PLURAL:$1|1 hesabi|$1 hesaban}} vıraşto.\nxulasa ney kesê ke IP adresê şıma xebıtneni hini nêeşkeni ney ra zêdêr hesab akeri.",
        "emailauthenticated": "E-postay şıma $2 sehat $3 dı biya araşt",
        "emailnotauthenticated": "Adresa e-pota da şıma qebul nébiya.\nQandé céréna şımaré teba do nérışiyo.",
        "noemailprefs": "Hesab biyo a.",
        "passwordreset-emailsentemail": "Eke na seba hesabê şıma yew adresa e-posteyê qeydına, yew e-posteyê parola nênkerdışi rışiyeno.",
        "passwordreset-invalideamil": "Adresê eposta raşt niya",
        "changeemail": "E-posta adresa xo wedarne",
-       "changeemail-header": "E-posya adresta hesabdê xo bıvurnê",
+       "changeemail-header": "E-posta adresa xo vuriyayışi rë ena former pır kerë. Eger kı şıma qayılë kı e postay adresi ra wedarnë se formi rıştış dı heruna e posta veng verdë",
        "changeemail-no-info": "Şıma gani bıkewê pele ke derdest bıresê na pele.",
        "changeemail-oldemail": "E-postay şımawa nıkaêne:",
        "changeemail-newemail": "E-postay şımawa newiye:",
        "last": "peyên",
        "page_first": "verên",
        "page_last": "peyên",
-       "histlegend": "Ferqê weçinıtışi: Qutiya versiyonan seba têversanayış işaret ke û dest be ''enter''i ya zi gocega cêrêne ro ne.<br />\nCedwel: <strong>({{int:ferq}})</strong> = ferqê verziyonê peyêni, <strong>({{int:peyên}})</strong> = ferqê versiyonê verêni, <strong>{{int:q}}</strong> = vurnayışo werdi.",
+       "histlegend": "Ferqê weçinayışi: Qutiya versiyonan seba têversanayış işaret ke u dest be ''enter''i ya zi gocega cêrêne ro ne.<br />\nCetwel: <strong>({{int:ferq}})</strong> = ferqê verziyonê peyêni, <strong>({{int:peyên}})</strong> = ferqê versiyonê verêni, <strong>{{int:q}}</strong> = vurnayışo werdi yo.",
        "history-fieldset-title": "Çımberz verori",
        "history-show-deleted": "Tenya esterıtey",
        "histfirst": "Verênêr",
        "search-category": "(kategori $1)",
        "search-file-match": "(zerreyê dosya yewbini gêno)",
        "search-suggest": "To va: $1",
-       "search-rewritten": "Neticey $ ra asenê.  Herunda ney wa neticey $2 ra bıasê?",
+       "search-rewritten": "Neticey $ ra asenê.  Herunda ney wa neticanë $2'i bıvin",
        "search-interwiki-caption": "Proceyê bıray",
        "search-interwiki-default": "$1 ra neticey:",
        "search-interwiki-more": "(véşi)",
        "prefs-labs": "Xacetê labs",
        "prefs-user-pages": "Pelê karberi",
        "prefs-personal": "Pela karberi",
-       "prefs-rc": "Vırnayışë newey",
+       "prefs-rc": "Vuriyayışë peyëni",
        "prefs-watchlist": "Lista seyrkerdışi",
        "prefs-editwatchlist": "Lista seyrkerdışi bıvurne",
        "prefs-editwatchlist-label": "Listey serkerdışanê cıkewtışi timar kerê",
        "nchanges": "$1 {{PLURAL:$1|vurnayış|vurnayışi}}",
        "enhancedrc-since-last-visit": "$1 {{PLURAL:$1|ziyaretê peyêni ra nata}}",
        "enhancedrc-history": "tarix",
-       "recentchanges": "Vırnayışë newey",
+       "recentchanges": "Vuriyayışë peyëni",
        "recentchanges-legend": "Tercihê vurnayışanê peyênan",
        "recentchanges-summary": "Wiki sero vurriyayışê peyêni asenê.",
        "recentchanges-noresult": "Goreyê kriteranê kıfşkerdeyan ra qet yew vurnayış nêvêniya.",
        "undeletepagetext": "{{PLURAL:$1|pelo|$1 pelo}} cerın hewn a şiyo labele hema zi arşiv de yo u tepiya geriyeno.\nArşiv daimi pak beno.",
        "undelete-fieldset-title": "revizyonan tepiya bar ker",
        "undeleteextrahelp": "Qey ardışê pel u verê pelani tuşê '''tepiya biya!'''yi bıtıknê. qey ciya ciya ardışê verê pelani zi qutiye tesdiqi nişane kerê u tuşê '''tepiya biya!'''yi bıtıknê '''''{{int:undeletebtn}}'''''.. qey hewn a kerdışê qutiya tesdiqan u qey sıfır kerdışê cayê sebebani zi tuşê '''agêr caverd/aça ker'''i bıtıknê '''''{{int:undeletebtn}}'''''..",
-       "undeleterevisions": "$1 {{PLURAL:$1|revizyon|revizyon}} arşiw bi",
+       "undeleterevisions": "$1 {{PLURAL:$1|revizyon|revizyon}} esteriya yë",
        "undeletehistory": "eke şıma pel tepiya biyari heme revizyonî zi tepiya yeni.\neke yew pel hewn a biyo u pê nameyê o peli newe ra yew pel bıvıraziyo, revizyonê o pelê verıni zerreyê no pel de aseno.",
        "undeleterevdel": "eke pelo serın de netice bıdo ya zi revizyoni qısmen hewn a bıbiy hewn a kerdışi tepiya nêgeriyeno.",
        "undeletehistorynoadmin": "na madde hewn a biya. sebebê hewna kerdışi u teferruatê karber ê ke maddeyi vıraştı cêr de diyayî. revizyonê hewn a biyayeyani têna serkari vineni",
        "undeletedrevisions": "pêro piya{{PLURAL:$1|1 qeyd|$1 qeyd}} tepiya anciya.",
        "undeletedrevisions-files": "{{PLURAL:$1|1 revizyon|$1 revizyon}} u {{PLURAL:$2|1 dosya|$2 dosya}} ameyê halê xo yê verıni",
        "undeletedfiles": "{{PLURAL:$1|1 dosya|$1 dosya}} tepiya anciyayi.",
-       "cannotundelete": "Besternayışo nêbeno:\n$1",
+       "cannotundelete": "Besternayışonhemembyana tayno nêbeno:\n$1",
        "undeletedpage": "'''$1 pel tepiya anciya'''\n\nqey karê tepiya ardışi u qey karê hewn a kerdışê verıni bıewnê [[Special:Log/delete|qeydê hewn a kerdışi]].",
        "undelete-header": "Peleyê ke veror de besterneyayê êna bıvinê: [[Special:Log/delete|qeydê esterneya]].",
        "undelete-search-title": "Bıgeyre pelanê eserıtiyan",
        "sp-contributions-newbies-sub": "Qe hesebê newe",
        "sp-contributions-newbies-title": "Îştîrakê karberî ser hesabê neweyî",
        "sp-contributions-blocklog": "qeydê kılitbiyayeyi",
-       "sp-contributions-deleted": "iştırakê karberi esterdi",
+       "sp-contributions-deleted": "iştırakê {{GENDER:$1|karberi}} esterdi",
        "sp-contributions-uploads": "Barkerdışi",
        "sp-contributions-logs": "qeydi",
        "sp-contributions-talk": "werênayış",
        "tooltip-p-logo": "Pela seri bıvêne",
        "tooltip-n-mainpage": "Şo pela seri",
        "tooltip-n-mainpage-description": "Şo pela seri",
-       "tooltip-n-portal": "Heqa proceyi de, çı şenay bıkerê, çı koti vêniyeno",
+       "tooltip-n-portal": "Heqa proceyi de, kes çı şeno bıkero, çı koti vêniyeno",
        "tooltip-n-currentevents": "Vurnayışanê peyênan de melumatê pey bıvêne",
        "tooltip-n-recentchanges": "Wiki de yew lista vurriyayışanê peyênan",
        "tooltip-n-randompage": "Pelê da raştameyiye bar ke",
        "tooltip-ca-nstab-category": "Pela kategoriye bıvêne",
        "tooltip-minoredit": "Nay vırnayışa werdi nışan bıkeré",
        "tooltip-save": "Vurnayışanê xo qeyd ke",
+       "tooltip-publish": "Vurnayışê xo vıla kı",
        "tooltip-preview": "Vurnayışané ğo çımra ravyarné. Verdé qeyd kerdışi eneri bıkarné!",
        "tooltip-diff": "Metni sero vurnayışan mocneno",
        "tooltip-compareselectedversions": "Ena per de ferqê rewziyonan de dı weçinaya bıvinê",
        "pageinfo-article-id": "Kamiya pele",
        "pageinfo-language": "Zıwanê zerreyê pele",
        "pageinfo-content-model": "Modela zerreka perer",
+       "pageinfo-content-model-change": "bıvurne",
        "pageinfo-robot-policy": "Weziyetê motor de cıgeyrayışi",
        "pageinfo-robot-index": "İndeksbiyayen",
        "pageinfo-robot-noindex": "İndeksnêbiyayen",
        "pageinfo-watchers": "Amariya pela serykeran",
+       "pageinfo-visiting-watchers": "Amora merdumanë vuriyayışanë peyënan weynayan",
        "pageinfo-few-watchers": "$1 ra tayê {{PLURAL:$1|seyrker|seyrkeri}}",
        "pageinfo-redirects-name": "Hetenayışê na perer",
        "pageinfo-redirects-value": "$1",
        "newimages-summary": "Ena pela xasi dosyayi ke peni de bar biyayeyi mocnane.",
        "newimages-legend": "Avrêc",
        "newimages-label": "Nameyê dosya ( ya zi parçe ey)",
+       "newimages-showbots": "Selaganë boti bıvin",
+       "newimages-hidepatrolled": "Selaganë dewriyeyan bıvinë",
        "noimages": "Çik çini yo.",
        "ilsubmit": "Cı geyre",
        "bydate": "goreyê zemani",
        "exif-compression-34712": "JPEG2000",
        "exif-copyrighted-true": "Heqê telifiye",
        "exif-copyrighted-false": "Telifiya waziyeta eyara",
+       "exif-photometricinterpretation-1": "Siya u sıpe (siya 0)",
        "exif-photometricinterpretation-2": "RGB",
        "exif-photometricinterpretation-6": "YCbCr",
        "exif-unknowndate": "Tarix nizanyano",
        "watchlistedit-clear-legend": "Lista serykerdışê pak kerê",
        "watchlistedit-clear-explain": "Listeya serykerdış da şıma dı sernamey pêro besteryay",
        "watchlistedit-clear-titles": "Sernamey:",
+       "watchlisttools-clear": "Lista serykerdışê xo pak kı",
        "watchlisttools-view": "Vurnayışanê elaqedaran bıvêne",
        "watchlisttools-edit": "Lista seyrkerdışi bıvêne û bıvurne",
        "watchlisttools-raw": "Lista seyrkerdışia xame bıvurne",
        "hebrew-calendar-m12-gen": "Elul",
        "signature": "[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1|mesac]])",
        "timezone-utc": "[[UTC]]",
+       "timezone-local": "Lokal",
        "duplicate-defaultsort": "'''Tembe:''' Hesıbyaye sırmey ratnayış de \"$2\" sırmey ratnayış de \"$1\"i nêhesıbneno.",
        "version": "Versiyon",
        "version-extensions": "Ekstensiyonî ke ronaye",
index 02def5d..45a79b0 100644 (file)
@@ -35,7 +35,7 @@
        "tog-enotifminoredits": "पानाहरू र फाइलहरूमी सामान्य सम्पादन भयालै मुइलाई ई-मेल गरियोस्",
        "tog-enotifrevealaddr": "जानकारी इ-मेलहरूमी मेरो इ-मेल खुलाउन्या",
        "tog-shownumberswatching": "निगरानी गरिरहेका प्रयोगकर्ताहरूको संख्या धेखाउन्या",
-       "tog-oldsig": "अहिलको हस्ताक्षर:",
+       "tog-oldsig": "तमरà¥\8b à¤\85हिलà¤\95à¥\8b à¤¹à¤¸à¥\8dताà¤\95à¥\8dषर:",
        "tog-fancysig": "मेरा दस्तखतलाई विकि पाठको रुपमी लिने (स्वत लिङ्क बिना)",
        "tog-uselivepreview": "प्रत्यक्ष पैल्लीकोरुप प्रयोग गर",
        "tog-forceeditsummary": "खाली सम्पादन शीर्षक प्रविष्टि गरेपछा मलाई सोधन्या",
@@ -52,7 +52,7 @@
        "tog-showhiddencats": "लुकाइएका श्रेणीहरू धेखाउन्या",
        "tog-norollbackdiff": "पैलास्थितिमी फर्काएपछा भिन्नता हटाउन्या",
        "tog-useeditwarning": "सम्पादनहरू सङ्ग्रह नगरिएका अवस्थामी अर्को पानामी जान खोज्या चेतावनी धेखाउन्या",
-       "tog-prefershttps": "पà¥\8dरवà¥\87श à¤\97रà¥\8dदा जबलै सुरक्षित जडानको प्रयोग गर्न्या",
+       "tog-prefershttps": "पà¥\8dरवà¥\87श à¤\97रनà¥\8dà¤\9cà¥\8dया जबलै सुरक्षित जडानको प्रयोग गर्न्या",
        "underline-always": "सधैं",
        "underline-never": "कभैई नाई",
        "underline-default": "खोल अथवा ब्राउजर पैलीकाजसो",
        "talk": "कुरणिकाआनी",
        "views": "अवलोकन गरऽ",
        "toolbox": "औजारअन",
+       "tool-link-userrights": "परिवर्तन{{GENDER:$1|प्रयोगकर्ता}}समूहहरू",
+       "tool-link-emailuser": "यो ईमेल{{GENDER:$|प्रयोगकर्ता}}",
        "userpage": "प्रयोगकर्ता पाना हेर्न्या",
        "projectpage": "प्रोजेक्ट पानो हेर्न्या",
        "imagepage": "चित्र पानो हेर",
index f43b50c..dfe09b4 100644 (file)
        "eauthentsent": "Un mesâg ed cunfèirma l'é stê spidî a l'indirés ed pôsta eletrônica sgnê ché. L'utèint per prèir inviêr di mesâg ed pôsta eletrônica al dēv andêr a drē al j istrusiòun scréti, in môd da cunfermêr ch' l'é ló al legétim proprietâri 'd l'indirés.",
        "throttled-mailpassword": "Un mesâg ed pôsta eletrônica 'd arnōv ed la cêva 'd ingrès l'é bèle stê inviê da mēno 'd {{PLURAL:$1|1 ōra|$1 ōri}}. Per pervèder abûş, la funziòun 'd arnōv ed la cêva 'd ingrès la pōl èser druvêda sōl 'na vôlta ògni {{PLURAL:$1|1 ōra|$1 ōri}}.",
        "mailerror": "Erōr int la spedisiòun dal mesâg $1",
-       "acct_creation_throttle_hit": "{{PLURAL:$1|1 registrasiòun l'é bèle stêda fâta |$1 registrasiòun în bèle stêdi fâti}} da quelchidûn cun al tó 'stès indirés IP int l'ûltem dé: l'é al mâsim permés in cól peréiod ed tèimp ché. Per còst j utèint che drōven cl 'indirés IP ché, p'r al mumèint,  an 's pōl mìa registrêr.",
+       "acct_creation_throttle_hit": "{{PLURAL:$1|1 registrasiòun l'é bèle stêda fâta |$1 registrasiòun în bèle stêdi fâti}} da quelchidûn cun al tó 'stès indirés IP int l'ûltem $2, ch'l'é al mâsim permés in cól peréiod ed tèimp ché. Per còst j utèint che drōven cl 'indirés IP ché, p'r al mumèint,  an 's pōl mìa registrêr.",
        "emailauthenticated": "L'indirés ed pôsta eletrônica l'é stê cunfermê al $2 al $3.",
        "emailnotauthenticated": "L'indirés ed pôsta eletrônica an n'é mìa incòra stê cunfermê.\nA gnirâ mìa spidî mesâg ed pôsta eletrônica p'r al funsiòun in elèinch ché sòta.",
        "noemailprefs": "Scréver un indirés ed pôsta eletrônica per fêr funsionêr st' al funsiòun.",
        "group-bot-member": "{{GENDER:$1|bot}}",
        "group-sysop-member": "{{GENDER:$1|aministradōr}}",
        "group-bureaucrat-member": "{{GENDER:$1|funsionâri}}",
-       "group-suppress-member": "{{GENDER:$1|oversight}}",
+       "group-suppress-member": "{{GENDER:$1|suppressor}}",
        "grouppage-user": "{{ns:project}}:Utèint",
        "grouppage-autoconfirmed": "{{ns:project}}:Utèint convalidê da per ló",
        "grouppage-bot": "{{ns:project}}:Bot",
        "grouppage-sysop": "{{ns:project}}:Aministradōr",
        "grouppage-bureaucrat": "{{ns:project}}:Funsionâri",
-       "grouppage-suppress": "{{ns:project}}:Oversight",
+       "grouppage-suppress": "{{ns:project}}:Suppressor",
        "right-read": "Al lēş al pàgini",
        "right-edit": "Mudéfica pàgini",
        "right-createpage": "Ét pō fêr al pàgini (fōra che 'l pàgini 'd discusiòun).",
        "right-override-export-depth": "Pôrta fōra al pàgini cun insèm al pàgini coleghêdi per 'na larghèsa ed 5",
        "right-sendemail": "Spidés pôsta eletrônica a êter utèint",
        "right-passwordreset": "A vèd i mesâg 'd arnōv ed la cêva 'ed ingrès",
-       "right-managechangetags": "Fà e tó via i [[Special:Tags|tag]] dal databêş",
+       "right-managechangetags": "Fa e mèt in funsiòun/blôca al j [[Special:Tags|etichèti]]",
        "right-applychangetags": "Tâca dal [[Special:Tags|tichèti]] al tō mudéfichi",
        "right-changetags": "Zûta e tó via [[Special:Tags|tichèti]] precîşi só versiòun ónichi o vōş ed regéster",
        "newuserlogpage": "Utèint nōv",
        "rightslogtext": "Ché sòt a gh' é la lésta dal mudéfichi a i dirét dê a j utèint.",
        "action-read": "lēzer cla pàgina ché",
        "action-edit": "Mudifichêr cla pàgina ché",
-       "action-createpage": "inventêr pàgini",
-       "action-createtalk": "fêr 'l pàgini 'd discusiòun.",
+       "action-createpage": "fà cla pàgina ché",
+       "action-createtalk": "fêr cla pàgina 'd discusiòun ché.",
        "action-createaccount": "fêr cla registrasiòun ché",
        "action-history": "vèder la stôria 'd cla pàgina ché",
        "action-minoredit": "sgnêr cla mudéfica che cme céca",
        "action-viewmyprivateinfo": "guêrda al tō infurmasiòun personêli",
        "action-editmyprivateinfo": "mudéfica al tō infurmasiòun personêli",
        "action-editcontentmodel": "câmbia al mudèl dèinter a 'na pàgina",
-       "action-managechangetags": "fà e tó via i tag dal databêÅ\9f",
+       "action-managechangetags": "fêr e mèter in funsiòun/bluchêr al j etichèti",
        "action-applychangetags": "tachêr dal tichèti al tō mudéfichi",
        "action-changetags": "zuntêr o tōr via tichèti precîşi só versiòun ónichi o vōş ed regéster",
        "nchanges": "$1\n{{PLURAL:$1|mudéfica|mudéfichi}}",
        "newpageletter": "N",
        "boteditletter": "b",
        "number_of_watching_users_pageview": "[vésta da {{PLURAL:$1|un utèint|$1 utèint}}]",
-       "rc_categories": "Lémita al categoréi (divîşi da \"|\")",
-       "rc_categories_any": "Bast' ech sia",
+       "rc_categories": "Lémita al categoréi (separêdi da \"|\")",
+       "rc_categories_any": "Bast' ech sia fra còli sgnêdi",
        "rc-change-size-new": "$1 {{PLURAL:$1|byte|byte}} dôp la mudéfica",
        "newsectionsummary": "/* $1 */ sesiòn nōva",
        "rc-enhanced-expand": "Fà vèder i particulêr.",
        "backend-fail-read": "An n'é mìa pusébil lēzer al file \"$1\".",
        "backend-fail-create": "An n'é mìa pusébil fêr al file \"$1\".",
        "backend-fail-maxsize": "L'é impusébil fêr al file \"$1\" perché l'é pió grôs ed {{PLURAL:$2|un|$2}} byte.",
-       "backend-fail-readonly": "Al prugrâma 'd memôria \"$1\" adèsa a 's pōl sōl lēzer. La ragiòun dêda l'é: \"$2\".",
+       "backend-fail-readonly": "Al prugrâma 'd memôria \"$1\" adèsa a 's pōl sōl lēzer. La ragiòun dêda l'é: <em>$2</em>.",
        "backend-fail-synced": "Al file \"$1\" l'é in un stêt mìa lôgich cun al sistēma 'd la memôria intêrna.",
        "backend-fail-connect": "Impusébil coleghêres al sistēma 'd memôria \"$1\".",
        "backend-fail-internal": "É sucès un erōr mìa cgnusû int al sistēma  ed memôria \"$1\".",
        "whatlinkshere-prev": "{{PLURAL:$1|còl préma|quî préma $1}}",
        "whatlinkshere-next": "{{PLURAL:$1|còl dôp|quî dôp $1}}",
        "whatlinkshere-links": "← colegamèint",
-       "whatlinkshere-hideredirs": "$1redirect",
+       "whatlinkshere-hideredirs": "$1 redirect",
        "whatlinkshere-hidetrans": "$1 uniòun",
        "whatlinkshere-hidelinks": "$1 colegamèint",
        "whatlinkshere-hideimages": "$1 colegamèint da file",
        "import-upload-filename": "Nòm dal file:",
        "import-comment": "Argumèint:",
        "import-upload": "Cârga infurmasiòun XML",
-       "tooltip-pt-userpage": "La  pàgina utèint",
-       "tooltip-pt-mytalk": "La  pàgina 'd discusiòun.",
-       "tooltip-pt-preferences": "Al  preferèinsi.",
+       "tooltip-pt-userpage": "La {{GENDER:|tó}} pàgina utèint",
+       "tooltip-pt-mytalk": "La {{GENDER:|tó}} pàgina 'd discusiòun.",
+       "tooltip-pt-preferences": "Al  {{GENDER:|tó}} preferèinsi.",
        "tooltip-pt-watchlist": "Elèinch dal pàgini che t'é drē tgnîr sòt ôc.",
-       "tooltip-pt-mycontris": "Elèinch di  lavōr.",
+       "tooltip-pt-mycontris": "Elèinch di {{GENDER:|tō}}  lavōr.",
        "tooltip-pt-login": "A 's cunsélia 'd fêr la registrasiòun, ânca s' an n'é mia ubligatôri.",
        "tooltip-pt-logout": "Và fōra",
        "tooltip-ca-talk": "Guêrda al discusiòun relatîvi a cla pàgina chè.",
-       "tooltip-ca-edit": "Ét pō mudifiche cla pàgina ché. Per piaşèir drōva al ptòun \"Guêrda préma 'd salvêr\" per vèder còl che t'é fât.",
+       "tooltip-ca-edit": "Mudéfica cla pàgina ché",
        "tooltip-ca-addsection": "Cumîncia 'na sesiòun nōva.",
        "tooltip-ca-viewsource": "Cla pàgina ché l'é sòta prutesiòun, mó 't pō vèder al só côdis surzéia.",
        "tooltip-ca-history": "Versiòun ed préma fâti a cla pàgina ché.",
        "tooltip-t-whatlinkshere": "Elèinch ed tót' al pàgini ch'în coleghêdi a còsta.",
        "tooltip-t-recentchangeslinked": "Elèinch dal j ûltmi mudéfichi al pàgini coleghêdi a còsta.",
        "tooltip-feed-atom": "Feed Atom per cla pàgina ché.",
-       "tooltip-t-contributions": "Lèsta di lavōr fât da cl'utèint ché.",
-       "tooltip-t-emailuser": "Mânda un mesâg cun la pòsta eletrônica a cl'utèint ché",
+       "tooltip-t-contributions": "Lèsta di lavōr fât da {{GENDER:$1|cl'utèint|cl'utèinta}}  ché.",
+       "tooltip-t-emailuser": "Mânda un mesâg cun la pòsta eletrônica a{{GENDER:$1|cl'utèint|cl'utèinta}}  ché",
        "tooltip-t-upload": "Cârga un file",
        "tooltip-t-specialpages": "Elèinch ed tót al pàgini specêli",
        "tooltip-t-print": "Per stampêr cla pàgina ché.",
        "tooltip-t-permalink": "Colegamèint fés a cla versiòun ché 'd  la pàgina.",
        "tooltip-ca-nstab-main": "Guêrda la pàgina",
        "tooltip-ca-nstab-user": "Guêrda la pàgina utèint",
-       "tooltip-ca-nstab-special": "Còsta ché l'é 'na pàgina specêlal l'an pōl mìa èser mudifichêda",
+       "tooltip-ca-nstab-special": "Còsta ché l'é 'na pàgina specêla l'an pōl mìa èser mudifichêda",
        "tooltip-ca-nstab-project": "Guêrda la pàgina dal prugèt",
        "tooltip-ca-nstab-image": "Guêrda la pàgina dal file",
        "tooltip-ca-nstab-template": "Guêrda 'l mudèl",
index a684a3f..615c4c1 100644 (file)
@@ -77,7 +77,7 @@
        "tog-enotifminoredits": "Να μου αποστέλλεται μήνυμα ηλεκτρονικού ταχυδρομείου και για αλλαγές μικρής κλίμακας σε σελίδες και αρχεία",
        "tog-enotifrevealaddr": "Αποκάλυψη της ηλεκτρονικής μου διεύθυνσης σε ειδοποιήσεις ηλεκτρονικού ταχυδρομείου",
        "tog-shownumberswatching": "Εμφάνιση του αριθμού των συνδεδεμένων χρηστών",
-       "tog-oldsig": "Î¥Ï\80άÏ\81Ï\87οÏ\85Ï\83α Ï\85Ï\80ογÏ\81αÏ\86ή:",
+       "tog-oldsig": "Î\97 Ï\84Ï\81έÏ\87οÏ\85Ï\83α Ï\85Ï\80ογÏ\81αÏ\86ή Ï\83αÏ\82:",
        "tog-fancysig": "Μεταχείριση υπογραφής ως κώδικα wiki (χωρίς αυτόματο σύνδεσμο)",
        "tog-uselivepreview": "Χρήση προεπισκόπησης σε ζωντανό χρόνο",
        "tog-forceeditsummary": "Να ειδοποιούμαι κατά την εισαγωγή κενής σύνοψης επεξεργασίας",
@@ -94,7 +94,7 @@
        "tog-showhiddencats": "Εμφάνιση κρυμμένων κατηγοριών",
        "tog-norollbackdiff": "Παράλειψη εμφάνισης διαφορών μετά την εκτέλεση επαναφοράς",
        "tog-useeditwarning": "Προειδοποίηση όταν εγκαταλείπω μία σελίδα επεξεργασίας χωρίς να έχω πρώτα αποθηκεύσει τις αλλαγές",
-       "tog-prefershttps": "Να γίνεται πάντα χρήση ασφαλούς σύνδεσης όταν ο χρήστης είναι συνδεδεμένος",
+       "tog-prefershttps": "Να γίνεται πάντα χρήση ασφαλούς σύνδεσης ενώ είμαι σε σύνδεση",
        "underline-always": "Πάντα",
        "underline-never": "Ποτέ",
        "underline-default": "Προεπιλογή από θέμα εμφάνισης ή από περιηγητή",
        "category-file-count-limited": "Η τρέχουσα κατηγορία περιέχει {{PLURAL:$1|το ακόλουθο αρχείο|τα ακόλουθα $1 αρχεία}}.",
        "listingcontinuesabbrev": "συνεχίζεται",
        "index-category": "Σελίδες καταλογογραφημένες για μηχανές αναζήτησης",
-       "noindex-category": "Σελίδες μη καταλογογραφημένες για μηχανές αναζήτησης",
+       "noindex-category": "Σελίδες μη καταλογογραφημένες",
        "broken-file-category": "Σελίδες με κατεστραμμένους συνδέσμους",
        "about": "Σχετικά",
        "article": "Σελίδα περιεχομένου",
        "newwindow": "(ανοίγει σε ξεχωριστό παράθυρο)",
        "cancel": "Ακύρωση",
        "moredotdotdot": "Περισσότερα...",
-       "morenotlisted": "Î\91Ï\85Ï\84ή Î· Î»Î¯Ï\83Ï\84α Î´ÎµÎ½ ÎµÎ¯Î½Î±Î¹ Ï\80λήÏ\81ης.",
+       "morenotlisted": "Î\91Ï\85Ï\84ή Î· Î»Î¯Ï\83Ï\84α Î¼Ï\80οÏ\81εί Î½Î± ÎµÎ¯Î½Î±Î¹ ÎµÎ»Î»Î¹Ï\80ής.",
        "mypage": "Σελίδα",
        "mytalk": "Συζήτηση",
        "anontalk": "Σελίδα συζήτησης αυτής της διεύθυνσης IP",
        "talk": "Συζήτηση",
        "views": "Προβολές",
        "toolbox": "Εργαλεία",
+       "tool-link-userrights": "Αλλαγή ομάδων {{GENDER:$1|χρήστη}}",
+       "tool-link-emailuser": "Αποστολή e-mail {{GENDER:$1|στο|στη}} χρήστη",
        "userpage": "Προβολή σελίδας χρήστη",
        "projectpage": "Προβολή σελίδας εγχειρήματος",
        "imagepage": "Προβολή σελίδας αρχείου",
        "eauthentsent": "Ένα μήνυμα επαλήθευσης έχει σταλεί στην ηλεκτρονική διεύθυνση που έχετε δηλώσει.\nΠριν αρχίσει η αποστολή μηνυμάτων στη συγκεκριμένη διεύθυνση, πρέπει να ακολουθήσετε τις οδηγίες που βρίσκονται στο μήνυμα που σας έχει σταλεί, για να επαληθεύσετε ότι η συγκεκριμένη ηλεκτρονική διεύθυνση ανήκει πραγματικά σε εσάς.",
        "throttled-mailpassword": "Ένα email επαναφοράς κωδικού έχει ήδη αποσταλεί, μέσα {{PLURAL:$1|στην τελευταία ώρα|στις τελευταίες $1 ώρες}}.\nΓια την αποφυγή κατάχρησης, μόνο ένα email επαναφοράς κωδικού θα στέλνεται ανά {{PLURAL:$1|ώρα|$1 ώρες}}.",
        "mailerror": "Σφάλμα στην αποστολή του μηνύματος: $1",
-       "acct_creation_throttle_hit": "Î\95Ï\80ιÏ\83κέÏ\80Ï\84εÏ\82 Î±Ï\85Ï\84οÏ\8d Ï\84οÏ\85 wiki Î¼Îµ Ï\84ην Î´Î¹ÎµÏ\8dθÏ\85νÏ\83η IP Ï\83αÏ\82 Î­Ï\87οÏ\85ν Î®Î´Î· Î´Î·Î¼Î¹Î¿Ï\85Ï\81γήÏ\83ει {{PLURAL:$1|ένα Î»Î¿Î³Î±Ï\81ιαÏ\83μÏ\8c|$1 Î»Î¿Î³Î±Ï\81ιαÏ\83μοÏ\8dÏ\82}}, ÎºÎ±Ï\84ά Ï\84ην Ï\84ελεÏ\85Ï\84αία Î¼Î¯Î± Î·Î¼Î­Ï\81α, που είναι και ο μέγιστος επιτρεπόμενος αριθμός.\nΩς αποτέλεσμα, επισκέπτες αυτού του wiki με αυτήν την διεύθυνση IP δεν μπορούν αυτή την στιγμή να δημιουργήσουν περισσότερους λογαριασμούς.",
+       "acct_creation_throttle_hit": "Î\95Ï\80ιÏ\83κέÏ\80Ï\84εÏ\82 Î±Ï\85Ï\84οÏ\8d Ï\84οÏ\85 wiki Î¼Îµ Ï\84ην Î´Î¹ÎµÏ\8dθÏ\85νÏ\83η IP Ï\83αÏ\82 Î­Ï\87οÏ\85ν Î®Î´Î· Î´Î·Î¼Î¹Î¿Ï\85Ï\81γήÏ\83ει {{PLURAL:$1|ένα Î»Î¿Î³Î±Ï\81ιαÏ\83μÏ\8c|$1 Î»Î¿Î³Î±Ï\81ιαÏ\83μοÏ\8dÏ\82}}, ÎºÎ±Ï\84ά Ï\83ε Ï\80εÏ\81ίοδο $2, που είναι και ο μέγιστος επιτρεπόμενος αριθμός.\nΩς αποτέλεσμα, επισκέπτες αυτού του wiki με αυτήν την διεύθυνση IP δεν μπορούν αυτή την στιγμή να δημιουργήσουν περισσότερους λογαριασμούς.",
        "emailauthenticated": "Η διεύθυνσή σας ηλεκτρονικού ταχυδρομείου επιβεβαιώθηκε στις $2 και ώρα $3.",
        "emailnotauthenticated": "Η ηλεκτρονική σας διεύθυνση δεν έχει επαληθευτεί ακόμα.\nΚανένα μήνυμα ηλεκτρονικού ταχυδρομείου δεν θα σταλεί για τις ακόλουθες λειτουργίες.",
        "noemailprefs": "Δεν έχει ορισθεί ηλεκτρονική διεύθυνση, οι λειτουργίες που ακολουθούν δεν θα είναι δυνατόν να ολοκληρωθούν.",
        "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": "Αποτυχία να προστεθεί το όνομα bot \"$1\". Έχει ήδη προστεθεί;",
        "botpasswords-updated-body": "Ο κωδικός πρόσβασης του ρομπότ «$1» του χρήστη «$2» ενημερώθηκε.",
        "botpasswords-deleted-title": "Ο κωδικός πρόσβασης του ρομπότ διαγράφτηκε",
        "botpasswords-deleted-body": "Ο κωδικός πρόσβασης για το όνομα ρομπότ \"$1\" του χρήστη \"$2\" διαγράφηκε.",
-       "botpasswords-newpassword": "Ο νέος κωδικός πρόσβασης για να συνδεθείτε με το <strong>$1</strong> είναι <strong>$2</strong>. <em>Παρακαλούμε σημειώστε το για μελλοντική αναφορά.</em>",
+       "botpasswords-newpassword": "Ο νέος κωδικός πρόσβασης για να συνδεθείτε με το <strong>$1</strong> είναι <strong>$2</strong>. <em>Παρακαλούμε σημειώστε το για μελλοντική αναφορά.</em><br />(Για παλιά bot που απαιτούν το όνομα σύνδεσης να είναι το ίδιο με το τελικό όνομα χρήστη, μπορείτε επίσης να χρησιμοποιήσετε το  <strong>$3</strong> ως όνομα χρήστη και <strong>$4</strong> ως κωδικό.)",
        "botpasswords-no-provider": "BotPasswordsSessionProvider δεν είναι διαθέσιμο.",
        "botpasswords-restriction-failed": "Περιορισμοί κωδικών πρόσβασης bot εμποδίζουν τη συγκεκριμένη σύνδεση.",
        "resetpass_forbidden": "Οι κωδικοί πρόσβασης δεν μπορούν να αλλαχθούν",
        "revdelete-unsuppress": "Αφαίρεσε περιορισμούς στις αποκατεστημένες αναθεωρήσεις",
        "revdelete-log": "Αιτία:",
        "revdelete-submit": "Εφαρμογή {{PLURAL:$1|στην επιλεγμένη αναθεώρηση|στις επιλεγμένες αναθεωρήσεις}}",
-       "revdelete-success": "'''Η ορατότητα έκδοσης ενημερώθηκε επιτυχώς.'''",
+       "revdelete-success": "Η ορατότητα έκδοσης ενημερώθηκε επιτυχώς.",
        "revdelete-failure": "'''Η ορατότητα της επεξεργασίας δεν ήταν δυνατόν να ενημερωθεί:''' $1",
        "logdelete-success": "Η ορατότητα γεγονότος τέθηκε επιτυχώς.",
        "logdelete-failure": "'''Η ορατότητα του καταλόγου δεν μπορούσε να ρυθμιστεί:'''\n$1",
        "apisandbox-sending-request": "Αποστολή αιτήματος API...",
        "apisandbox-loading-results": "Λήψη αποτελεσμάτων API...",
        "apisandbox-request-url-label": "Αίτηση URL:",
-       "apisandbox-request-time": "Χρόνος αιτήματος: $1",
+       "apisandbox-request-time": "Χρόνος αιτήματος: {{PLURAL:$1|$1 ms}}",
        "booksources": "Πηγές βιβλίων",
        "booksources-search-legend": "Αναζήτηση για πηγές βιβλίων",
        "booksources-isbn": "ISBN:",
        "sp-contributions-newbies-title": "Συνεισφορές χρηστών για νέους λογαριασμούς",
        "sp-contributions-blocklog": "αρχείο καταγραφών φραγών",
        "sp-contributions-suppresslog": "διαγεγραμμένες συνεισφορές {{GENDER:$1|χρήστη|χρήστριας}}",
-       "sp-contributions-deleted": "διαγεγραμμένες συνεισφορές χρήστη",
+       "sp-contributions-deleted": "διαγεγραμμένες συνεισφορές {{GENDER:$1|χρήστη|χρήστριας}}",
        "sp-contributions-uploads": "ανεβάσματα αρχείων",
        "sp-contributions-logs": "καταγραφές",
        "sp-contributions-talk": "συζήτηση",
        "import-nonewrevisions": "Καμία αναθεώρηση δεν εισήχθει (όλες είτε ήταν ήδη παρούσες, ή παραλήφθηκαν λόγω σφαλμάτων).",
        "xml-error-string": "$1 στη γραμμή $2, στήλη $3 (byte $4): $5",
        "import-upload": "Ανέβασμα δεδομένων XML",
-       "import-token-mismatch": "Απώλεια των στοιχείων της συνόδου. Παρακαλούμε προσπαθήστε ξανά.",
+       "import-token-mismatch": "Απώλεια δεδομένων περιόδου λειτουργίας.\n\nΜπορεί να έχουν αποσυνδεθεί. <strong>Παρακαλούμε βεβαιωθείτε ότι είστε ακόμα συνδεδεμένοι και προσπαθήστε ξανά</strong>.\nΑν εξακολουθεί να μην λειτουργεί, δοκιμάστε να [[Special:UserLogout|αποσυνδεθείτε]] και επανασυνδεθείτε, και ελέγξτε ότι ο browser σας επιτρέπει cookies από αυτό τον ιστοτόπο.",
        "import-invalid-interwiki": "Δεν είναι δυνατή η εισαγωγή από το καθορισμένο wiki.",
        "import-error-edit": "Η σελίδα «$1» δεν εισήχθη επειδή δεν σας επιτρέπεται να την επεξεργαστείτε.",
        "import-error-create": "Η σελίδα «$1» δεν εισήχθη επειδή δεν σας επιτρέπεται να την δημιουργήσετε.",
        "pageinfo-article-id": "Αναγνωριστικό σελίδας",
        "pageinfo-language": "Γλώσσα περιεχομένου σελίδας",
        "pageinfo-content-model": "Μοντέλο περιεχομένου σελίδας",
+       "pageinfo-content-model-change": "αλλαγή",
        "pageinfo-robot-policy": "Ευρετηρίαση από ρομπότ",
        "pageinfo-robot-index": "Επιτρεπτό",
        "pageinfo-robot-noindex": "Μη επιτρεπτό",
        "scarytranscludefailed-httpstatus": "[Η λήψη προτύπου απέτυχε για  το $1: HTTP  $2]",
        "scarytranscludetoolong": "[Η διεύθυνση URL είναι πολύ μεγάλη.]",
        "deletedwhileediting": "'''Προσοχή''': Αυτή η σελίδα έχει διαγραφεί αφότου ξεκινήσατε την επεξεργασία!",
-       "confirmrecreate": "Ο χρήστης [[User:$1|$1]] ([[User talk:$1|συζήτηση]]) διέγραψε αυτή τη σελίδα αφότου ξεκινήσατε την επεξεργασία με αιτιολόγηση:\n: ''$2''\nΠαρακαλώ επιβεβαιώστε ότι θέλετε πραγματικά να ξαναδημιουργήσετε αυτή τη σελίδα.",
-       "confirmrecreate-noreason": "Ο χρήστης [[User:$1|$1]] ([[User talk:$1|συζήτηση]]) διέγραψε αυτή τη σελίδα αφότου ξεκινήσατε την επεξεργασία.\nΠαρακαλούμε επιβεβαιώστε ότι θέλετε πραγματικά να ξαναδημιουργήσετε αυτή τη σελίδα.",
+       "confirmrecreate": "Ο χρήστης [[User:$1|$1]] ([[User talk:$1|συζήτηση]]) διέγραψε αυτή τη σελίδα αφότου ξεκινήσατε την επεξεργασία με αιτιολόγηση:\n: <em>$2</em>\nΠαρακαλούμε επιβεβαιώστε ότι θέλετε πραγματικά να ξαναδημιουργήσετε αυτή τη σελίδα.",
+       "confirmrecreate-noreason": "{{GENDER:$1|Ο χρήστης|Η χρήστρια}} [[User:$1|$1]] ([[User talk:$1|συζήτηση]]) διέγραψε αυτή τη σελίδα αφότου ξεκινήσατε την επεξεργασία.\nΠαρακαλούμε επιβεβαιώστε ότι θέλετε πραγματικά να ξαναδημιουργήσετε αυτή τη σελίδα.",
        "recreate": "Αναδημιουργία",
        "confirm_purge_button": "Εντάξει",
        "confirm-purge-top": "Καθαρισμός της λανθάνουσας μνήμης αυτής της σελίδας.",
        "tags-actions-header": "Ενέργειες",
        "tags-active-yes": "Ναι",
        "tags-active-no": "Όχι",
-       "tags-source-extension": "Î\9fÏ\81ιζÏ\8cμενη Î±Ï\80Ï\8c ÎµÏ\80έκÏ\84αÏ\83η",
+       "tags-source-extension": "Î\9fÏ\81ίζεÏ\84αι Î±Ï\80Ï\8c Ï\84ο Î»Î¿Î³Î¹Ï\83μικÏ\8c",
        "tags-source-manual": "Εφαρμοζόμενη με μη αυτόματο τρόπο από χρήστες και ρομπότ",
        "tags-source-none": "Όχι σε χρήση πλέον",
        "tags-edit": "επεξεργασία",
        "htmlform-title-not-exists": "Το $1 δεν υπάρχει.",
        "htmlform-user-not-exists": "Δεν υπάρχει χρήστης με όνομα <strong>$1</strong>.",
        "htmlform-user-not-valid": "Το <strong>$1</strong> δεν είναι έγκυρο όνομα χρήστη.",
-       "sqlite-has-fts": "$1 με υποστήριξη αναζήτησης πλήρους κειμένου",
-       "sqlite-no-fts": "$1 χωρίς την υποστήριξη αναζήτησης πλήρους κειμένου",
        "logentry-delete-delete": "{{GENDER:$2|Ο|Η}} $1 διέγραψε τη σελίδα $3",
        "logentry-delete-restore": "Ο/Η $1 αποκατέστησε τη σελίδα $3",
        "logentry-delete-event": "{{GENDER:$2|Ο|Η}} $1 άλλαξε την ορατότητα {{PLURAL:$5|ενός καταγραφόμενου συμβάντος|$5 καταγραφόμενων συμβάντων}} στο $3: $4",
index 460ae5a..cbe755d 100644 (file)
        "upload-dialog-disabled": "File uploads using this dialog are disabled on this wiki.",
        "upload-dialog-title": "Upload file",
        "upload-dialog-button-cancel": "Cancel",
+       "upload-dialog-button-back": "Back",
        "upload-dialog-button-done": "Done",
        "upload-dialog-button-save": "Save",
        "upload-dialog-button-upload": "Upload",
        "htmlform-cloner-create": "Add more",
        "htmlform-cloner-delete": "Remove",
        "htmlform-cloner-required": "At least one value is required.",
+       "htmlform-date-placeholder": "YYYY-MM-DD",
+       "htmlform-time-placeholder": "HH:MM:SS",
+       "htmlform-datetime-placeholder": "YYYY-MM-DD HH:MM:SS",
+       "htmlform-date-invalid": "The value you specified is not a recognized date. Try using YYYY-MM-DD format.",
+       "htmlform-time-invalid": "The value you specified is not a recognized time. Try using HH:MM:SS format.",
+       "htmlform-datetime-invalid": "The value you specified is not a recognized date and time. Try using YYYY-MM-DD HH:MM:SS format.",
+       "htmlform-date-toolow": "The value you specified is before the earliest allowed date of $1.",
+       "htmlform-date-toohigh": "The value you specified is after the latest allowed date of $1.",
+       "htmlform-time-toolow": "The value you specified is before the earliest allowed time of $1.",
+       "htmlform-time-toohigh": "The value you specified is after the latest allowed time of $1.",
+       "htmlform-datetime-toolow": "The value you specified is before the earliest allowed date and time of $1.",
+       "htmlform-datetime-toohigh": "The value you specified is after the latest allowed date and time of $1.",
        "htmlform-title-badnamespace": "[[:$1]] is not in the \"{{ns:$2}}\" namespace.",
        "htmlform-title-not-creatable": "\"$1\" is not a creatable page title",
        "htmlform-title-not-exists": "$1 does not exist.",
index 58e0ab1..5cbe965 100644 (file)
@@ -76,7 +76,7 @@
        "tog-enotifminoredits": "Sendi al mi ankaŭ retmesaĝojn pro malgrandaj redaktoj de paĝoj kaj dosieroj",
        "tog-enotifrevealaddr": "Malkaŝi mian retadreson en informaj retpoŝtaĵoj",
        "tog-shownumberswatching": "Montri la nombron da priatentaj uzantoj",
-       "tog-oldsig": "Ekzistanta subskribo:",
+       "tog-oldsig": "Via ekzistanta subskribo:",
        "tog-fancysig": "Trakti subskribon kiel vikitekston (sen aŭtomata ligo)",
        "tog-uselivepreview": "Uzadi tujan antaŭrigardon",
        "tog-forceeditsummary": "Averti min kiam mi konservas malplenan redaktoresumon",
@@ -93,7 +93,7 @@
        "tog-showhiddencats": "Montri kaŝitajn kategoriojn",
        "tog-norollbackdiff": "Ne montri diferencon post plenumado de ŝanĝomalfaro",
        "tog-useeditwarning": "Averti min kiam mi forlasas redaktan paĝon kun nekonservitaj ŝanĝoj",
-       "tog-prefershttps": "Ĉiam uzu sekuran konekton ensalutite",
+       "tog-prefershttps": "Ĉiam uzi sekuran konekton ensalutite",
        "underline-always": "Ĉiam",
        "underline-never": "Neniam",
        "underline-default": "Pravaloro laŭ foliumilo",
        "newwindow": "(en nova fenestro)",
        "cancel": "Nuligi",
        "moredotdotdot": "Pli...",
-       "morenotlisted": "Ĉi tiu listo ne estas kompleta.",
+       "morenotlisted": "Ĉi tiu listo povas esti nekompleta.",
        "mypage": "Paĝo",
        "mytalk": "Diskuto",
        "anontalk": "Diskuto",
        "eauthentsent": "Konfirma retmesaĝo estis sendita al la nomita retadreso. Antaŭ ol iu ajn alia mesaĝo estos sendita al la konto, vi devos sekvi la instrukciojn en la mesaĝo por konfirmi ke la konto ja estas via.",
        "throttled-mailpassword": "Retpoŝto kun reŝargita pasvorto estis jam sendita ene de la {{PLURAL:$1|lasta horo|lastaj $1 horoj}}.\nPor preventi misuzon, nur unu reŝargita pasvorto estos sendita dum {{PLURAL:$1|horo|$1 horoj}}.",
        "mailerror": "Okazis eraro sendante retpoŝtaĵon: $1",
-       "acct_creation_throttle_hit": "Vizitintoj al ĉi tiu vikio uzintaj vian IP-adreson kreis {{PLURAL:$1|1 konton|$1 kontojn}} dum la lasta tago, {{PLURAL:$1|kiu|kiuj}} estas la maksimume permesita en ĉi tiu tempoperiodo.\nTial, vizitantoj kun ĉi tiu IP-adreso ne povas krei pliajn kontojn ĉi-momente.",
+       "acct_creation_throttle_hit": "Vizitintoj al ĉi tiu vikio uzintaj vian IP-adreson kreis {{PLURAL:$1|1 konton|$1 kontojn}} dum la lasta $2, kio estas la maksimumo permesita en ĉi tiu tempoperiodo.\nTial, vizitantoj kun ĉi tiu IP-adreso ne povas krei pliajn kontojn ĉi-momente.",
        "emailauthenticated": "Via retadreso estis konfirmita ekde $2 je $3.",
        "emailnotauthenticated": "Via retadreso ne jam estas aŭtentigata.\nNeniu retpoŝto estos sendita por iu el la jenaj funkcioj.",
        "noemailprefs": "Donu retpoŝtan adreson en viaj preferoj, por ke ĉi tiuj funkcioj estu je dispono.",
        "watchlist-hide": "Kaŝi",
        "watchlist-submit": "Montri",
        "wlshowtime": "Vidigenda tempodaŭro:",
-       "wlshowhideminor": "Etaj redaktoj",
-       "wlshowhidebots": "robotoj",
-       "wlshowhideliu": "registritaj uzantoj",
-       "wlshowhideanons": "anonimaj uzantoj",
+       "wlshowhideminor": "etajn redaktojn",
+       "wlshowhidebots": "robotojn",
+       "wlshowhideliu": "registritajn uzantojn",
+       "wlshowhideanons": "anonimajn uzantojn",
        "wlshowhidepatr": "patrolitaj redaktoj",
-       "wlshowhidemine": "miaj redaktoj",
-       "wlshowhidecategorization": "paĝa enkategoriigo.",
+       "wlshowhidemine": "miajn redaktojn",
+       "wlshowhidecategorization": "kategoriigon de paĝoj",
        "watchlist-options": "Opcioj por atentaro",
        "watching": "Aldonata al la atentaro...",
        "unwatching": "Malatentante...",
        "undeletedrevisions": "{{PLURAL:$1|1 versio restarigita|$1 versioj restarigitaj}}",
        "undeletedrevisions-files": "{{PLURAL:$1|1 versio|$1 versioj}} kaj {{PLURAL:$2|1 dosiero|$2 dosieroj}} restarigitaj",
        "undeletedfiles": "{{PLURAL:$1|1 dosiero restarigita|$1 dosieroj restarigitaj}}",
-       "cannotundelete": "Restarigo malsukcesis: \n$1",
+       "cannotundelete": "Iu aŭ ĉiuj restarigoj malsukcesis: \n$1",
        "undeletedpage": "'''$1 estis restarigita'''\n\nKonsultu la [[Special:Log/delete|deletion log]] por protokolo pri la lastatempaj forigoj kaj restarigoj.",
        "undelete-header": "Konsulti la [[Special:Log/delete|protokolo de forigoj]] por lastatempaj forigoj.",
        "undelete-search-title": "Serĉi forigitajn paĝojn",
        "tags-actions-header": "Agoj",
        "tags-active-yes": "Jes",
        "tags-active-no": "Ne",
-       "tags-source-extension": "Difinita de etendaĵo",
+       "tags-source-extension": "Difinita de la programo",
        "tags-source-manual": "Aldonita permane de uzantoj aŭ robotoj",
        "tags-source-none": "Ne plu uzata",
        "tags-edit": "redakti",
index 26c79ef..04d8760 100644 (file)
        "upload-dialog-disabled": "En este wiki están desactivadas las subidas de archivos mediante este cuadro de diálogo.",
        "upload-dialog-title": "Subir archivo",
        "upload-dialog-button-cancel": "Cancelar",
+       "upload-dialog-button-back": "Volver",
        "upload-dialog-button-done": "Hecho",
        "upload-dialog-button-save": "Guardar",
        "upload-dialog-button-upload": "Subir",
        "tags-actions-header": "Acciones",
        "tags-active-yes": "Sí",
        "tags-active-no": "No",
-       "tags-source-extension": "Definida por una extensión",
+       "tags-source-extension": "Definida por el software",
        "tags-source-manual": "Aplicada manualmente por usuarios y bots",
        "tags-source-none": "No se utiliza más",
        "tags-edit": "editar",
        "htmlform-cloner-create": "Añadir más",
        "htmlform-cloner-delete": "Eliminar",
        "htmlform-cloner-required": "Se requiere al menos un valor.",
+       "htmlform-date-placeholder": "AAAA-MM-DD",
+       "htmlform-time-placeholder": "HH:MM:SS",
+       "htmlform-datetime-placeholder": "AAAA-MM-DD HH:MM:SS",
+       "htmlform-date-invalid": "No se reconoció la fecha en el formato proporcionado. Prueba a usar el formato AAAA-MM-DD.",
+       "htmlform-time-invalid": "No se reconoció la hora en el formato proporcionado. Prueba a usar el formato HH:MM:SS.",
+       "htmlform-datetime-invalid": "No se reconoció la fecha y la hora en el formato proporcionado. Prueba a usar el formato AAAA-MM-DD HH:MM:SS.",
+       "htmlform-date-toolow": "El valor especificado es anterior a la fecha más antigua permitida, $1.",
+       "htmlform-date-toohigh": "El valor especificado es posterior a la fecha límite permitida, $1.",
+       "htmlform-time-toolow": "El valor especificado es anterior a la hora más antigua permitida, $1.",
+       "htmlform-time-toohigh": "El valor especificado es posterior a la hora límite permitida, $1.",
+       "htmlform-datetime-toolow": "El valor especificado es anterior a la fecha y hora más antigua permitidas, $1.",
+       "htmlform-datetime-toohigh": "El valor especificado es posterior a la fecha y hora límite permitidas, $1.",
        "htmlform-title-badnamespace": "[[:$1]] no está en el espacio de nombres \"{{ns:$2}}\".",
        "htmlform-title-not-creatable": "\"$1\" no es un título de página que se pueda crear",
        "htmlform-title-not-exists": "$1 no existe.",
index 476e3f1..6ff7c3b 100644 (file)
        "upload-copy-upload-invalid-domain": "Domeinu honetan ezin dira igoerak kopiatu.",
        "upload-dialog-title": "Igo fitxategia",
        "upload-dialog-button-cancel": "Utzi",
+       "upload-dialog-button-back": "Atzera",
        "upload-dialog-button-done": "Egina",
        "upload-dialog-button-save": "Gorde",
        "upload-dialog-button-upload": "Igo",
        "htmlform-chosen-placeholder": "Aukeratu",
        "htmlform-cloner-create": "Gehitu gehiago",
        "htmlform-cloner-delete": "Kendu",
+       "htmlform-date-placeholder": "UUUU-HH-EE",
+       "htmlform-time-placeholder": "OO:MM:SS",
+       "htmlform-datetime-placeholder": "UUUU-HH-EE OO:MM:SS",
+       "htmlform-date-invalid": "Jarri duzun balioak ez du data ezagunik adierazten. Saiatu UUUU-HH-EE formatua erabiltzen.",
+       "htmlform-time-invalid": "Jarri duzun balioak ez du denbora ezagunik adierazten. Saiatu OO:MM:SS formatua erabiltzen.",
+       "htmlform-datetime-invalid": "Jarri duzun balioak ez da data eta denbora bezala ezagutzen. Saitu UUUU-HH-EE OO:MM:SS formatua erabiltzen.",
        "htmlform-title-not-creatable": "\"$1\" ez da sor daitekeen orrialde baten izenburua",
        "htmlform-title-not-exists": "$1 ez da existitzen.",
        "htmlform-user-not-exists": "<strong>$1</strong> ez da existitzen.",
index 7d085fa..def34be 100644 (file)
@@ -80,7 +80,7 @@
        "tog-enotifminoredits": "Lähetä sähköpostiviesti myös pienistä muokkauksista",
        "tog-enotifrevealaddr": "Näytä sähköpostiosoitteeni muille lähetetyissä ilmoituksissa",
        "tog-shownumberswatching": "Näytä sivua tarkkailevien käyttäjien määrä",
-       "tog-oldsig": "Nykyinen allekirjoitus:",
+       "tog-oldsig": "Nykyinen allekirjoituksesi:",
        "tog-fancysig": "Muotoilematon allekirjoitus ilman automaattista linkkiä",
        "tog-uselivepreview": "Käytä välitöntä esikatselua",
        "tog-forceeditsummary": "Huomauta minua, jos en ole kirjoittanut yhteenvetoa",
        "newwindow": "(avautuu uuteen ikkunaan)",
        "cancel": "Peruuta",
        "moredotdotdot": "Lisää...",
-       "morenotlisted": "Tämä luettelo ei ole täydellinen.",
+       "morenotlisted": "Tämä luettelo ei ehkä ole täydellinen.",
        "mypage": "Käyttäjäsivu",
        "mytalk": "Keskustelu",
        "anontalk": "Keskustelu",
        "eauthentsent": "Varmennussähköposti on lähetetty annettuun sähköpostiosoitteeseen.\nMuita viestejä ei lähetetä, ennen kuin olet toiminut viestin ohjeiden mukaan ja varmistanut, että sähköpostiosoite kuuluu sinulle.",
        "throttled-mailpassword": "Salasananpalautusviesti on lähetetty {{PLURAL:$1|kuluvan|kuluvien $1}} tunnin aikana. Salasananpalautusviestejä lähetetään enintään {{PLURAL:$1|tunnin|$1 tunnin}} välein.",
        "mailerror": "Virhe lähetettäessä sähköpostia: $1",
-       "acct_creation_throttle_hit": "IP-osoitteestasi on luotu tähän wikiin jo {{PLURAL:$1|yksi tunnus|$1 tunnusta}} päivän aikana, joka suurin sallittu määrä tälle ajalle.\nTästä johtuen tästä IP-osoitteesta ei voi tällä hetkellä luoda uusia tunnuksia.",
+       "acct_creation_throttle_hit": "IP-osoitteestasi on luotu tähän wikiin jo {{PLURAL:$1|yksi tunnus|$1 tunnusta}} viimeisen $2 aikana, joka on suurin sallittu määrä tälle ajalle.\nTästä johtuen tästä IP-osoitteesta ei voi tällä hetkellä luoda uusia tunnuksia.",
        "emailauthenticated": "Sähköpostiosoitteesi varmennettiin $2 kello $3.",
        "emailnotauthenticated": "Sähköpostiosoitettasi ei ole vielä varmennettu.\nSähköpostia ei lähetetä liittyen alla oleviin toimintoihin.",
        "noemailprefs": "Sähköpostiosoitetta ei ole määritelty.",
        "htmlform-cloner-create": "Lisää enemmän",
        "htmlform-cloner-delete": "Poista",
        "htmlform-cloner-required": "Vähintään yksi arvo on pakollinen.",
+       "htmlform-date-placeholder": "VVVV-KK-PP",
+       "htmlform-time-placeholder": "TT:MM:SS",
+       "htmlform-datetime-placeholder": "VVVV-KK-PP TT:MM:SS",
        "htmlform-title-badnamespace": "Sivu [[:$1]] ei ole nimiavaruudessa ”{{ns:$2}}”.",
        "htmlform-title-not-creatable": "”$1” ei kelpaa sivun nimeksi.",
        "htmlform-title-not-exists": "Sivua $1 ei ole olemassa.",
index effeff9..d57e53f 100644 (file)
        "upload-dialog-disabled": "Les téléversements de fichier utilisant cette boîte de dialogue sont désactivés sur ce wiki.",
        "upload-dialog-title": "Téléverser un fichier",
        "upload-dialog-button-cancel": "Annuler",
+       "upload-dialog-button-back": "Retour",
        "upload-dialog-button-done": "Terminé",
        "upload-dialog-button-save": "Enregistrer",
        "upload-dialog-button-upload": "Téléverser",
        "tag-mw-contentmodelchange": "modification du modèle de contenu",
        "tag-mw-contentmodelchange-description": "Modifications qui [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:ChangeContentModel changent le modèle de contenu] d'une page",
        "tags-title": "Balises",
-       "tags-intro": "Cette page liste les balises que le logiciel peut utiliser pour marquer une modification et la signification de chacune.",
+       "tags-intro": "Cette page liste les balises que le logiciel peut utiliser pour marquer une modification et la signification de chacune d’elles.",
        "tags-tag": "Nom de la balise",
        "tags-display-header": "Apparence dans les listes de modifications",
        "tags-description-header": "Description complète de la balise",
        "tags-active-yes": "Oui",
        "tags-active-no": "Non",
        "tags-source-extension": "Défini par le logiciel",
-       "tags-source-manual": "Appliquée manuellement par les utilisateurs et les bots",
+       "tags-source-manual": "Appliquée manuellement par les utilisateurs et les robots",
        "tags-source-none": "Obsolète",
        "tags-edit": "modifier",
        "tags-delete": "supprimer",
        "tags-manage-no-permission": "Vous n'avez pas la permission de gérer les modifications de balises.",
        "tags-manage-blocked": "Vous ne pouvez pas accéder à l’interface de modification des balises lorsque vous êtes bloqué{{GENDER:||e}}.",
        "tags-create-heading": "Créer une nouvelle balise",
-       "tags-create-explanation": "Par défaut, les nouvelles balises créées seront disponibles pour les utilisateurs et les bots.",
+       "tags-create-explanation": "Par défaut, les nouvelles balises créées seront disponibles pour les utilisateurs et les robots.",
        "tags-create-tag-name": "Nom de la balise :",
        "tags-create-reason": "Raison :",
        "tags-create-submit": "Créer",
        "htmlform-cloner-create": "Ajouter encore",
        "htmlform-cloner-delete": "Supprimer",
        "htmlform-cloner-required": "Une valeur au moins est obligatoire.",
+       "htmlform-date-placeholder": "AAAA-MM-JJ",
+       "htmlform-time-placeholder": "HH:MM:SS",
+       "htmlform-datetime-placeholder": "AAAA-MM-JJ HH:MM:SS",
+       "htmlform-date-invalid": "La valeur que vous avez spécifiée n’est pas une date reconnue. Essayez en utilisant le format AAAA-MM-JJ.",
+       "htmlform-time-invalid": "La valeur que vous avez spécifiée n’est pas une heure reconnue. Essayez en utilisant le format HH:MM:SS.",
+       "htmlform-datetime-invalid": "La valeur que vous avez spécifiée n’est pas un horodatage reconnu. Essayez en utilisant le format AAAA-MM-JJ HH:MM:SS.",
+       "htmlform-date-toolow": "La valeur que vous avez spécifiée est antérieure à la date autorisée la plus ancienne, qui est $1.",
+       "htmlform-date-toohigh": "La valeur que vous avez spécifiée est postérieure à la date autorisée la plus lointaine, qui est $1.",
+       "htmlform-time-toolow": "La valeur que vous avez spécifiée est antérieure à la plus petite heure autorisée, qui est $1.",
+       "htmlform-time-toohigh": "La valeur que vous avez spécifiée est postérieure à la plus grande heure autorisée, qui est $1.",
+       "htmlform-datetime-toolow": "La valeur que vous avez spécifiée est antérieure à l’horodatage autorisé le plus ancien, qui est $1.",
+       "htmlform-datetime-toohigh": "La valeur que vous avez spécifiée est postérieure à l’horodatage autorisé le plus lointain, qui est $1.",
        "htmlform-title-badnamespace": "[[:$1]] n'est pas dans l’espace de noms « {{ns:$2}} ».",
        "htmlform-title-not-creatable": "« $1 » n’est pas un titre de page pouvant être créée",
        "htmlform-title-not-exists": "$1 n’existe pas",
        "unlinkaccounts-success": "Le compte a été dissocié.",
        "authenticationdatachange-ignored": "Les modifications de données d’authentification n’ont pas été gérées. Peut-être aucun fournisseur n’a-t-il été configuré ?",
        "userjsispublic": "Veuillez noter: les sous-pages JavaScript ne doivent pas contenir de données confidentielles parce qu'elles sont visibles des autres utilisateurs.",
-       "usercssispublic": "Veuillez noter: les sous-pages CSS ne doivent pas contenir de données confidentielles parce qu'elles sont visibles des autres utilisateurs."
+       "usercssispublic": "Veuillez noter: les sous-pages CSS ne doivent pas contenir de données confidentielles parce qu'elles sont visibles des autres utilisateurs.",
+       "restrictionsfield-badip": "Adresse IP ou plage non valide : $1",
+       "restrictionsfield-label": "Plages IP autorisées :",
+       "restrictionsfield-help": "Une adresse IP ou une plage CIDR par ligne. Pour tout activer, utiliser <br><code>0.0.0.0/0</code><br><code>::/0</code>"
 }
index 77eb096..3a10563 100644 (file)
        "tog-minordefault": "Marcar todas as edicións como pequenas por defecto",
        "tog-previewontop": "Mostrar a vista previa antes da caixa de edición",
        "tog-previewonfirst": "Mostrar a vista previa na primeira edición",
-       "tog-enotifwatchlistpages": "Desexo recibir un aviso por correo electrónico cando unha páxina ou un ficheiro da miña lista de vixilancia sufra algún cambio",
-       "tog-enotifusertalkpages": "Desexo recibir un aviso por correo electrónico cando a miña páxina de conversa cambie",
-       "tog-enotifminoredits": "Enviádeme tamén unha mensaxe de correo electrónico cando se produzan edicións pequenas nas páxinas ou nos ficheiros",
+       "tog-enotifwatchlistpages": "Recibir un aviso por correo electrónico cando unha páxina ou un ficheiro da miña lista de vixilancia sufra algún cambio",
+       "tog-enotifusertalkpages": "Recibir un aviso por correo electrónico cando a miña páxina de conversa sufra algún cambio",
+       "tog-enotifminoredits": "Recibir tamén unha mensaxe de correo electrónico cando se produzan edicións pequenas nas páxinas ou nos ficheiros",
        "tog-enotifrevealaddr": "Revelar o meu enderezo de correo electrónico nos correos de notificación",
        "tog-shownumberswatching": "Mostrar o número de usuarios que están a vixiar",
        "tog-oldsig": "A súa sinatura actual:",
        "tog-fancysig": "Tratar a sinatura como se fose texto wiki (sen ligazón automática)",
        "tog-uselivepreview": "Usar a vista previa en tempo real",
-       "tog-forceeditsummary": "Avisádeme cando o campo resumo estea baleiro",
+       "tog-forceeditsummary": "Avisar cando o campo resumo estea baleiro",
        "tog-watchlisthideown": "Agochar as edicións propias na lista de vixilancia",
        "tog-watchlisthidebots": "Agochar as edicións dos bots na lista de vixilancia",
        "tog-watchlisthideminor": "Agochar as edicións pequenas na lista de vixilancia",
        "tog-watchlisthideanons": "Agochar as edicións dos usuarios anónimos na lista de vixilancia",
        "tog-watchlisthidepatrolled": "Agochar as edicións patrulladas na lista de vixilancia",
        "tog-watchlisthidecategorization": "Agochar a categorización das páxinas",
-       "tog-ccmeonemails": "Enviádeme ao meu enderezo unha copia das mensaxes de correo electrónico que envíe a outros usuarios",
+       "tog-ccmeonemails": "Recibir no meu enderezo unha copia das mensaxes de correo electrónico que envíe a outros usuarios",
        "tog-diffonly": "Non mostrar o contido da páxina debaixo das diferenzas entre edicións",
        "tog-showhiddencats": "Mostrar as categorías ocultas",
        "tog-norollbackdiff": "Omitir as diferenzas despois de levar a cabo unha reversión de edicións",
-       "tog-useeditwarning": "Avisádeme cando deixe unha páxina de edición cos cambios sen gardar",
+       "tog-useeditwarning": "Avisar ao deixar unha páxina de edición cos cambios sen gardar",
        "tog-prefershttps": "Utilizar sempre unha conexión segura para acceder ao sistema",
        "underline-always": "Sempre",
        "underline-never": "Nunca",
        "databaseerror-query": "Pescuda: $1",
        "databaseerror-function": "Función: $1",
        "databaseerror-error": "Erro: $1",
-       "transaction-duration-limit-exceeded": "Para evitar crear un gran atraso na replicación, esta transacción abortouse xa que a duración de escritura ($1) excedeu o límite de $2 {{PLURAL:$2|segundo|segundos}} .\nSe está a cambiar moitos obxectos ao mesmo tempo, procure facer operacións múltiples máis pequenas no seu lugar.",
+       "transaction-duration-limit-exceeded": "Para evitar crear un grande atraso na replicación, esta transacción abortouse xa que a duración de escritura ($1) excedeu o límite de $2 segundos.\nSe está a cambiar moitos obxectos ao mesmo tempo, procure facer operacións múltiples máis pequenas no seu lugar.",
        "laggedslavemode": "'''Aviso:''' A páxina pode non conter as actualizacións recentes.",
        "readonly": "Base de datos pechada",
        "enterlockreason": "Dea unha razón para o peche, incluíndo unha estimación de até cando se manterá",
        "createacct-reason-ph": "Por que crea outra conta?",
        "createacct-reason-help": "Mensaxe que se mostra no rexistro de creación de contas",
        "createacct-submit": "Crear a conta",
-       "createacct-another-submit": "Crear conta",
+       "createacct-another-submit": "Crear conta",
        "createacct-continue-submit": "Continuar a creación da conta",
        "createacct-another-continue-submit": "Continuar a creación da conta",
        "createacct-benefit-heading": "Xente coma vostede elabora {{SITENAME}}.",
        "resetpass_submit": "Establecer o contrasinal e acceder ao sistema",
        "changepassword-success": "O seu contrasinal foi modificado!",
        "changepassword-throttled": "Fixo demasiados intentos de acceder ao sistema.\nPor favor, agarde $1 antes de probar outra vez.",
-       "botpasswords": "Contrasinais de Bot",
-       "botpasswords-summary": "Os <em>contrasinais de Bot</em> permiten acceder a unha conta de usuario por medio da API sen usar as crecenciais de acceso da conta principal. Os dereitos de usuario dispoñibles cando se accede ao sistema cun contrasinal de bot poden estar restrinxidos.",
-       "botpasswords-disabled": "Os contrasinais de bot non están habilitados.",
-       "botpasswords-no-central-id": "Para usar contrasinais de bot debes acceder ao sistema cunha conta centralizada.",
-       "botpasswords-existing": "Contrasinais de bot existentes",
+       "botpasswords": "Contrasinais de bots",
+       "botpasswords-summary": "Os <em>contrasinais de bots</em> permiten acceder a unha conta de usuario por medio da API sen usar as crecenciais de acceso da conta principal. Os dereitos de usuario dispoñibles cando se accede ao sistema cun contrasinal de bot poden estar restrinxidos.\n\nSe non sabe por que quere facer isto, probablemente signifique que non o queira facer. Ningunha persoa debería pedirlle a vostede que xere unha destas claves para entregarlla.",
+       "botpasswords-disabled": "Os contrasinais de bots non están habilitados.",
+       "botpasswords-no-central-id": "Para usar os contrasinais de bots debe acceder ao sistema cunha conta centralizada.",
+       "botpasswords-existing": "Contrasinais de bots existentes",
        "botpasswords-createnew": "Crear un novo contrasinal de bot",
        "botpasswords-editexisting": "Editar un contrasinal de bot xa existente",
        "botpasswords-label-appid": "Nome do bot:",
        "botpasswords-label-delete": "Borrar",
        "botpasswords-label-resetpassword": "Restablecer o contrasinal",
        "botpasswords-label-grants": "Permisos aplicables:",
-       "botpasswords-help-grants": "Cada permiso da acceso aos permisos de usuario listados que a conta xa teña. Vexa a [[Special:ListGrants|táboa de permisos]] para máis información.",
+       "botpasswords-help-grants": "Cada permiso dá acceso aos permisos de usuario listados que a conta xa teña. Consulte a [[Special:ListGrants|táboa de permisos]] para obter máis información.",
        "botpasswords-label-grants-column": "Concedido",
        "botpasswords-bad-appid": "O nome de bot \"$1\" non é válido.",
        "botpasswords-insert-failed": "Erro ao engadir o nome de bot \"$1\". Revise se xa foi engadido previamente.",
        "botpasswords-update-failed": "Erro ao actualizar o nome de bot \"$1\". Revise se foi borrado.",
-       "botpasswords-created-title": "Contrasinal de bot creado",
+       "botpasswords-created-title": "Creouse o contrasinal de bot",
        "botpasswords-created-body": "Creouse o contrasinal para o bot de nome \"$1\" do usuario \"$2\".",
-       "botpasswords-updated-title": "Contrasinal de bot actualizado",
-       "botpasswords-updated-body": "O contrasinal de bot do bot de nome \"$1\" do usuario \"$2\" foi actualizado.",
-       "botpasswords-deleted-title": "Contrasinal de bot borrado",
-       "botpasswords-deleted-body": "O contrasinal de bot do bot de nome \"$1\" do usuario \"$2\" foi borrado.",
-       "botpasswords-newpassword": "O novo contrasinal para acceder con <strong>$1</strong> é <strong>$2</strong>. <em>Por favor, rexistre isto para referencias futuras.</em><br />(Para bots vellos que requiren que o nome de acceso sexa o mesmo que o nome de usuario eventual, pode usar tamén <strong>$3</strong> como nome de usuario e <strong>$4</strong>  como contrasinal.)",
+       "botpasswords-updated-title": "Actualizouse o contrasinal de bot",
+       "botpasswords-updated-body": "Actualizouse o contrasinal para o bot de nome \"$1\" do usuario \"$2\".",
+       "botpasswords-deleted-title": "Borrouse o contrasinal de bot",
+       "botpasswords-deleted-body": "Borrouse o contrasinal para o bot de nome \"$1\" do usuario \"$2\".",
+       "botpasswords-newpassword": "O novo contrasinal para acceder con <strong>$1</strong> é <strong>$2</strong>. <em>Por favor, conserve isto para referencias futuras.</em><br />(Para os bots vellos que requiren que o nome de acceso sexa o mesmo que o nome de usuario eventual, pode usar tamén <strong>$3</strong> como nome de usuario e <strong>$4</strong> como contrasinal.)",
        "botpasswords-no-provider": "BotPasswordsSessionProvider non está dispoñible.",
-       "botpasswords-restriction-failed": "Restricións de contrasinal de bots evitaron esta conexión.",
+       "botpasswords-restriction-failed": "Algunhas restricións de contrasinal de bots evitaron esta conexión.",
        "botpasswords-invalid-name": "O nome de usuario especificado non contén o separador de contrasinal de bot (\"$1\").",
        "botpasswords-not-exist": "O usuario \"$1\" non ten un contrasinal de bot de nome \"$2\".",
        "resetpass_forbidden": "Non se poden mudar os contrasinais",
        "prefs-resetpass": "Cambiar o contrasinal",
        "prefs-changeemail": "Cambiar ou eliminar o enderezo de correo electrónico",
        "prefs-setemail": "Establecer un enderezo de correo electrónico",
-       "prefs-email": "Opcións de correo electrónico",
+       "prefs-email": "Opcións do correo electrónico",
        "prefs-rendering": "Aparencia",
        "saveprefs": "Gardar",
        "restoreprefs": "Restaurar todas as preferencias por defecto (en todas as seccións)",
        "badsig": "Sinatura non válida; comprobe o código HTML utilizado.",
        "badsiglength": "A súa sinatura é demasiado longa.\nHa de ter menos {{PLURAL:$1|dun carácter|de $1 caracteres}}.",
        "yourgender": "Cal das seguintes oracións referidas a vostede é a máis axeitada?",
-       "gender-unknown": "Ao mencionarlle, o software empregará verbas de xénero neutral sempre que sexa posible",
+       "gender-unknown": "Ao facer mención á súa persoa, o software empregará verbas de xénero neutro sempre que sexa posible",
        "gender-male": "El edita as páxinas do wiki",
        "gender-female": "Ela edita as páxinas do wiki",
        "prefs-help-gender": "Definir esta preferencia é opcional.\nO software usa este valor para dirixirse á súa persoa e para facerlle mencións mediante o xénero gramatical axeitado.\nEsta información será pública.",
        "email": "Correo electrónico",
-       "prefs-help-realname": "O nome real é opcional.\nEn caso de revelalo, utilizarase para atribuírlle o seu traballo.",
+       "prefs-help-realname": "O nome real é opcional.\nEn caso de revelalo, ha utilizarse para atribuírlle o seu traballo.",
        "prefs-help-email": "O enderezo de correo electrónico é opcional, pero permite que se lle envíe un contrasinal novo se se esquece del.",
-       "prefs-help-email-others": "Tamén pode optar por deixar aos outros que se poidan poñer en contacto con vostede a través da súa páxina de usuario sen necesidade de revelar a súa identidade.",
+       "prefs-help-email-others": "Tamén pode optar por deixar que outras persoas se poñan en contacto con vostede a través dunha ligazón na súa páxina de usuario e de conversa.\nO seu enderezo non se revela cando contacten con vostede.",
        "prefs-help-email-required": "Cómpre o enderezo de correo electrónico.",
        "prefs-info": "Información básica",
        "prefs-i18n": "Internacionalización",
        "recentchanges-page-removed-from-category-bundled": "[[:$1]] eliminada da categoría [[Special:WhatLinksHere/$1||esta páxina está incluída noutras páxinas]]",
        "autochange-username": "Cambio automático de MediaWiki",
        "upload": "Subir un ficheiro",
-       "uploadbtn": "Subir un ficheiro",
+       "uploadbtn": "Subir o ficheiro",
        "reuploaddesc": "Cancelar a carga e volver ao formulario de carga",
        "upload-tryagain": "Enviar a descrición do ficheiro modificada",
        "uploadnologin": "Non accedeu ao sistema",
        "upload-dialog-disabled": "As cargas de ficheiros usando esta pantalla están desactivadas neste wiki.",
        "upload-dialog-title": "Subir un ficheiro",
        "upload-dialog-button-cancel": "Cancelar",
+       "upload-dialog-button-back": "Volver",
        "upload-dialog-button-done": "Feito",
        "upload-dialog-button-save": "Gardar",
        "upload-dialog-button-upload": "Subir",
        "upload-form-label-infoform-description-tooltip": "Describa brevemente todo o destacable acerca do traballo.\nPara unha foto, mencione as cousas principais que se representan, a ocasión ou o lugar.",
        "upload-form-label-usage-title": "Uso",
        "upload-form-label-usage-filename": "Nome do ficheiro",
-       "upload-form-label-own-work": "Isto é o meu propio traballo",
+       "upload-form-label-own-work": "Isto é unha obra propia",
        "upload-form-label-infoform-categories": "Categorías",
        "upload-form-label-infoform-date": "Data",
        "upload-form-label-own-work-message-generic-local": "Confirmo que estou a cargar este ficheiro seguindo os termos de uso e políticas de licenza de {{SITENAME}}.",
        "protectedpages-performer": "Protector",
        "protectedpages-params": "Parámetros da protección",
        "protectedpages-reason": "Motivo",
-       "protectedpages-submit": "Mostrar páxinas",
+       "protectedpages-submit": "Mostrar as páxinas",
        "protectedpages-unknown-timestamp": "Descoñecido",
        "protectedpages-unknown-performer": "Usuario descoñecido",
        "protectedtitles": "Títulos protexidos",
        "protectedtitles-summary": "Esta páxina lista os títulos que están protexidos actualmente fronte á creación. Para obter unha lista de páxinas existentes protexidas, consulte [[{{#special:ProtectedPages}}|{{int:protectedpages}}]].",
        "protectedtitlesempty": "Actualmente non hai ningún título protexido con eses parámetros.",
-       "protectedtitles-submit": "Mostrar títulos",
+       "protectedtitles-submit": "Mostrar os títulos",
        "listusers": "Lista de usuarios",
        "listusers-editsonly": "Mostrar só os usuarios con edicións",
        "listusers-creationsort": "Ordenar por data de creación",
        "nopagetext": "A páxina que especificou non existe.",
        "pager-newer-n": "{{PLURAL:$1|unha posterior|$1 posteriores}}",
        "pager-older-n": "{{PLURAL:$1|unha anterior|$1 anteriores}}",
-       "suppress": "Supresor",
+       "suppress": "Suprimir",
        "querypage-disabled": "Esta páxina especial está desactivada por razóns de rendemento.",
        "apihelp": "Axuda coa API",
        "apihelp-no-such-module": "Non se atopou o módulo \"$1\".",
        "htmlform-cloner-create": "Engadir máis",
        "htmlform-cloner-delete": "Eliminar",
        "htmlform-cloner-required": "Necesítase, polo menos, un valor.",
+       "htmlform-date-placeholder": "AAAA-MM-DD",
+       "htmlform-time-placeholder": "HH:MM:SS",
+       "htmlform-datetime-placeholder": "AAAA-MM-DD HH:MM:SS",
+       "htmlform-date-invalid": "O valor especificado non é unha data recoñedica. Probe usando o formato AAAA-MM-DD.",
+       "htmlform-time-invalid": "O valor especificado non é unha hora recoñedica. Probe usando o formato HH:MM:SS.",
+       "htmlform-datetime-invalid": "O valor especificado non é unha data e hora recoñedica. Probe usando o formato AAAA-MM-DD HH:MM:SS.",
+       "htmlform-date-toolow": "O valor especificado é anterior á data máis antiga permitida: $1",
+       "htmlform-date-toohigh": "O valor especificado é posterior á data máis nova permitida: $1",
+       "htmlform-time-toolow": "O valor especificado é anterior ó tempo máis antigo permitido: $1",
+       "htmlform-time-toohigh": "O valor especificado é posterior ó tempo máis novo permitido: $1",
+       "htmlform-datetime-toolow": "O valor especificado é anterior á data e tampo máis antigo permitido: $1",
+       "htmlform-datetime-toohigh": "O valor especificado é posterior á data e tempo máis novo permitido: $1",
        "htmlform-title-badnamespace": "\"[[:$1]]\" non está no espazo de nomes \"{{ns:$2}}\".",
        "htmlform-title-not-creatable": "\"$1\" non é un título de páxina que se poida crear",
        "htmlform-title-not-exists": "\"$1\" non existe.",
        "unlinkaccounts-success": "A conta foi desvinculada.",
        "authenticationdatachange-ignored": "Os cambios de datos de autenticación non foron xerados. Está configurado o provedor?",
        "userjsispublic": "Lembre: As subpáxinas JavaScript non deberían conter datos confidenciais porque outros usuarios poden velos.",
-       "usercssispublic": "Lembre: As subpáxinas CSS non deberían conter datos confidenciais porque outros usuarios poden velos."
+       "usercssispublic": "Lembre: As subpáxinas CSS non deberían conter datos confidenciais porque outros usuarios poden velos.",
+       "restrictionsfield-badip": "Enderezo IP ou rango de IP non válido: $1",
+       "restrictionsfield-label": "Rangos de IP permitidos:",
+       "restrictionsfield-help": "Un único enderezo IP ou rango CIDR por liña. Para habilitalos todos, utilice<br><code>0.0.0.0/0</code><br><code>::/0</code>"
 }
index d798b86..bdfcfb5 100644 (file)
        "title-invalid-characters": "כותרת הדף המבוקש מכילה תווים בלתי תקינים: \"$1\".",
        "title-invalid-relative": "בכותרת יש נתיב יחסי. כותרת דפים יחסיות (./, ../) אינן תקינות, משום שלעתים קרובות הן יהיו בלתי־ניתנות להשגה כשתטופלנה על־ידי הדפדפן של המשתמש.",
        "title-invalid-magic-tilde": "כותרת הדף המבוקש מכילה רצף טילדות מיוחד שאינו תקין (<nowiki>~~~</nowiki>).",
-       "title-invalid-too-long": "כותרת הדף המבוקש ארוכה מדי. היא צריכה להיות לכל היותר באורך {{PLURAL:$1|בייט אחד|$1 בייטים}} בקידוד UTF-8.",
+       "title-invalid-too-long": "כותרת הדף המבוקש ארוכה מדי. היא צריכה להיות לכל היותר באורך של {{PLURAL:$1|בייט אחד|$1 בייטים}} בקידוד UTF-8.",
        "title-invalid-leading-colon": "כותרת הדף המבוקש מכילה תו נקודתיים בלתי תקין בתחילתה.",
-       "perfcached": "המידע הבא הוא עותק שמור בזיכרון המטמון של המידע, ועשוי שלא להיות מעודכן. לכל היותר {{PLURAL:$1|תוצאה אחת נשמרת|$1 תוצאות נשמרות}} בזיכרון המטמון.",
-       "perfcachedts": "המידע הבא הוא עותק שמור בזיכרון המטמון של המידע, שעודכן לאחרונה ב־$1. לכל היותר {{PLURAL:$4|תוצאה אחת נשמרת|$4 תוצאות נשמרות}} בזיכרון המטמון.",
+       "perfcached": "המידע הבא הוא עותק שמור בזיכרון המטמון, ועשוי שלא להיות מעודכן. לכל היותר {{PLURAL:$1|תוצאה אחת נשמרת|$1 תוצאות נשמרות}} בזיכרון המטמון.",
+       "perfcachedts": "המידע הבא הוא עותק שמור בזיכרון המטמון, שעודכן לאחרונה ב־$1. לכל היותר {{PLURAL:$4|תוצאה אחת נשמרת|$4 תוצאות נשמרות}} בזיכרון המטמון.",
        "querypage-no-updates": "העדכונים לדף זה כרגע מופסקים, והמידע לא יעודכן באופן שוטף.",
        "viewsource": "הצגת מקור",
        "viewsource-title": "הצגת המקור של הדף \"$1\"",
        "translateinterface": "כדי להוסיף או לשנות תרגומים של הודעות מערכת עבור כל אתרי הוויקי, יש להשתמש ב־[https://translatewiki.net/ translatewiki.net], פרויקט התרגום של מדיה־ויקי.",
        "cascadeprotected": "דף זה מוגן מעריכה כי הוא מוכלל {{PLURAL:$1|בדף הבא, שמופעלת עליו|בדפים הבאים, שמופעלת עליהם}} הגנה מדורגת:\n$2",
        "namespaceprotected": "אין {{GENDER:|לך|לך|לכם}} הרשאה לערוך דפים במרחב השם <strong>$1</strong>.",
-       "customcssprotected": "×\90×\99× ×\9a ×\9e×\95רש×\94 ×\9cער×\95×\9a ×\93×£ CSS ×\96×\94 ×\9b×\99×\95×\95×\9f ×©×\94×\95×\90 ×\9b×\95×\9cל הגדרות אישיות של משתמש אחר.",
-       "customjsprotected": "×\90×\99× ×\9a ×\9e×\95רש×\94 ×\9cער×\95×\9a ×\93×£ JavaScript ×\96×\94 ×\9b×\99×\95×\95×\9f ×©×\94×\95×\90 ×\9b×\95×\9cל הגדרות אישיות של משתמש אחר.",
-       "mycustomcssprotected": "אין לך הרשאה לערוך דף CSS זה.",
-       "mycustomjsprotected": "אין לך הרשאה לערוך דף JavaScript זה.",
-       "myprivateinfoprotected": "אין לך הרשאה לערוך את המידע הפרטי שלך.",
-       "mypreferencesprotected": "אין לך הרשאה לערוך את ההעדפות שלך.",
+       "customcssprotected": "×\90×\99×\9f {{GENDER:|×\9c×\9a\9c×\9a\9c×\9b×\9d}} ×\94רש×\90×\94 ×\9cער×\95×\9a ×\90ת ×\93×£ ×\94Ö¾CSS ×\94×\96×\94, ×\9eש×\95×\9d ×©×\94×\95×\90 ×\9e×\9b×\99ל הגדרות אישיות של משתמש אחר.",
+       "customjsprotected": "×\90×\99×\9f {{GENDER:|×\9c×\9a\9c×\9a\9c×\9b×\9d}} ×\94רש×\90×\94 ×\9cער×\95×\9a ×\90ת ×\93×£ ×\94Ö¾JavaScript ×\94×\96×\94, ×\9eש×\95×\9d ×©×\94×\95×\90 ×\9e×\9b×\99ל הגדרות אישיות של משתמש אחר.",
+       "mycustomcssprotected": "אין {{GENDER:|לך|לך|לכם}} הרשאה לערוך את דף ה־CSS הזה.",
+       "mycustomjsprotected": "אין {{GENDER:|לך|לך|לכם}} הרשאה לערוך את דף ה־JavaScript הזה.",
+       "myprivateinfoprotected": "אין {{GENDER:|לך|לך|לכם}} הרשאה לערוך את המידע הפרטי {{GENDER:|שלך|שלך|שלכם}}.",
+       "mypreferencesprotected": "אין {{GENDER:|לך|לך|לכם}} הרשאה לערוך את ההעדפות {{GENDER:|שלך|שלך|שלכם}}.",
        "ns-specialprotected": "לא ניתן לערוך דפים מיוחדים.",
-       "titleprotected": "[[User:$1|$1]] {{GENDER:$1|×\94פע×\99×\9c\94פע×\99×\9c×\94}} ×\94×\92× ×\94 ×¢×\9c ×\94×\93×£ ×\94×\96×\94 ×\9eפנ×\99 ×\99צ×\99ר×\94.\n×\94ס×\99×\91×\94 ×©× ×\99תנ×\94 ×\9c×\9b×\9a ×\94×\99×\90 <em>$2</em>.",
+       "titleprotected": "[[User:$1|$1]] {{GENDER:$1|×\94פע×\99×\9c\94פע×\99×\9c×\94}} ×¢×\9c ×\94×\93×£ ×\94×\96×\94 ×\94×\92× ×\94 ×\9eפנ×\99 ×\99צ×\99ר×\94.\n×\94ס×\99×\91×\94 ×©× ×\99תנ×\94 ×\9c×\94×\92× ×\94 ×\94×\99×\90: <em>$2</em>.",
        "filereadonlyerror": "לא ניתן לשנות את הקובץ \"$1\" כיוון שמאגר הקבצים \"$2\" במצב קריאה בלבד.\n\nמנהל המערכת שנעל את המאגר סיפק את ההסבר הבא: \"'''$3'''\".",
        "invalidtitle-knownnamespace": "כותרת בלתי־תקינה עם מרחב השם \"$2\" ושם דף \"$3\"",
        "invalidtitle-unknownnamespace": "כותרת בלתי־תקינה עם מרחב שם בלתי־ידוע מספר $1 ושם דף \"$2\"",
        "eauthentsent": "דוא\"ל אימות נשלח לכתובת הדוא\"ל שצוינה.\nלפני שדברי דוא\"ל אחרים יישלחו לחשבון הזה, יהיה עליכם לפעול לפי ההוראות בדוא\"ל, כדי לאשר שהחשבון אכן שייך לכם.",
        "throttled-mailpassword": "כבר נשלח דוא\"ל לאיפוס הסיסמה ב{{PLURAL:$1|שעה האחרונה|שעתיים האחרונות|־$1 השעות האחרונות}}.\nכדי למנוע ניצול לרעה, יכול להישלח רק דוא\"ל אחד כזה בכל {{PLURAL:$1|שעה|שעתיים|$1 שעות}}.",
        "mailerror": "שגיאה בשליחת דואר: $1",
-       "acct_creation_throttle_hit": "×\9e×\91קר×\99×\9d ×\91×\90תר ×\96×\94 ×\93ר×\9a ×\9bת×\95×\91ת ×\94Ö¾IP ×©×\9c×\9b×\9d ×\9b×\91ר ×\99צר×\95 {{PLURAL:$1|×\97ש×\91×\95×\9f ×\90×\97×\93|$1 ×\97ש×\91×\95× ×\95ת}} ×\91×\99×\95×\9d ×\94×\90×\97ר×\95×\9f. ×\96×\94×\95 ×\94×\9eקס×\99×\9e×\95×\9d ×\94×\9e×\95תר ×\91תק×\95פ×\94 ×\96×\95.\n×\9cפ×\99×\9b×\9a, ×\9e×\91קר×\99×\9d ×\93ר×\9a ×\9bת×\95×\91ת ×\94Ö¾IP ×\94×\96×\90ת ×\9c×\90 ×\99×\9b×\95×\9c×\99×\9d ×\9c×\99צ×\95ר ×\97ש×\91×\95× ×\95ת × ×\95ספ×\99×\9d ×\91ר×\92×¢ ×\96×\94.",
+       "acct_creation_throttle_hit": "×\9e×\91קר×\99×\9d ×\91×\90תר ×\96×\94 ×\93ר×\9a ×\9bת×\95×\91ת ×\94Ö¾IP ×©×\9c×\9a ×\9b×\91ר ×\99צר×\95 {{PLURAL:$1|×\97ש×\91×\95×\9f ×\90×\97×\93|$1 ×\97ש×\91×\95× ×\95ת}} ×\91Ö¾$2. ×\96×\94×\95 ×\94×\9eקס×\99×\9e×\95×\9d ×\94×\9e×\95תר ×\91תק×\95פ×\94 ×\96×\95.\n×\9cפ×\99×\9b×\9a, ×\9bר×\92×¢ ×\9c×\90 × ×\99ת×\9f ×\9c×\99צ×\95ר ×\97ש×\91×\95× ×\95ת × ×\95ספ×\99×\9d ×\9e×\9bת×\95×\91ת ×\94Ö¾IP ×\94×\96×\95.",
        "emailauthenticated": "כתובת הדוא\"ל שלך אומתה ב־$2 בשעה $3.",
        "emailnotauthenticated": "כתובת הדוא\"ל שלכם עדיין לא אומתה.\nלא יישלח אליכם דוא\"ל עבור אף אחת מהתכונות הבאות.",
        "noemailprefs": "יש לציין כתובת דוא\"ל בהעדפות שלך כדי שתכונות אלה יעבדו.",
        "unlinkaccounts-success": "קישור החשבון בוטל.",
        "authenticationdatachange-ignored": "השינוי בנתוני האימות לא הצליח. ייתכן שלא הוגדר ספק.",
        "userjsispublic": "שימו לב: משתמשים אחרים יכולים לצפות בדפי ה־JavaScript שלכם, ולכן אין לכלול בהם מידע סודי.",
-       "usercssispublic": "שימו לב: משתמשים אחרים יכולים לצפות בדפי ה־CSS שלכם, ולכן אין לכלול בהם מידע סודי."
+       "usercssispublic": "שימו לב: משתמשים אחרים יכולים לצפות בדפי ה־CSS שלכם, ולכן אין לכלול בהם מידע סודי.",
+       "restrictionsfield-badip": "כתובת או טווח כתובות IP בלתי תקין: $1",
+       "restrictionsfield-label": "טווחי כתובות IP מותרים:",
+       "restrictionsfield-help": "כתובת IP אחת או טווח CIDR אחד בשורה. כדי לאפשר את הכול, ניתן להשתמש ב:<br><code>0.0.0.0/0</code><br><code>::/0</code>"
 }
index 850fdba..716b426 100644 (file)
@@ -62,7 +62,7 @@
        "tog-enotifminoredits": "Pošalji mi e-mail i kod manjih izmjena stranice",
        "tog-enotifrevealaddr": "Prikaži moju e-mail adresu u obavijestima o izmjeni",
        "tog-shownumberswatching": "Prikaži broj suradnika koji prate stranicu (u nedavnim izmjenama, popisu praćenja i samim člancima)",
-       "tog-oldsig": "Pregled postojećeg potpisa:",
+       "tog-oldsig": "Vaš postojeći potpis:",
        "tog-fancysig": "Običan potpis kao wikitekst (bez automatske poveznice)",
        "tog-uselivepreview": "Uključi trenutačni pretpregled",
        "tog-forceeditsummary": "Podsjeti me ako sažetak uređivanja ostavljam praznim",
        "august": "kolovoza",
        "september": "rujna",
        "october": "listopada",
-       "november": "studenoga",
+       "november": "studenog",
        "december": "prosinca",
        "january-gen": "siječnja",
        "february-gen": "veljače",
        "newwindow": "(otvara se u novom prozoru)",
        "cancel": "Odustani",
        "moredotdotdot": "Više...",
-       "morenotlisted": "Ovaj popis nije potpun.",
+       "morenotlisted": "Ovaj popis možda nije potpun.",
        "mypage": "Stranica",
        "mytalk": "Razgovor",
        "anontalk": "Razgovor",
        "print": "Ispiši",
        "view": "Vidi",
        "view-foreign": "vidi na projektu $1",
-       "edit": "uredi",
+       "edit": "Uredi",
        "edit-local": "Uredi lokalni opis",
        "create": "Započni",
        "create-local": "dodaj lokalni opis",
        "talk": "Razgovor",
        "views": "Pogledi",
        "toolbox": "Pomagala",
+       "tool-link-userrights": "Promijeni {{GENDER:$1|suradnikove|suradničine}} grupe",
+       "tool-link-emailuser": "Pošalji e-poštu {{GENDER:$1|suradniku|suradnici}}",
        "userpage": "Vidi suradnikovu stranicu",
        "projectpage": "Vidi stranicu o projektu",
        "imagepage": "Vidi stranicu datoteke",
        "redirectedfrom": "(Preusmjereno s $1)",
        "redirectpagesub": "Preusmjeravanje",
        "redirectto": "Preusmjerava na:",
-       "lastmodifiedat": "Datum i vrijeme posljednje promjene na ovoj stranici: $1 u $2",
+       "lastmodifiedat": "Ova stranica posljednji put je izmjenjena $1 u $2.",
        "viewcount": "Ova stranica je pogledana {{PLURAL:$1|$1 put|$1 puta}}.",
        "protectedpage": "Zaštićena stranica",
        "jumpto": "Skoči na:",
        "aboutpage": "Project:O_projektu_{{SITENAME}}",
        "copyright": "Sadržaji se koriste u skladu s $1.",
        "copyrightpage": "{{ns:project}}:Autorska prava",
-       "currentevents": "Aktualno",
+       "currentevents": "Novosti",
        "currentevents-url": "Project:Novosti",
        "disclaimers": "Odricanje od odgovornosti",
        "disclaimerpage": "Project:General_disclaimer",
        "viewsourceold": "vidi izvor",
        "editlink": "uredi",
        "viewsourcelink": "vidi izvornik",
-       "editsectionhint": "Uredi odlomak $1",
+       "editsectionhint": "Uredi odlomak: $1",
        "toc": "Sadržaj",
        "showtoc": "prikaži",
        "hidetoc": "sakrij",
        "red-link-title": "$1 (stranica ne postoji)",
        "sort-descending": "Sortiraj silazno",
        "sort-ascending": "Sortiraj uzlazno",
-       "nstab-main": "Članak",
+       "nstab-main": "Stranica",
        "nstab-user": "{{GENDER:{{BASEPAGENAME}}|Stranica suradnika|Stranica suradnice}}",
        "nstab-media": "Mediji",
        "nstab-special": "Posebna stranica",
        "virus-unknownscanner": "nepoznati antivirus:",
        "logouttext": "'''Odjavili ste se.'''\n\nNeke se stranice mogu prikazivati kao da ste još uvijek prijavljeni, sve dok ne očistite međuspremnik svog preglednika.",
        "cannotlogoutnow-title": "Odjava trenutno nije moguća.",
+       "cannotlogoutnow-text": "Odjava nije moguća tijekom uporabe $1.",
        "welcomeuser": "Dobrodošli, $1!",
        "welcomecreation-msg": "Vaš je suradnički račun otvoren.\nNe zaboravite prilagoditi Vaše [[Special:Preferences|{{SITENAME}} postavke]].",
        "yourname": "Suradničko ime",
        "createacct-yourpasswordagain-ph": "Unesite zaporku ponovno",
        "userlogin-remembermypassword": "Zapamti me",
        "userlogin-signwithsecure": "Rabi sigurnu vezu",
+       "cannotlogin-title": "Prijava nije moguća",
+       "cannotlogin-text": "Prijava nija moguća.",
        "cannotloginnow-title": "Prijava trenutno nije moguća.",
+       "cannotloginnow-text": "Prijava nije moguća tijekom uporabe $1.",
+       "cannotcreateaccount-title": "Nije moguće stvoriti račune",
        "yourdomainname": "Vaša domena",
        "password-change-forbidden": "Ne možete promjeniti zaporku na ovom projektu.",
        "externaldberror": "Došlo je do pogreške s vanjskom autorizacijom ili Vam nije dopušteno osvježavanje vanjskog suradničkog računa.",
        "resetpass_submit": "Postavite lozinku i prijavite se",
        "changepassword-success": "Zaporka je uspješno postavljena!",
        "changepassword-throttled": "Nedavno ste se previše puta pokušali prijaviti.\nMolimo Vas pričekajte $1 prije nego što pokušate ponovno.",
+       "botpasswords": "Lozinke botova",
+       "botpasswords-disabled": "Lozinke botova su onemogućene.",
+       "botpasswords-no-central-id": "Za uporabu lozinki botova, morate biti prijavljeni na središnji račun.",
+       "botpasswords-existing": "Postojeće lozinke botova",
+       "botpasswords-createnew": "Stvorite novu lozinku bota",
+       "botpasswords-editexisting": "Uredite postojeću lozinku bota",
+       "botpasswords-label-appid": "Ime bota:",
        "botpasswords-label-create": "Stvori",
        "botpasswords-label-update": "Ažuriraj",
        "botpasswords-label-cancel": "Odustani",
+       "botpasswords-label-delete": "Izbriši",
        "botpasswords-label-resetpassword": "Ponovno postavljanje lozinke",
+       "botpasswords-label-grants": "Primjenjive dozvole:",
+       "botpasswords-help-grants": "Svaka dozvola daje pristup navedenim suradničkim pravima koja su već dodjeljena suradničkom računu. Vidjeti [[Special:ListGrants|tablicu dozvola]] za više informacija.",
+       "botpasswords-label-grants-column": "Odobreno",
+       "botpasswords-bad-appid": "Ime bota \"$1\" nije valjano.",
        "botpasswords-insert-failed": "Nije moguće dodavanje imena bota \"$1\". Možda je već dodano?",
+       "botpasswords-update-failed": "Nije moguće ažurirati bot s imenom \"$1\". Možda je izbrisan?",
        "resetpass_forbidden": "Lozinka ne može biti promijenjena",
        "resetpass-no-info": "Morate biti prijavljeni da biste izravno pristupili ovoj stranici.",
        "resetpass-submit-loggedin": "Promijeni lozinku",
        "minoredit": "Ovo je manja promjena",
        "watchthis": "Prati ovu stranicu",
        "savearticle": "Sačuvaj stranicu",
+       "savechanges": "Spremi promjene",
        "publishpage": "Objavi stranicu",
        "publishchanges": "Objavi izmjene",
        "preview": "Pregled kako će stranica izgledati",
        "diff-multi-manyusers": "({{PLURAL:$1|Nije prikazana jedna međuinačica|Nisu prikazane $1 međuinačice|Nije prikazano $1 međuinačica}} više od {{PLURAL:$2|jednog|$2|$2}} suradnika)",
        "difference-missing-revision": "{{PLURAL:$2|Uređivanje|$2 uređivanja}} sljedeće šifre ($1) ne {{PLURAL:$2|postoji|postoje}}.\n\nOvo je obično uzrokovano kada kliknete na zastarjelu poveznicu na stranice koja je obrisana.\nViše informacija možete pronaći u [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} evidenciji brisanja].",
        "searchresults": "Rezultati pretrage",
-       "searchresults-title": "Rezultati traženja za \"$1\"",
+       "searchresults-title": "Rezultati pretrage za \"$1\"",
        "titlematches": "Pronađene stranice prema naslovu",
        "textmatches": "Pronađene stranice prema tekstu članka",
        "notextmatches": "Nema pronađenih stranica prema tekstu članka",
        "grant-blockusers": "Blokiraj i odblokiraj korisnike",
        "grant-createaccount": "Otvori račune",
        "grant-createeditmovepage": "Stvori, uredi i premjesti stranice",
-       "grant-editmyoptions": "Uredi korisničke postavke",
+       "grant-editmyoptions": "Uređivanje vlastitih suradničkih postavki",
+       "grant-editpage": "Uređivanje postojećih stranica",
+       "grant-editprotected": "Uređivanje zaštićenih stranica",
        "grant-highvolume": "Uređivanja velikog opsega",
        "grant-basic": "Osnovna prava",
        "grant-viewdeleted": "Prikaz izbrisanih datoteka i stranica",
        "rc-old-title": "izvorno ime bilo je \"$1\"",
        "recentchangeslinked": "Povezane stranice",
        "recentchangeslinked-feed": "Povezane stranice",
-       "recentchangeslinked-toolbox": "Povezane stranice",
+       "recentchangeslinked-toolbox": "Povezane promjene",
        "recentchangeslinked-title": "Povezane promjene sa stranicom \"$1\"",
        "recentchangeslinked-summary": "Ova posebna stranica pokazuje nedavne promjene na povezanim stranicama (ili stranicama određene kategorije). Stranice koje su na [[Special:Watchlist|Vašem popisu praćenja]] su '''podebljane'''.",
        "recentchangeslinked-page": "Naslov stranice:",
        "upload-copy-upload-invalid-domain": "Kopije postavljenih datoteka nisu dostupne s ove domene.",
        "upload-dialog-title": "Postavi datoteku",
        "upload-dialog-button-cancel": "Odustani",
+       "upload-dialog-button-back": "Natrag",
        "upload-dialog-button-done": "Gotovo",
        "upload-dialog-button-save": "Spremi",
        "upload-dialog-button-upload": "Postavi",
        "checkbox-select": "Odaberite: $1",
        "checkbox-all": "Sve",
        "checkbox-none": "Nijedan",
+       "checkbox-invert": "Obrnuto",
        "allpages": "Sve stranice",
        "nextpage": "Sljedeća stranica ($1)",
        "prevpage": "Prethodna stranica ($1)",
        "listgrouprights-removegroup-self-all": "Uklonite sve skupine iz vlastitog računa",
        "listgrouprights-namespaceprotection-header": "Ograničenja prostora imena",
        "listgrouprights-namespaceprotection-namespace": "Imenski prostor",
+       "listgrants": "Dozvole",
+       "listgrants-summary": "Slijedi popis dozvola s pridruženim pristupom suradničkim pravima. Suradnici mogu omogućiti aplikacijama uporabu svojih računa, ali s ograničenim ovlastima na temelju dozvola koje je suradnik dodijelio aplikaciji. Aplikacija koja djeluje u ime suradnika međutim ne može rabiti prava koje suradnik nema.\nMoguće su [[{{MediaWiki:Listgrouprights-helppage}}|dodatne informacije]] o pojedinim pravima.",
+       "listgrants-grant": "Dozvola",
+       "listgrants-rights": "Prava",
        "trackingcategories-nodesc": "Opis nije dostupan.",
        "mailnologin": "Nema adrese pošiljatelja",
        "mailnologintext": "Morate biti [[Special:UserLogin|prijavljeni]]\ni imati valjanu adresu e-pošte u svojim [[Special:Preferences|postavkama]]\nda bi mogli slati poštu drugim suradnicima.",
        "emailccsubject": "Kopija Vaše poruke suradniku $1: $2",
        "emailsent": "E-mail poslan",
        "emailsenttext": "Vaša poruka je poslana.",
-       "emailuserfooter": "Ova je poruka poslana od $1 za $2 uporabom \"elektroničke pošte\" s projekta {{SITENAME}}.",
+       "emailuserfooter": "Ovu je e-poruku {{GENDER:$1|poslao suradnik|poslala suradnica}} $1 {{GENDER:$2|suradniku $2|suradnici $2}} uporabom mogućnosti \"{{int:emailuser}}\" s projekta {{SITENAME}}.",
        "usermessage-summary": "Ostavljanje poruke sustava.",
        "usermessage-editor": "Uređivač sistemskih poruka",
-       "watchlist": "Moj popis praćenja",
+       "watchlist": "Popis praćenja",
        "mywatchlist": "Popis praćenja",
        "watchlistfor2": "Za $1 $2",
        "nowatchlist": "Na Vašem popisu praćenja nema nijednog članka.",
        "rollback-success": "uklonjeno uređivanje {{GENDER:$1|suradnika|suradnice}} $1\nvraćeno na posljednju inačicu {{GENDER:$2|suradnika|suradnice}} $2.",
        "sessionfailure-title": "Prekid sesije",
        "sessionfailure": "Uočili smo problem s Vašom prijavom. Zadnja naredba nije izvršena kako bi se izbjegla zloupotreba. Molimo Vas da se u pregledniku vratite natrag na prethodnu stranicu, ponovno je učitate i zatim pokušate opet.",
+       "changecontentmodel": "Promijeni model sadržaja stranice",
        "changecontentmodel-legend": "Promijeni model sadržaja",
        "changecontentmodel-title-label": "Naziv stranice",
        "changecontentmodel-model-label": "Novi model sadržaja",
        "tooltip-pt-preferences": "Vaše postavke",
        "tooltip-pt-watchlist": "Popis stranica koje pratite.",
        "tooltip-pt-mycontris": "Popis Vaših doprinosa",
-       "tooltip-pt-login": "Predlažemo Vam da se prijavite, ali nije obvezno.",
+       "tooltip-pt-login": "Predlažemo Vam da se prijavite, međutim nije obvezno.",
        "tooltip-pt-logout": "Odjavi se",
-       "tooltip-pt-createaccount": "Nudimo vam mogućnost da napravite račun i prijavite se, iako to nije nužno.",
+       "tooltip-pt-createaccount": "Predlažemo Vam mogućnost stvaranja računa i prijave, iako to nije nužno.",
        "tooltip-ca-talk": "Razgovor o stranici",
        "tooltip-ca-edit": "Uredi ovu stranicu",
        "tooltip-ca-addsection": "Dodaj novi odlomak",
        "tooltip-ca-viewsource": "Ova stranica je zaštićena. Možete pogledati izvorni kod.",
-       "tooltip-ca-history": "Ranije izmjene na ovoj stranici.",
+       "tooltip-ca-history": "Ranije izmjene na ovoj stranici",
        "tooltip-ca-protect": "Zaštiti ovu stranicu",
        "tooltip-ca-unprotect": "Ukloni zaštitu s ove stranice",
        "tooltip-ca-delete": "Izbriši ovu stranicu",
        "tooltip-ca-move": "Premjesti ovu stranicu",
        "tooltip-ca-watch": "Dodaj ovu stranicu na svoj popis praćenja",
        "tooltip-ca-unwatch": "Ukloni ovu stranicu s popisa praćenja",
-       "tooltip-search": "Pretraži ovaj wiki",
+       "tooltip-search": "Pretraži {{SITENAME}}",
        "tooltip-search-go": "Idi na stranicu s ovim imenom ako ona postoji",
        "tooltip-search-fulltext": "Traži ovaj tekst na svim stranicama",
-       "tooltip-p-logo": "Glavna stranica",
+       "tooltip-p-logo": "Posjeti glavnu stranicu",
        "tooltip-n-mainpage": "Posjeti glavnu stranicu",
        "tooltip-n-mainpage-description": "Posjeti glavnu stranicu",
-       "tooltip-n-portal": "O projektu, što možete učiniti, gdje je što",
-       "tooltip-n-currentevents": "O trenutačnim događajima",
-       "tooltip-n-recentchanges": "Popis nedavnih promjena u wikiju.",
+       "tooltip-n-portal": "O projektu, što možete učiniti, gdje se što nalazi",
+       "tooltip-n-currentevents": "Saznajte više o trenutačnim događajima",
+       "tooltip-n-recentchanges": "Popis nedavnih promjena u wikiju",
        "tooltip-n-randompage": "Učitaj slučajnu stranicu",
-       "tooltip-n-help": "Mjesto za pomoć suradnicima.",
-       "tooltip-t-whatlinkshere": "Popis stranica koje sadrže poveznice na ovu stranicu",
+       "tooltip-n-help": "Mjesto gdje se može dobiti pomoć",
+       "tooltip-t-whatlinkshere": "Popis svih stranica koje sadrže poveznice na ovu stranicu",
        "tooltip-t-recentchangeslinked": "Nedavne promjene na stranicama na koje vode ovdašnje poveznice",
        "tooltip-feed-rss": "RSS feed za ovu stranicu",
        "tooltip-feed-atom": "Atom feed za ovu stranicu",
        "tooltip-t-contributions": "Pogledaj popis doprinosa {{GENDER:$1|ovog suradnika|ove suradnice}}",
        "tooltip-t-emailuser": "Pošalji suradniku e-mail",
        "tooltip-t-info": "Više informacija o ovoj stranici",
-       "tooltip-t-upload": "Postavi slike i druge medije",
-       "tooltip-t-specialpages": "Popis posebnih stranica",
-       "tooltip-t-print": "Verzija za ispis ove stranice",
+       "tooltip-t-upload": "Postavi datoteke",
+       "tooltip-t-specialpages": "Popis svih posebnih stranica",
+       "tooltip-t-print": "Inačica za ispis ove stranice",
        "tooltip-t-permalink": "Trajna poveznica na ovu verziju stranice",
        "tooltip-ca-nstab-main": "Pogledaj sadržaj",
        "tooltip-ca-nstab-user": "Pogledaj suradničku stranicu",
        "htmlform-cloner-create": "Dodaj još",
        "htmlform-cloner-delete": "Ukloni",
        "htmlform-cloner-required": "Potrebna je barem jedna vrijednost.",
+       "htmlform-date-placeholder": "GGGG-MM-DD",
+       "htmlform-time-placeholder": "HH:MM:SS",
+       "htmlform-datetime-placeholder": "GGGG-MM-DD HH:MM:SS",
+       "htmlform-time-invalid": "Unesena vrijednost nije prepoznati format vremena. Pokušajte koristiti format HH:MM:SS.",
+       "htmlform-datetime-toohigh": "Uneseni datum i vrijeme su veći od $1",
        "logentry-delete-delete": "$1 je {{GENDER:$2|obrisao|obrisala}} stranicu $3",
        "logentry-delete-restore": "$1 je {{GENDER:$2|vratio|vratila}} stranicu $3",
        "logentry-delete-event": "$1 je {{GENDER:$2|promijenio|promijenila}} vidljivost {{PLURAL:$5|zapisa u evidenciji|$5 zapisa u evidenciji}} na $3: $4",
        "mw-widgets-titleinput-description-redirect": "preusmjeravanje na $1",
        "log-action-filter-block": "Vrsta blokiranja:",
        "log-action-filter-newusers": "Način stvaranja računa:",
+       "log-action-filter-patrol": "Vrsta pregledavanja:",
        "log-action-filter-upload": "Vrsta postavljanja:",
        "log-action-filter-all": "sve",
        "log-action-filter-block-block": "blokiranje",
        "log-action-filter-newusers-create2": "stvorio registrirani suradnik",
        "log-action-filter-newusers-autocreate": "automatski stvoren",
        "log-action-filter-newusers-byemail": "stvoren lozinkom poslanom na e-poštu",
+       "log-action-filter-patrol-patrol": "Ručno pregledavanje",
+       "log-action-filter-patrol-autopatrol": "Automatsko pregledavanje",
        "log-action-filter-upload-upload": "novo postavljanje",
-       "log-action-filter-upload-overwrite": "ponovno postavljanje"
+       "log-action-filter-upload-overwrite": "ponovno postavljanje",
+       "changecredentials": "Promjena vjerodajnica",
+       "removecredentials": "Uklanjanje vjerodajnica"
 }
index aebeaf2..97f9194 100644 (file)
        "upload-dialog-disabled": "Il caricamento di file tramite questa finestra di dialogo è disabilitato in questo wiki.",
        "upload-dialog-title": "Carica file",
        "upload-dialog-button-cancel": "Annulla",
+       "upload-dialog-button-back": "Indietro",
        "upload-dialog-button-done": "Fatto",
        "upload-dialog-button-save": "Salva",
        "upload-dialog-button-upload": "Carica",
        "htmlform-cloner-create": "Aggiungi altro",
        "htmlform-cloner-delete": "Rimuovi",
        "htmlform-cloner-required": "È obbligatorio almeno un valore.",
+       "htmlform-date-placeholder": "AAAA-MM-GG",
+       "htmlform-time-placeholder": "HH:MM:SS",
+       "htmlform-datetime-placeholder": "AAAA-MM-GG HH:MM:SS",
+       "htmlform-date-invalid": "Il valore specificato non è riconosciuto come data. Prova a utilizzare il formato AAAA-MM-GG.",
+       "htmlform-time-invalid": "Il valore specificato non è riconosciuto come orario. Prova a utilizzare il formato HH:MM:SS.",
+       "htmlform-datetime-invalid": "Il valore specificato non è riconosciuto come data e ora. Prova a utilizzare il formato AAAA-MM-GG HH:MM:SS.",
+       "htmlform-date-toolow": "Il valore specificato è precedente alla prima data consentita del $1.",
+       "htmlform-date-toohigh": "Il valore specificato è successivo all'ultima data consentita del $1.",
+       "htmlform-time-toolow": "Il valore specificato è precedente al primo orario consentito del $1.",
+       "htmlform-time-toohigh": "Il valore specificato è successivo all'ultimo orario consentito di $1.",
+       "htmlform-datetime-toolow": "Il valore specificato è precedente alla prima data e ora consentita del $1.",
+       "htmlform-datetime-toohigh": "Il valore specificato è successivo all'ultima data e ora consentita del $1.",
        "htmlform-title-badnamespace": "[[:$1]] non si trova nel namespace \"{{ns:$2}}\".",
        "htmlform-title-not-creatable": "\"$1\" è il titolo di una pagina non creabile",
        "htmlform-title-not-exists": "$1 non esiste.",
        "linkaccounts-success-text": "L'utenza è stata collegata.",
        "linkaccounts-submit": "Collega utenze",
        "unlinkaccounts": "Scollega utenze",
-       "unlinkaccounts-success": "L'utenza è stata scollegata."
+       "unlinkaccounts-success": "L'utenza è stata scollegata.",
+       "restrictionsfield-badip": "Indirizzo IP o intervallo non valido: $1",
+       "restrictionsfield-label": "Intervalli IP consentiti:",
+       "restrictionsfield-help": "Un indirizzo IP o intervallo CIDR per linea. Per consentire tutto, utilizza<br><code>0.0.0.0/0</code><br><code>::/0</code>"
 }
index 981bb72..ef53d84 100644 (file)
        "createaccountreason": "Себебі:",
        "createacct-reason": "Себебі:",
        "createacct-reason-ph": "Неге басқа тіркегі жасамақшысыз",
-       "createacct-submit": "Тіркелгіңізді жасаңыз",
+       "createacct-submit": "Тіркеліңіз",
        "createacct-another-submit": "Тіркелгі жасау",
        "createacct-continue-submit": "Тіркелуді жалғастыру",
        "createacct-benefit-heading": "{{SITENAME}} сіздермен жасалады.",
index 5d2c25c..f09c38b 100644 (file)
@@ -36,6 +36,7 @@
        "tog-hideminor": "ಇತ್ತೀಚಿನ ಬದಲಾವಣೆಗಳಲ್ಲಿ ಚಿಕ್ಕಪುಟ್ಟ ಸಂಪಾದನೆಗಳನ್ನು ಅಡಗಿಸಿ",
        "tog-hidepatrolled": "ಪಹರೆಯಲ್ಲಿ ಆದ ಸಂಪಾದನೆಗಳನ್ನು ಇತ್ತೀಚೆಗಿನ ಬದಲಾವಣೆಗಳಲ್ಲಿ ಅಡಗಿಸು",
        "tog-newpageshidepatrolled": "ಪಹರೆಯಲ್ಲಿ ಆದ ಪುಟಗಳನ್ನು ಹೊಸ ಪುಟಗಳ ಪಟ್ಟಿಯಲ್ಲಿ ಅಡಗಿಸು",
+       "tog-hidecategorization": "ಪುಟಗಳ ವರ್ಗೀಕರಣವನ್ನು ಅಡಗಿಸು",
        "tog-extendwatchlist": "ಕೇವಲ ಇತ್ತೀಚೆಗಿನ ಬದಲಾವಣೆಗಳಲ್ಲದೆ, ಎಲ್ಲಾ ಬದಲಾವಣೆಗಳನ್ನು ತೋರುವಂತೆ ಪಟ್ಟಿಯನ್ನು ವಿಸ್ತರಿಸಿ",
        "tog-usenewrc": "ಹೆಚ್ಚು ವರ್ಧಿಸಲಾದ ಇತ್ತೀಚಿನ ಬದಲಾವಣೆಗಳು ಪುಟ ಬಳಸು",
        "tog-numberheadings": "ತಲೆಬರಹಗಳಿಗೆ ಅಂಕಿಗಳನ್ನು ತೋರಿಸು",
@@ -46,6 +47,7 @@
        "tog-watchdefault": "ನಾನು ಸಂಪಾದಿಸುವ ಪುಟಗಳನ್ನು ವೀಕ್ಷಣಾಪಟ್ಟಿಗೆ ಸೇರಿಸು",
        "tog-watchmoves": "ನಾನು ಸ್ಥಳಾಂತರಿಸುವ ಪುಟಗಳನ್ನು ನನ್ನ ವೀಕ್ಷಣಾಪಟ್ಟಿಗೆ ಸೇರಿಸು",
        "tog-watchdeletion": "ನಾನು ಅಳಿಸುವ ಪುಟಗಳನ್ನು ನನ್ನ ವೀಕ್ಷಣಾ ಪಟ್ಟಿಗೆ ಸೇರಿಸು",
+       "tog-watchuploads": "ನಾನು ಹೊಸದಾಗಿ ಅಪ್‍ಲೋಡ್ ಮಾಡಿದ ಫೈಲ್‍ಗಳನ್ನು ನನ್ನ ವೀಕ್ಷಣಾಪಟ್ಟಿಗೆ ಸೇರಿಸು",
        "tog-watchrollback": "ನಾನು ಹಿಮ್ಮರಳುವಿಕೆಯನ್ನು ನಡೆಸಿದ ಪುಟಗಳನ್ನು ನನ್ನ ಗಮನಸೂಚಿಗೆ ಸೇರಿಸು",
        "tog-minordefault": "ನನ್ನ ಎಲ್ಲಾ ಸಂಪಾದನೆಗಳನ್ನು ಚುಟುಕಾದವು ಎಂದು ಗುರುತು ಮಾಡು",
        "tog-previewontop": "ಮುನ್ನೋಟವನ್ನು ಸಂಪಾದನೆ ಚೌಕದ ಮುಂಚೆ ತೋರು",
@@ -55,7 +57,7 @@
        "tog-enotifminoredits": "ಚಿಕ್ಕ-ಪುಟ್ಟ ಬದಲಾವಣೆಗಳಾದಾಗಲೂ ಇ-ಅಂಚೆ ಕಳುಹಿಸು",
        "tog-enotifrevealaddr": "ಪ್ರಕಟಣೆ ಇ-ಅಂಚೆಗಳಲ್ಲಿ ನನ್ನ ಇ-ಅಂಚೆ ವಿಳಾಸ ತೋರು",
        "tog-shownumberswatching": "ಪುಟವನ್ನು ವೀಕ್ಷಿಸುತ್ತಿರುವ ಸದಸ್ಯರ ಸಂಖ್ಯೆಯನ್ನು ತೋರಿಸು",
-       "tog-oldsig": "ಪ್ರಸ್ತುತ ಸಹಿ",
+       "tog-oldsig": "ನಿಮà³\8dಮ à²ªà³\8dರಸà³\8dತà³\81ತ à²¸à²¹à²¿",
        "tog-fancysig": "ಸರಳ ಸಹಿಗಳು (ಕೊಂಡಿ ಇಲ್ಲದಿರುವಂತೆ)",
        "tog-uselivepreview": "ನೇರ ಮುನ್ನೋಟವನ್ನು ಉಪಯೋಗಿಸಿ",
        "tog-forceeditsummary": "ಸಂಪಾದನೆ ಸಾರಾಂಶವನ್ನು ಖಾಲಿ ಬಿಟ್ಟಲ್ಲಿ ನೆನಪಿಸು",
        "tog-watchlisthideliu": "ಲಾಗ್ ಇನ್ ಆಗಿರುವ ಸದಸ್ಯರ ಸಂಪಾದನೆಗಳನ್ನು ವೀಕ್ಷಣಾಪಟ್ಟಿಯಲ್ಲಿ ಅಡಗಿಸು",
        "tog-watchlisthideanons": "ಅನಾಮಧೇಯ ಬಳಕೆದಾರರ ಸಂಪಾದನೆಗಳನ್ನು ವೀಕ್ಷಣಾಪಟ್ಟಿಯಲ್ಲಿ ಅಡಗಿಸು",
        "tog-watchlisthidepatrolled": "ವೀಕ್ಷಣಾ ಪತ್ತಿಯಲ್ಲಿ ಹಸ್ತುಕದರ್ ಬದಲಾವಣೆಗಳನ್ನು ಅದಗಿಸು",
+       "tog-watchlisthidecategorization": "ಪುಟಗಳ ವರ್ಗೀಕರಣವನ್ನು ಅಡಗಿಸು",
        "tog-ccmeonemails": "ಇತರರಿಗೆ ನಾನು ಕಳುಹಿಸುವ ಇ-ಅಂಚೆಯ ಪ್ರತಿಯನ್ನು ನನಗೂ ಕಳುಹಿಸು",
        "tog-diffonly": "ವ್ಯತ್ಯಾಸಗಳ ಕೆಳಗಿರುವ ಪುಟದ ವಿವರಗಳನ್ನು ತೋರಿಸಬೇಡ",
        "tog-showhiddencats": "ಅಡಗಿಸಲ್ಪಟ್ಟ ವರ್ಗಗಳನ್ನು ತೋರಿಸು",
-       "tog-norollbackdiff": "ತà³\8aಡà³\86ದà³\81ಹಾà²\95ಿದ à²¨à²\82ತರ à²µà³\8dಯತà³\8dಯಸವನà³\8dನà³\81 à²¬à²¿à²¦à³\81",
+       "tog-norollbackdiff": "ತà³\8aಡà³\86ದà³\81ಹಾà²\95ಿದ à²¨à²\82ತರ à²µà³\8dತà³\8dಯತà³\8dಯಾಸವನà³\8dನà³\81 à²¤à³\8bರಿಸಬà³\87ಡ",
        "tog-useeditwarning": "ಸಂಪಾದನೆಯನ್ನು ಉಳಿಸದೆ ಹೊರಟಲ್ಲಿ ನನಗೆ ಎಚ್ಚರಿಸು",
        "tog-prefershttps": "ಯಾವತ್ತು ಸಹ ಲಾಗಿನ್ ನಂತರ ಸುರಕ್ಷಿತ ಸಂಪರ್ಕವನ್ನು ಬಳಸಿ",
        "underline-always": "ಯಾವಾಗಲೂ",
        "october-date": "ಅಕ್ಟೋಬರ್ $1",
        "november-date": "ನವೆಂಬರ್ $1",
        "december-date": "ಡಿಸೆಂಬರ್ $1",
+       "period-am": "ಪೂರ್ವಾಹ್ನ",
+       "period-pm": "ಅಪರಾಹ್ನ",
        "pagecategories": "{{PLURAL:$1|ವರ್ಗ|ವರ್ಗಗಳು}}",
        "category_header": "\"$1\" ವರ್ಗದಲ್ಲಿರುವ ಲೇಖನಗಳು",
        "subcategories": "ಉಪವರ್ಗಗಳು",
        "newwindow": "(ಹೊಸ ಕಿಟಕಿಯಲ್ಲಿ ತೆರೆಯುತ್ತದೆ)",
        "cancel": "ರದ್ದುಮಾಡು",
        "moredotdotdot": "ಇನ್ನಷ್ಟು...",
-       "morenotlisted": "à²\88 à²ªà²\9fà³\8dà²\9fಿ à²ªà³\82ರ à²\87ಲà³\8dಲ.",
+       "morenotlisted": "à²\88 à²ªà²\9fà³\8dà²\9fಿ à²\85ಪರಿಪà³\82ರà³\8dಣವಾà²\97ಿರಬಹà³\81ದà³\81.",
        "mypage": "ಪುಟ",
        "mytalk": "ಚರ್ಚೆ",
        "anontalk": "ಚರ್ಚೆ",
        "yourpasswordagain": "ಪ್ರವೇಶ ಪದ ಮತ್ತೊಮ್ಮೆ ಟೈಪ್ ಮಾಡಿ",
        "createacct-yourpasswordagain": "ಪ್ರವೇಶಪದವನ್ನು ಧೃಡೀಕರಿಸಿ",
        "createacct-yourpasswordagain-ph": "ಪ್ರವೇಶಪದವನ್ನು ಮತ್ತೊಮ್ಮೆ ನಮೂದಿಸಿ",
-       "remembermypassword": "ಈ ಗಣಕಯಂತ್ರದಲ್ಲಿ ನನ್ನ ಲಾಗಿನ್ ನೆನಪಿನಲ್ಲಿಟ್ಟುಕೊ (ಗರಿಷ್ಠ $1 {{PLURAL:$1|ದಿನದ|ದಿನಗಳ}}ವರೆಗೆ)",
        "userlogin-remembermypassword": "ನನ್ನನ್ನು ಲಾಗಿನ್ ಆಗಿಯೇ ಇಡಿ",
        "userlogin-signwithsecure": "ಸುರಕ್ಷಿತವಾದ ಕನೆಕ್ಷನ್ ಉಪಯೋಗಿಸಿ.",
        "yourdomainname": "ನಿಮ್ಮ ಕ್ಷೇತ್ರ:",
index b08be9a..f8b033b 100644 (file)
        "talk": "토론",
        "views": "보기",
        "toolbox": "도구",
+       "tool-link-userrights": "{{GENDER:$1|사용자}} 그룹 변경",
        "tool-link-emailuser": "이 {{GENDER:$1|사용자}}에게 이메일 보내기",
        "userpage": "사용자 문서 보기",
        "projectpage": "프로젝트 문서 보기",
        "upload-dialog-disabled": "이 대화창을 이용한 파일 올리기는 이 위키에서 비활성화되어 있습니다.",
        "upload-dialog-title": "파일 올리기",
        "upload-dialog-button-cancel": "취소",
+       "upload-dialog-button-back": "뒤로",
        "upload-dialog-button-done": "완료",
        "upload-dialog-button-save": "저장",
        "upload-dialog-button-upload": "올리기",
        "htmlform-cloner-create": "더 추가",
        "htmlform-cloner-delete": "제거",
        "htmlform-cloner-required": "적어도 하나의 값이 필요합니다.",
+       "htmlform-date-placeholder": "YYYY-MM-DD",
+       "htmlform-time-placeholder": "HH:MM:SS",
+       "htmlform-datetime-placeholder": "YYYY-MM-DD HH:MM:SS",
        "htmlform-title-badnamespace": "[[:$1]] 문서는 \"{{ns:$2}}\" 이름공간에 없습니다.",
        "htmlform-title-not-creatable": "\"$1\"은 만들 수 없는 문서 제목입니다.",
        "htmlform-title-not-exists": "$1 문서는 존재하지 않습니다.",
        "unlinkaccounts-success": "계정의 연결이 해제되었습니다.",
        "authenticationdatachange-ignored": "인증 데이터 변경을 처리하지 못했습니다. 제공자를 설정하지 않으셨습니까?",
        "userjsispublic": "주목해 주십시오: 자바스크립트의 하위 문서들은 다른 사용자들이 볼 수 있기 때문에 기밀 데이터를 포함해서는 안 됩니다.",
-       "usercssispublic": "주목해 주십시오: CSS의 하위 문서들은 다른 사용자들이 볼 수 있기 때문에 기밀 데이터를 포함해서는 안 됩니다."
+       "usercssispublic": "주목해 주십시오: CSS의 하위 문서들은 다른 사용자들이 볼 수 있기 때문에 기밀 데이터를 포함해서는 안 됩니다.",
+       "restrictionsfield-badip": "유효하지 않은 IP 주소나 대역: $1",
+       "restrictionsfield-label": "허용된 IP 대역:"
 }
index cf3b8ba..5106ff4 100644 (file)
        "talk": "Diskussioun",
        "views": "Affichagen",
        "toolbox": "Geschirkëscht",
+       "tool-link-userrights": "{{GENDER:$1|Benotzer}}gruppen änneren",
        "tool-link-emailuser": "{{GENDER:$1|Dëser Benotzerin|Dësem Benotzer}} eng Mail schécken",
        "userpage": "Benotzersäit",
        "projectpage": "Meta-Text",
        "eauthentsent": "Eng Confirmatiouns-E-Mail gouf un déi Adress geschéckt déi Dir uginn hutt.\n\nIer iergendeng E-Mail vun anere Benotzer op dee Kont geschéckt ka ginn, musst Dir als éischt d'Instructiounen an der Confirmatiouns-E-Mail befollegen, fir ze bestätegen datt de Kont wierklech Ären eegenen ass.",
        "throttled-mailpassword": "An {{PLURAL:$1|der leschter Stonn|de leschte(n) $1 Stonnen}} eng E-Mail verschéckt fir d'Passwuert zréckzesetzen.\nFir de Mëssbrauch vun dëser Funktioun ze verhënneren kann nëmmen all {{PLURAL:$1|Stonn|$1 Stonnen}} sou eng Mail verschéckt ginn.",
        "mailerror": "Feeler beim Schécke vun der E-Mail: $1",
-       "acct_creation_throttle_hit": "Visiteure vun dëser Wiki déi Är IP-Adress hu {{PLURAL:$1|schonn $1 Benotzerkont|scho(nn) $1 Benotzerkonten}} an de leschten Deeg opgemaach, dëst ass déi maximal Zuel déi an dësem Zäitraum erlaabt ass.\nDofir kënne Visiteure déi dës IP-Adress benotzen den Ament keng Benotzerkonten opmaachen.",
+       "acct_creation_throttle_hit": "Visiteure vun dëser Wiki déi Är IP-Adress hu {{PLURAL:$1|schonn $1 Benotzerkont|scho(nn) $1 Benotzerkonten}} an de leschten $2 Deeg opgemaach, dëst ass déi maximal Zuel déi an dësem Zäitraum erlaabt ass.\nDofir kënne Visiteure déi dës IP-Adress benotzen den Ament keng Benotzerkonten opmaachen.",
        "emailauthenticated": "Är E-Mail-Adress gouf den $2 ëm $3 Auer bestätegt.",
        "emailnotauthenticated": "Är E-Mail Adress gouf nach net confirméiert.\nDowéinst gëtt fir keng vun dëse Funktiounen E-Maile geschéckt.",
        "noemailprefs": "Gitt eng E-Mailadress bei Ären Astellungen un, fir datt déi Funktioune funktionéieren.",
        "botpasswords-label-cancel": "Ofbriechen",
        "botpasswords-label-delete": "Läschen",
        "botpasswords-label-resetpassword": "D'Passwuert zrécksetzen",
+       "botpasswords-label-grants": "Applikabel Rechter:",
        "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-grants-column": "Accordéiert",
        "botpasswords-bad-appid": "Den Numm vum Bot \"$1\" ass net valabel.",
        "content-not-allowed-here": "\"$1\"-Inhalt ass op der Säit [[$2]] net erlaabt",
        "editwarning-warning": "Wann Dir dës Säit verloosst kann dat dozou féieren datt Dir all Ännerungen, déi Dir gemaach hutt, verléiert.\nWann Dir ageloggt sidd, kënnt Dir dës Warnung an der Sektioun \"{{int:prefs-editing}}\" vun Ären Astellungen ausschalten.",
        "editpage-invalidcontentmodel-title": "Modell vum Inhalt gëtt net ënnerstëtzt",
+       "editpage-invalidcontentmodel-text": "Den Inhaltsmodell \"$1\" gëtt net ënnerstëtzt.",
        "editpage-notsupportedcontentformat-title": "Format vum Inhalt gëtt net ënnerstëtzt",
        "editpage-notsupportedcontentformat-text": "De Format vum Inhalt $1 gëtt net vum Modell vum Inhalt $2 ënnerstëtzt.",
        "content-model-wikitext": "Wikitext",
        "content-model-css": "CSS",
        "content-json-empty-object": "Eidelen Objet",
        "content-json-empty-array": "Eidel Tabell",
+       "deprecated-self-close-category": "Säiten déi net valabel 'self-closed' HTML-Tags benotzen",
        "duplicate-args-warning": "<strong>Opgepasst:</strong> [[:$1]] rifft [[:$2]] mat méi wéi engem Wäert fir de Parameter \"$3\" op. Nëmmen de leschte Wäert gëtt benotzt.",
        "duplicate-args-category": "Säiten, déi duebel Argumenter a Schablounenopriff gebrauchen",
        "expensive-parserfunction-warning": "'''Opgepasst:'' Dës Säit huet ze vill Ufroe vu komplexe Parserfunktiounen.\n\nEt däerfen net méi wéi $2 {{PLURAL:$2|Ufro|Ufroe}} sinn, aktuell {{PLURAL:$2|ass et $1 Ufro|sinn et $1 Ufroe}}.",
        "showingresultsinrange": "Hei drënner {{PLURAL:$1|<strong>gëtt 1</strong> Resultat|gi(nn) <strong>$1</strong> Resultater}} aus dem Beräich #<strong>$2</strong> bis #<strong>$3</strong>.",
        "search-showingresults": "{{PLURAL:$4|Resultat <strong>$1</strong> of <strong>$3</strong>|Resultater <strong>$1 - $2</strong> vu(n) <strong>$3</strong>}}",
        "search-nonefound": "Fir Är Ufro gouf näischt fonnt.",
+       "search-nonefound-thiswiki": "Et gouf op dësem Site näischt fonnt wat Ärer Ufro entsprécht.",
        "powersearch-legend": "Erweidert Sich",
        "powersearch-ns": "Sichen an den Nummraim:",
        "powersearch-togglelabel": "Markéieren:",
        "action-viewmyprivateinfo": "Är privat Informatioune kucken",
        "action-editmyprivateinfo": "Är privat Informatiounen änneren",
        "action-editcontentmodel": "de Modell vum Inhalt vun enger Säit änneren",
+       "action-deletechangetags": "Markéierungen aus der Datebank läschen",
        "action-purge": "dës Säit eidelzemaachen",
        "nchanges": "$1 {{PLURAL:$1|Ännerung|Ännerungen}}",
        "enhancedrc-since-last-visit": "$1 {{PLURAL:$1|zanter dem leschte Passage}}",
        "file-thumbnail-no": "Den Numm vum Fichier fänkt mat <strong>$1</strong> un.\nDa deit drop hin datt et eng Minitaur ''(thumbnail)'' ass.\nWann Dir dat Bild a méi enger grousser Opléisung hutt, da luet dëst erop, wann net dann ännert w.e.g. den Numm vum Fichier.",
        "fileexists-forbidden": "Et gëtt schonn e Fichier mat dësem Numm an dee kann net iwwerschriwwe ginn.\nWann Dir de Fichier nach ëmmer eropluede wëllt, da gitt w.e.g. zréck a benotzt en neien Numm. [[File:$1|thumb|center|$1]]",
        "fileexists-shared-forbidden": "E Fichier mat dësem Numm gëtt et schonn an dem gedeelte Repertoire.\nWann Dir dëse Fichier trotzdeem eropluede wëllt da gitt w.e.g. zréck a luet dëse Fichier ënner engem aneren Numm erop. [[File:$1|thumb|center|$1]]",
+       "fileexists-no-change": "Den eropgeluedene Fichier ass en exakten Duplikat vun der aktueller Versioun vu(n) <strong>[[:$1]]",
+       "fileexists-duplicate-version": "Den eropgeluedene Fichier ass en exakten Duplikat vun {{PLURAL:$2|enger eelerer Versioun|eelere Versioune}} vu(n) <strong>[[:$1]]</strong>.",
        "file-exists-duplicate": "Dëse Fichier schéngt een Doublon vun {{PLURAL:$1|dësem Fichier|dëse Fichieren}} ze sinn:",
        "file-deleted-duplicate": "En identesche Fichier ([[:$1]]) gouf virdru geläscht. Kuckt w.e.g. an der Lëscht vum Läschen no, ier Dir en nach emol eropluet.",
        "file-deleted-duplicate-notitle": "En identesche Fichier gouf scho geläscht an den Titel gouf suppriméiert. Dir sollt e froen dee suppriméiert Date vu Fichiere kucken däerf fir d'Situatioun ze klären ier Dir de Fichier nach eng Kéier eroplued.",
        "php-uploaddisabledtext": "D'Eropluede vu Fichieren ass am PHP desaktivéiert. Kuckt w.e.g. d'Astellung ''file_uploads'' no.",
        "uploadscripted": "An dësem Fichier ass HTML- oder Scriptcode, dee vun engem Webbrowser falsch interpretéiert kéint ginn.",
        "upload-scripted-pi-callback": "Et ass net méiglech XML-Fichieren eropzelueden an deenen XML-Stylesheet Instruktioune fir d'Verschaffen drastinn",
+       "uploaded-hostile-svg": "Net sécheren CSS am Stilelement vum eropgeluedene SVG-Fichier fonnt.",
        "uploadscriptednamespace": "An dësem SVG-Fichier ass en illegalen Nummraum \"$1\"",
        "uploadinvalidxml": "Den XML am eropgelueden Fichier konnt net verschafft ginn.",
        "uploadvirus": "An dësem Fichier ass ee Virus! Detailer: $1",
        "upload-dialog-disabled": "D'Eropluede vu Fichieren mat dësem Dialog ass op dëser Wiki desaktivéiert.",
        "upload-dialog-title": "Fichier eroplueden",
        "upload-dialog-button-cancel": "Ofbriechen",
+       "upload-dialog-button-back": "Zréck",
        "upload-dialog-button-done": "Fäerdeg",
        "upload-dialog-button-save": "Späicheren",
        "upload-dialog-button-upload": "Eroplueden",
        "changecontentmodel-success-title": "De Modell vum Inhalt gouf geännert",
        "changecontentmodel-success-text": "Den Typ vum Inhalt vu(n) [[:$1]] gouf geännert.",
        "changecontentmodel-cannot-convert": "Den Inhalt vu(n) [[:$1]] kann net op den Typ $2 ëmgewandelt ginn.",
+       "changecontentmodel-nodirectediting": "Den Inhaltsmodell $1 ënnerstëtzt keng direkt Ännerungen",
        "changecontentmodel-emptymodels-title": "Keng Modeller fir Inhalter disponibel",
        "logentry-contentmodel-change-revertlink": "zrécksetzen",
        "logentry-contentmodel-change-revert": "zrécksetzen",
        "htmlform-cloner-create": "Méi derbäisetzen",
        "htmlform-cloner-delete": "Ewechhuelen",
        "htmlform-cloner-required": "Mindestens ee Wäert ass obligatoresch.",
+       "htmlform-date-placeholder": "JJJJ-MM-DD",
+       "htmlform-time-placeholder": "HH:MM:SS",
+       "htmlform-datetime-placeholder": "JJJJ-MM-DD HH:MM:SS",
+       "htmlform-date-invalid": "De Wäert deen Dir aginn hutt gouf net als Datum erkannt. Probéiert de Format JJJJ-MM-DD ze benotzen.",
+       "htmlform-time-invalid": "De Wäert deen Dir aginn hutt gouf net als Zäit erkannt. Probéiert de Format HH:MM:SS ze benotzen.",
+       "htmlform-datetime-invalid": "De Wäert deen Dir aginn hutt gouf net als Datum an Zäit erkannt. Probéiert de Format JJJJ-MM-DD HH:MM:SS ze benotzen.",
        "htmlform-title-badnamespace": "[[:$1]] ass net am Nummraum \"{{ns:$2}}\".",
        "htmlform-title-not-creatable": "\"$1\" ass kee Säitentitel deen ugeluecht ka ginn",
        "htmlform-title-not-exists": "$1 gëtt et net.",
        "logentry-newusers-create2": "De Benotzerkont $3 gouf vum $1 {{GENDER:$2|ugeluecht}}",
        "logentry-newusers-byemail": "De Benotzerkont $3 gouf vum $1 {{GENDER:$2|ugeluecht}} an d'Passwuert gouf per E-Mail geschéckt.",
        "logentry-newusers-autocreate": "De Benotzerkont $1 gouf automatesch {{GENDER:$2|ugeluecht}}",
+       "logentry-protect-unprotect": "$1 huet d'Spär vu(n) $3 {{GENDER:$2|ewechgeholl}}",
        "logentry-protect-protect": "$1 {{GENDER:$2|huet}} d'Säit $3 $4 gespaart",
        "logentry-protect-protect-cascade": "$1 {{GENDER:$2|huet}} d'Säit $3 $4 gespaart [Kaskadespär]",
        "logentry-rights-rights": "$1 {{GENDER:$2|huet}} d'Gruppen zou deenen {{GENDER:$6|d'|de}} $3 gehéiert vu(n) $4 op $5 geännert",
        "api-error-nomodule": "Interne Feeler: de Modul fir d'Eroplueden ass net agestallt.",
        "api-error-ok-but-empty": "Interne Feeler: keng Äntwert vum Server.",
        "api-error-overwrite": "D'Iwwerschreiwe vun engem Fichier ass net erlaabt.",
+       "api-error-ratelimited": "Dir probéiert fir méi ££Fichieren a kuerzer Zäit eropzeluede wéi der op dëser Wiki erlaabt sinn. Probéiert w.e.g. an e puer Minutten nach eng Kéier.",
        "api-error-stashfailed": "Interne Feeler: de Server konnt den temporäre Fichier net späicheren.",
        "api-error-publishfailed": "Interne Feeler: de Server konnt den temporäre Fichier net publizéieren.",
        "api-error-stasherror": "Beim Eropluede vum Fichier ass e Feeler geschitt.",
        "log-action-filter-block-reblock": "Ännere vun enger Spär",
        "log-action-filter-block-unblock": "Spär ophiewen",
        "log-action-filter-delete-delete": "Säite läschen",
+       "log-action-filter-delete-restore": "Säiterestauratioun",
+       "log-action-filter-delete-event": "Logbuch-Läschung",
        "log-action-filter-delete-revision": "Läsche vun enger Versioun",
        "log-action-filter-import-interwiki": "Transwiki-Import",
        "log-action-filter-import-upload": "Import duerch Eropluede vun engem XML",
+       "log-action-filter-managetags-create": "Uleeë vun engem Tag",
+       "log-action-filter-managetags-delete": "Läsche vun engem Tag",
+       "log-action-filter-managetags-activate": "Aktivatioun vun engem Tag",
+       "log-action-filter-managetags-deactivate": "Desaktivatioun vun engem Tag",
+       "log-action-filter-move-move": "Réckelen ouni Iwwerschreiwe vu Viruleedungen",
        "log-action-filter-move-move_redir": "Réckele mat Iwwerschreiwe vu Viruleedungen",
        "log-action-filter-newusers-create": "Ugeluecht vun engem anonyme Benotzer",
        "log-action-filter-newusers-create2": "Ugeluecht vun engem registréierte Benotzer",
        "authmanager-create-from-login": "Fir Äre Benotzerkont unzeleeën fëllt w.e.g. d'Felder hei drënner aus.",
        "authmanager-authplugin-setpass-failed-title": "Änner vum Passwuert huet net funktionéiert",
        "authmanager-authplugin-setpass-bad-domain": "Net valabelen Domain.",
+       "authmanager-autocreate-noperm": "Automatescht Uleeë vu Benotzerkonten ass net erlaabt.",
+       "authmanager-autocreate-exception": "Automatescht Uleeë vu Benotzerkonte gouf op Grond vu fréiere Feeler temporär ausgeschalt.",
        "authmanager-userdoesnotexist": "De Benotzerkont \"$1\" ass net registréiert.",
+       "authmanager-userlogin-remembermypassword-help": "Ob d'Passwuert méi laang verhal gi soll wéi d'Dauer vun der Sessioun.",
+       "authmanager-username-help": "Benotzernumm fir d'Authentifikatioun.",
+       "authmanager-password-help": "Passwuert fir d'Authentifikatioun.",
+       "authmanager-domain-help": "Domain fir extern Authentifikatioun",
        "authmanager-retype-help": "Passwuert nach eng Kéier fir ze konfirméieren",
        "authmanager-email-label": "E-Mail",
        "authmanager-email-help": "E-Mail-Adress",
        "authmanager-realname-label": "Richtegen Numm",
        "authmanager-realname-help": "Richtegen Numm vum Benotzer",
+       "authmanager-provider-password": "Authentifikatioun baséiert um Passwuert",
+       "authmanager-provider-password-domain": "Authentifikatioun baséiert um Passwuert an um Domain",
        "authmanager-provider-temporarypassword": "Temporäert Passwuert:",
+       "authprovider-confirmlink-request-label": "Benotzerkonten déi solle verbonn sinn",
+       "authprovider-confirmlink-success-line": "$1: Verbonn",
+       "authprovider-confirmlink-failed": "Verbanne vum Benotzerkont huet net richteg geklappt: $1",
        "authprovider-resetpass-skip-label": "Iwwersprangen",
        "authprovider-resetpass-skip-help": "D'Zrécksetze vum Passwuert iwwersprangen",
        "authform-notoken": "Toke feelt",
        "cannotlink-no-provider-title": "Et gëtt keng Benotzerkonte fir ze verlinken",
        "linkaccounts": "Benotzerkonte verbannen",
        "linkaccounts-submit": "Benotzerkonte verbannen",
-       "userjsispublic": "DEnkt drun: Op JavaScript-Ënnersäite solle keng vertraulech Informatioune stoe well se vun anere Benotzer kënne gesi ginn."
+       "userjsispublic": "DEnkt drun: Op JavaScript-Ënnersäite solle keng vertraulech Informatioune stoe well se vun anere Benotzer kënne gesi ginn.",
+       "restrictionsfield-badip": "Net valabel IP-Adress oder Beräich: $1",
+       "restrictionsfield-label": "Zougeloossen IP-Beräicher:"
 }
index 45b25ac..90f5c98 100644 (file)
        "version-libraries-description": "Aprašymas",
        "version-libraries-authors": "Autoriai",
        "redirect": "Nukreiptas iš failo, naudotojo, versijos arba žurnalo įrašo ID",
-       "redirect-summary": "Šis specialus puslapis peradresuoja į failą (nurodant failo pavadinimą), puslapį (nurodant versijos ID ar puslapio ID), naudotojo puslapį (nurodant skaitinį naudotojo ID), arba žurnalo įrašą (nurodant žurnalo įrašo ID).\nNaudojimas: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/page/64308]], [[{{#Special:Redirect}}/revision/328429]], [[{{#Special:Redirect}}/user/101]], arba[[{{#Special:Redirect}}/logid/186]].",
+       "redirect-summary": "Šis specialus puslapis peradresuoja į failą (nurodant failo pavadinimą), puslapį (nurodant versijos ID ar puslapio ID), naudotojo puslapį (nurodant skaitinį naudotojo ID), arba žurnalo įrašą (nurodant žurnalo įrašo ID). Naudojimas:\n[[{{#Special:Redirect}}/file/Example.jpg]],\n[[{{#Special:Redirect}}/page/64308]],[[{{#Special:Redirect}}/revision/328429]], [[{{#Special:Redirect}}/user/101]], arba\n[[{{#Special:Redirect}}/logid/186]].",
        "redirect-submit": "Eiti",
        "redirect-lookup": "Peržvalgos:",
        "redirect-value": "Vertė:",
index 501bbd7..82bd5ab 100644 (file)
        "subject-preview": "Temata pirmskats:",
        "blockedtitle": "Dalībnieks ir bloķēts.",
        "blockedtext": "'''Tavs lietotāja vārds vai IP adrese ir nobloķēta.'''\n\n$1 nobloķēja tavu lietotāja vārdu vai IP adresi.\nBloķējot norādītais iemesls bija: ''$2''.\n\n*Bloka sākums: $8\n*Bloka beigas: $6\n*Bija domāts nobloķēt: $7\n\nTu vari sazināties ar $1 vai kādu citu [[{{MediaWiki:Grouppage-sysop}}|administratoru]] lai apspriestu šo bloku.\n\nPievērs uzmanību, tam, ka ja tu neesi norādījis derīgu e-pasta adresi ''[[Special:Preferences|savās izvēlēs]]'', tev nedarbosies \"sūtīt e-pastu\" iespēja.\n\nTava IP adrese ir $3 un bloka identifikators ir #$5. Lūdzu iekļauj vienu no tiem, vai abus, visos turpmākajos pieprasījumos.",
-       "autoblockedtext": "Tava IP adrese ir tikusi automātiski nobloķēta, tāpēc, ka to (nupat kā) ir lietojis cits lietotājs, kuru nobloķēja $1.\nNorādītais bloķēšanas iemesls bija:\n\n:''$2''\n\n* Bloka sākums: $8\n* Bloka beigas: $6\n* Bija domāts nobloķēt: $7\n\nTu vari sazināties ar $1 vai kādu citu [[{{MediaWiki:Grouppage-sysop}}|adminu]] lai apspriestu šo bloku.\n\nAtceries, ka tu nevari lietot \"sūtīt e-pastu šim lietotājam\" iespēju, ja tu neesi norādījis derīgu e-pasta adresi savās [[Special:Preferences|lietotāja izvelēs]] un bloķējot tev nav aizbloķēta iespēja sūtīt e-pastu.\n\nTava pašreizējā IP adrese ir $3 un  bloka ID ir $5.\nLūdzu iekļauj šos visos ziņojumos, kurus sūti adminiem, apspriežot šo bloku.",
+       "autoblockedtext": "Tava IP adrese ir tikusi automātiski nobloķēta, tāpēc, ka to (nupat kā) ir lietojis cits dalībnieks, kuru nobloķēja $1.\nNorādītais bloķēšanas iemesls bija:\n\n:''$2''\n\n* Bloka sākums: $8\n* Bloka beigas: $6\n* Bija domāts nobloķēt: $7\n\nTu vari sazināties ar $1 vai kādu citu [[{{MediaWiki:Grouppage-sysop}}|adminu]] lai apspriestu šo bloku.\n\nAtceries, ka tu nevari lietot \"sūtīt e-pastu šim dalībniekam\" iespēju, ja tu neesi norādījis derīgu e-pasta adresi savās [[Special:Preferences|dalībnieka izvelēs]] un bloķējot tev nav aizbloķēta iespēja sūtīt e-pastu.\n\nTava pašreizējā IP adrese ir $3 un  bloka ID ir $5.\nLūdzu iekļauj šos visos ziņojumos, kurus sūti adminiem, apspriežot šo bloku.",
        "blockednoreason": "iemesls nav norādīts",
        "whitelistedittext": "Lūdzu $1, lai varētu labot lapas.",
        "confirmedittext": "Lai varētu izmainīt lapas, vispirms jāapstiprina savu e-pasta adresi.\nNorādi un apstiprini e-pasta adresi savos [[Special:Preferences|lietotāja uzstādījumos]].",
        "trackingcategories-disabled": "Kategorija ir atslēgta",
        "mailnologin": "Nav adreses, uz kuru sūtīt",
        "mailnologintext": "Tev jābūt [[Special:UserLogin|iegājušam]], kā arī tev jābūt [[Special:Preferences|norādītai]] derīgai e-pasta adresei, lai sūtītu e-pastu citiem lietotājiem.",
-       "emailuser": "Sūtīt e-pastu šim lietotājam",
+       "emailuser": "Sūtīt e-pastu šim dalībniekam",
        "emailuser-title-target": "Nosūtīt e-pastu {{GENDER:$1|šim dalībniekam|šai dalībniecei}}",
        "emailuser-title-notarget": "Sūtīt e-pastu lietotājam",
        "emailpagetext": "Ar šo veidni ir iespējams nosūtīt e-pastu šim {{GENDER:$1|lietotājam}}.\nTā e-pasta adrese, kuru tu esi norādījis [[Special:Preferences|savā izvēļu lapā]], parādīsies e-pasta \"From\" lauciņā, tādejādi saņēmējs varēs tev atbildēt.",
        "emailccme": "Atsūtīt man uz e-pastu mana ziņojuma kopiju.",
        "emailsent": "E-pasts nosūtīts",
        "emailsenttext": "Tavs e-pasts ir nosūtīts.",
-       "emailuserfooter": "Šis e-pasts ir lietotāja $1 sūtīts lietotājam $2, izmantojot \"Sūtīt e-pastu šim lietotājam\" funkciju {{SITENAME}}.",
+       "emailuserfooter": "Šis e-pasts ir dalībnieka $1 sūtīts dalībniekam $2, izmantojot \"Sūtīt e-pastu šim dalībniekam\" funkciju {{SITENAME}}.",
        "usermessage-summary": "Atstāt sistēmas ziņojumu.",
        "usermessage-editor": "Sistēmas ziņotājs",
        "watchlist": "Mani uzraugāmie raksti",
        "sp-contributions-blocked-notice": "Šis lietotājs pašlaik ir nobloķēts.\nPēdējais bloķēšanas reģistra ieraksts ir apskatāms zemāk:",
        "sp-contributions-blocked-notice-anon": "Šī IP adrese pašlaik ir nobloķēta.\nPēdējais bloķēšanas reģistra ieraksts ir apskatāms zemāk:",
        "sp-contributions-search": "Meklēt lietotāju veiktās izmaiņas",
-       "sp-contributions-username": "IP adrese vai lietotāja vārds:",
+       "sp-contributions-username": "IP adrese vai dalībnieka vārds:",
        "sp-contributions-toponly": "Rādīt tikai labojumus, kuri ir jaunākās versijas",
        "sp-contributions-submit": "Meklēt",
        "whatlinkshere": "Norādes uz šo rakstu",
        "emailblock": "e-pasts bloķēts",
        "blocklist-nousertalk": "nevar izmainīt savu diskusiju lapu",
        "ipblocklist-empty": "Bloķēšanas saraksts ir tukšs.",
-       "ipblocklist-no-results": "Norādītā IP adrese vai lietotājs nav bloķēts.",
+       "ipblocklist-no-results": "Norādītā IP adrese vai dalībnieks nav bloķēts.",
        "blocklink": "bloķēt",
        "unblocklink": "atbloķēt",
        "change-blocklink": "izmainīt bloku",
index 8f29932..0d7f4fb 100644 (file)
        "tog-editsectiononrightclick": "अनुभाग शीर्षक पर दाहिन क्लिक करै पर अनुभाग सम्पादित करी",
        "tog-watchcreations": "हमर बनाओल पृष्ठ हमर साकांक्ष सूचीमे राखी",
        "tog-watchdefault": "हमर सम्पादित पृष्ठ हमर साकांक्ष सूचीमे देखाबी",
-       "tog-watchmoves": "हमरादà¥\8dवारा à¤\98सà¥\8dà¤\95ाà¤\93ल पृष्ठ हमर साकांक्ष सूचीमे राखी",
-       "tog-watchdeletion": "हमरादà¥\8dवारा à¤®à¥\87à¤\9fाà¤\93ल पृष्ठ हमर साकांक्ष सूचीमे राखी",
-       "tog-watchrollback": "हमरादà¥\8dवारा à¤°à¥\8bलबà¥\8dयाà¤\95 कएल पृष्ठ हमर सांकक्ष सूचीमे राखी",
-       "tog-minordefault": "हमर सभ सम्पादन पूर्वन्यस्त रूपमे मामूली कही",
-       "tog-previewontop": "समà¥\8dपादन à¤ªà¥\87à¤\9fà¥\80à¤\95 à¤\8aपर à¤¦à¥\83शà¥\8dय देखाबी",
+       "tog-watchmoves": "हमरादà¥\8dवारा à¤¸à¥\8dथानानà¥\8dतरित पृष्ठ हमर साकांक्ष सूचीमे राखी",
+       "tog-watchdeletion": "हमरादà¥\8dवारा à¤®à¥\87à¤\9fाà¤\8fल पृष्ठ हमर साकांक्ष सूचीमे राखी",
+       "tog-watchrollback": "हमरादà¥\8dवारा à¤ªà¥\82रà¥\8dववत कएल पृष्ठ हमर सांकक्ष सूचीमे राखी",
+       "tog-minordefault": "हमर सभ सम्पादनसभ छोट परिवर्तनक रूपमे चिह्नित करी",
+       "tog-previewontop": "समà¥\8dपादन à¤¸à¤¨à¥\8dदà¥\82à¤\95 à¤¸à¤\81 à¤ªà¤¹à¤¿à¤¨à¥\87 à¤\9dलà¤\95 देखाबी",
        "tog-previewonfirst": "पहिल सम्पादनक बाद पूर्वावलोकन देखाबी",
        "tog-enotifwatchlistpages": "जौं हमर ध्यानसूचीक कोनो पन्नामे परिवर्तन हुअए तँ हमरा इमेल पठाबी",
        "tog-enotifusertalkpages": "हमर वार्ता पृष्ठ परिवर्तित भेला पर हमरा इमेल करी",
        "tog-watchlisthideminor": "हमर साकांक्ष सूचीसँ मामूली सम्पादन नुकाबी",
        "tog-watchlisthideliu": "साकांक्षसूचीसँ सम्प्रवेशित प्रयोक्ताक सम्पादन हटाबी",
        "tog-watchlisthideanons": "साकांक्षसूचीसँ अनाम प्रयोक्ताक सम्पादन हटाबी",
-       "tog-watchlisthidepatrolled": "साकांक्ष सूचीसँ संचालित सम्पादन नुकाबी",
+       "tog-watchlisthidepatrolled": "साकांक्ष सूचीसँ परीक्षित सम्पादन नुकाबी",
+       "tog-watchlisthidecategorization": "पृष्ठसभक श्रेणीकरण नुकाबी",
        "tog-ccmeonemails": "हमरद्वारा दोसर प्रयोक्ताक पठाओल ई-पत्रक कपी पठाबी",
        "tog-diffonly": "फाइल-अन्तर प्रणालीक नीचाँ पन्नाक सामिग्री नै देखाबी",
        "tog-showhiddencats": "नुकाएल श्रेणी देखाबी",
-       "tog-norollbackdiff": "समà¥\8dपादन à¤µà¤¾à¤ªà¤¸ à¤² à¤²à¥\87ला बाद अन्तर नै देखाबी",
-       "tog-useeditwarning": "à¤\9cब à¤¹à¤® à¤\95à¥\8bनà¥\8b à¤¸à¤®à¥\8dपादन à¤ªà¥\83षà¥\8dठà¤\95à¥\87 à¤¬à¤¿à¤¨à¤¾ à¤¸à¥\81रà¤\95à¥\8dषित à¤\95à¥\87नà¥\88 à¤¬à¤¦à¤²à¤¾à¤µ à¤¸à¤\82à¤\97 à¤\9bà¥\8bडि à¤¦à¤¿ à¤¤ à¤¹à¤®à¤°à¤¾ à¤¸à¥\82à¤\9aित à¤\95रà¥\80 ।",
-       "tog-prefershttps": "समà¥\8dपà¥\8dरवà¥\87शित à¤\95रलाà¤\95 à¤¬à¤¾à¤¦ à¤¸à¤¦à¥\88व à¤¸à¥\81रà¤\95à¥\8dषित à¤\95नà¥\87à¤\95à¥\8dशनà¤\95à¥\87 प्रयोग करी",
+       "tog-norollbackdiff": "समà¥\8dपादन à¤µà¤¾à¤ªà¤¸ à¤\95रलाà¤\95 बाद अन्तर नै देखाबी",
+       "tog-useeditwarning": "à¤\9cब à¤¹à¤® à¤\95à¥\8bनà¥\8b à¤¸à¤®à¥\8dपादन à¤ªà¥\83षà¥\8dठà¤\95à¥\87 à¤¬à¤¿à¤¨à¤¾ à¤¸à¥\81रà¤\95à¥\8dषित à¤\95à¥\87नà¥\88 à¤¬à¤¦à¤²à¤¾à¤µ à¤¸à¤\82à¤\97 à¤\9bà¥\8bडि à¤¦à¥\80 à¤¤à¤\81 à¤¹à¤®à¤°à¤¾ à¤¸à¥\82à¤\9aित à¤\95रà¥\80।",
+       "tog-prefershttps": "समà¥\8dपà¥\8dरवà¥\87शित à¤\95रलाà¤\95 à¤¬à¤¾à¤¦ à¤¸à¤¦à¥\88व à¤¸à¥\81रà¤\95à¥\8dषित à¤\95नà¥\87à¤\95à¥\8dसनà¤\95 प्रयोग करी",
        "underline-always": "सदिखन",
        "underline-never": "कखनो नै",
        "underline-default": "पूर्वन्यस्त गवेषक",
        "period-am": "पूर्वाह्न",
        "period-pm": "अपराह्न",
        "pagecategories": "{{PLURAL:$1|श्रेणी|श्रेणीसभ}}",
-       "category_header": "श्रेणी \"$1\" मे पन्ना सभ",
+       "category_header": "\"$1\" श्रेणीमे पृष्ठसभ",
        "subcategories": "उपश्रेणी",
        "category-media-header": "श्रेणी \"$1\" मे मिडिया",
        "category-empty": "<em>ई श्रेणीमे ई समय कोनो पृष्ठ या मिडिया नै अछि।</em>",
        "category-file-count": "{{PLURAL:$2|ई श्रेणीमे मात्र निम्नलिखित फाइल अछि।|ई श्रेणीमे निम्नलिखित {{PLURAL:$1|फाइल|$1 फाइलसभ}} अछि, कुल फाइलसभ $2}}",
        "category-file-count-limited": "ई श्रेणीमे निम्नलिखित {{PLURAL:$1|फाइल अछि।|फाइलसभ अछि।}}",
        "listingcontinuesabbrev": "शेष आगाँ।",
-       "index-category": "à¤\95à¥\8dरम à¤\95à¤\8fल à¤ªà¤¨à¥\8dनासभ",
-       "noindex-category": "à¤\95à¥\8dरम à¤¨à¥\88 à¤\95à¤\8fल à¤ªà¤¨à¥\8dनासभ",
-       "broken-file-category": "पनà¥\8dनासभ à¤\9cाà¤\87मे फाइल लिङ्कसभ टूटल हुअए",
+       "index-category": "सà¥\82à¤\9aà¥\80बदà¥\8dध à¤ªà¥\83षà¥\8dठ",
+       "noindex-category": "à¤\95à¥\8dरम à¤¨à¥\88 à¤\95à¥\87ल à¤ªà¥\83षà¥\8dठ",
+       "broken-file-category": "पनà¥\8dनासभ à¤\9cाहिमे फाइल लिङ्कसभ टूटल हुअए",
        "about": "क विषयमे",
        "article": "सामग्री लेख",
        "newwindow": "(नव विन्डोमे खुजत)",
        "cancel": "रद्द करी",
        "moredotdotdot": "आर...",
-       "morenotlisted": "à¤\88 à¤ªà¥\81रा सूची नै छी।",
+       "morenotlisted": "à¤\88 à¤ªà¥\82रà¥\8dण सूची नै छी।",
        "mypage": "पन्ना",
        "mytalk": "वार्ता",
        "anontalk": "वार्ता",
        "navigation": "सञ्चार",
        "and": "&#32;आर",
        "qbfind": "ताकी",
-       "qbbrowse": "à¤\97वà¥\87षण करी",
+       "qbbrowse": "बà¥\8dराà¤\89à¤\9c करी",
        "qbedit": "सम्पादन करी",
        "qbpageoptions": "ई पृष्ठ",
        "qbmyoptions": "हमर पृष्ठसभ",
        "faq": "त्वरित प्रश्नोत्तरी",
        "faqpage": "Project: त्वरित प्रश्नोत्तरी",
        "actions": "क्रियासभ",
-       "namespaces": "à¤\9aà¥\87नà¥\8dहासà¥\80 समूहसभ",
-       "variants": "पà¥\8dरà¤\95ारसभ",
+       "namespaces": "नामसà¥\8dथान समूहसभ",
+       "variants": "सà¤\82सà¥\8dà¤\95रण",
        "navigation-heading": "दिक्चालन सूची",
        "errorpagetitle": "त्रुटि",
        "returnto": "$1 पर आबी।",
        "searcharticle": "जाए",
        "history": "पृष्ठ इतिहास",
        "history_short": "इतिहास",
-       "updatedmarker": "हमर à¤\85नà¥\8dतिम à¤\86à¤\97मनसà¤\81 à¤ªà¤¹à¤¿à¤¨à¥\87 à¤\85दà¥\8dयतन à¤\95à¤\8fल",
+       "updatedmarker": "हमर à¤\85नà¥\8dतिम à¤\86à¤\97मनसà¤\81 à¤ªà¤¹à¤¿à¤¨à¥\87 à¤\85दà¥\8dयतन à¤\95à¥\87ल",
        "printableversion": "प्रिन्ट करबा योग्य",
        "permalink": "स्थायी लिङ्क",
        "print": "छापी",
        "talk": "वार्तालाप",
        "views": "दर्शाव",
        "toolbox": "उपकरण",
+       "tool-link-userrights": "{{GENDER:$1|सदस्य}} समूह परिवर्तन करी",
+       "tool-link-emailuser": "ई {{GENDER:$1|प्रयोक्ता}}के इमेल भेजी",
        "userpage": "प्रयोक्ता पन्ना देखी",
        "projectpage": "परियोजना पन्ना देखी",
        "imagepage": "फाइल पृष्ठ देखी",
        "redirectedfrom": "($1सँ पुनर्निर्देशित)",
        "redirectpagesub": "पृष्ठ पुनर्निर्देशित करी",
        "redirectto": "कऽ अनुप्रेषित:",
-       "lastmodifiedat": "à¤\88 à¤ªà¥\83षà¥\8dठà¤\95 à¤ªà¤¹à¤¿à¤¨à¥\81à¤\95ा à¤¬à¤¦à¤²à¤¾à¤µ $1 के $2 बजे भेल छल।",
+       "lastmodifiedat": "à¤\88 à¤ªà¥\83षà¥\8dठà¤\95 à¤¨à¤µà¥\80नतम à¤ªà¤°à¤¿à¤µà¤°à¥\8dतन $1 के $2 बजे भेल छल।",
        "viewcount": "ई पृष्ठ {{PLURAL:$1|एक|$1}} बेर देखल गेल छल।",
        "protectedpage": "सुरक्षित पृष्ठ",
        "jumpto": "एतय जाए:",
        "privacy": "गोपनीयताक नियम",
        "privacypage": "Project:गोपनीयता नियम",
        "badaccess": "आज्ञा गल्ती",
-       "badaccess-group0": "à¤\85हाà¤\81à¤\95 à¤\86à¤\97à¥\8dरह à¤\95à¤\8fल क्रियाक करबाक अनुमति नै अछि।",
-       "badaccess-groups": "à¤\85हाà¤\81 à¤\9cà¥\87 à¤\95à¥\8dरिया à¤\86à¤\9cमà¥\87नà¥\87 à¤\9bà¥\80 à¤\93 à¤®à¤¾à¤¤à¥\8dर {{PLURAL:$2|$1 à¤¸à¤®à¥\82ह|$1 à¤¸à¤®à¥\82हसभ}}à¤\95 à¤¸à¤¦à¤¸à¥\8dय à¤¹à¥\80 à¤\95रि à¤¸à¤\95à¤\8fत अछि।",
+       "badaccess-group0": "à¤\85हाà¤\81à¤\95 à¤\86à¤\97à¥\8dरह à¤\95à¥\87ल क्रियाक करबाक अनुमति नै अछि।",
+       "badaccess-groups": "à¤\85हाà¤\81 à¤\9cà¥\87 à¤\95à¥\8dरिया à¤\86à¤\9cमà¥\87नà¥\87 à¤\9bà¥\80 à¤\93 à¤®à¤¾à¤¤à¥\8dर {{PLURAL:$2|$1 à¤¸à¤®à¥\82ह|$1 à¤¸à¤®à¥\82हसभ}}à¤\95 à¤¸à¤¦à¤¸à¥\8dय à¤®à¤¾à¤¤à¥\8dर à¤\95रि à¤¸à¤\95à¥\88त अछि।",
        "versionrequired": "मिडियाविकिक संस्करण $1 चाही",
        "versionrequiredtext": "ई पृष्ठ प्रयोग करैक लेल मिडियाविकिक $1 अवतरण जरुरी अछि।\nदेखी [[Special:Version|अवतरण पृष्ठ]]।",
        "ok": "ठीक अछि",
        "databaseerror-query": "अनुरोध: $1",
        "databaseerror-function": "फङ्क्सन: $1",
        "databaseerror-error": "त्रुटि: $1",
-       "laggedslavemode": "'''चेतौनी:''' पन्नापर सम्भव जे अद्यतन परिवर्तन नै हुअए।",
-       "readonly": "दतà¥\8dतनिधि प्रतिबन्धित",
-       "enterlockreason": "पà¥\8dरतिबनà¥\8dध à¤²à¥\87ल à¤\95ारण à¤¬à¤¤à¤¾à¤¬à¥\80, à¤¸à¤\82à¤\97à¥\87 à¤\8fà¤\95à¤\9fा à¤\85नà¥\8dदाà¤\9c à¤¸à¥\87हà¥\8b à¤¬à¤¤à¤¾à¤¬à¥\80 à¤\9cà¥\87 à¤\95à¤\96न à¤\88 à¤ªà¥\8dरतिबनà¥\8dध à¤¹à¤\9fाà¤\8fल à¤\9cाà¤\8fत।",
+       "laggedslavemode": "<strong>चेतौनी:</strong> पन्नापर सम्भव जे अद्यतन परिवर्तन नै हुअए।",
+       "readonly": "डà¥\87à¤\9fाबà¥\87स प्रतिबन्धित",
+       "enterlockreason": "पà¥\8dरतिबनà¥\8dध à¤²à¥\87ल à¤\95ारण à¤¬à¤¤à¤¾à¤¬à¥\80, à¤¸à¤\82à¤\97à¥\87 à¤\8fà¤\95à¤\9fा à¤\85नà¥\8dदाà¤\9c à¤¸à¥\87हà¥\8b à¤¬à¤¤à¤¾à¤¬à¥\80 à¤\9cà¥\87 à¤\95à¤\96न à¤\88 à¤ªà¥\8dरतिबनà¥\8dध à¤¹à¤\9fाà¤\8fल à¤\9cाà¤\87त।",
        "readonlytext": "अखन दत्तांशनिधि नव प्रविष्टि आ आन संशोधन लेल प्रतिबन्धित अछि, सम्भवतः सामान्त दत्तांशनिधि देखभाल लेल, तकर बाद ई सामान्य भऽ जाएत।\n\nसञ्चालक जे एकरा प्रतिबन्धित कएने छथि ई कारण दै छथि:$1",
        "missing-article": "दत्तनिधि पृष्ठक वान्छित पाठ्य नै ताकि सकल, माने \"$1\" $2\nएकर कारण कोनो पुरान फाइल चेन्हासी वा ऐतिहासिक लिङ्कक पाछाँ जाएब अछि, जे मेटा देल गेल छै।\nजौं ई तकर कारण नै अछि, तखन अहाँ तन्त्रांशमे कोनो दोष भेटल अछि।\nएकर खबरि पहुँचाबी [[Special:ListUsers/sysop|प्रबन्धक]]केँ, अपन सार्वत्रिक विभव सङ्केत सूचित करैत।",
        "missingarticle-rev": "(संशोधन#: $1)",
        "virus-badscanner": "खराप विन्यास: अज्ञात विषविधि बिम्बक: <em>$1</em>",
        "virus-scanfailed": "बिम्ब विफल (विध्यादेश $1)",
        "virus-unknownscanner": "अज्ञात विषविधि निरोधक",
-       "logouttext": "'''अहाँ निष्क्रमण कऽ गेल छी।'''\n\nअहाँ {{अन्तर्जाल}} प्रयोग अनाम भऽ कऽ सकै छी, वा अहाँ <span class='plainlinks'>[$1 log in again]</span> वएह आकि कोनो आन प्रयोक्ताक रूपमे सेहू प्रयोक कऽ सकै छी।\nई मोन राखू जे किछु पन्ना एना देखा पड़ि सकैए जेना अहाँ अखनो सम्प्रवेशित होइ, जावत अहाँ अपन गवेषकक उपस्मृति मेटा नै दै छी।",
+       "logouttext": "<strong>आब अहाँ निष्क्रमण कऽ गेल छी।</strong>\n\nध्यान दी कि जाबे धरि अहाँ अपन ब्राउजर क्यास खाली नै करब, किछ पृष्ठपर अखनो अहाँ सम्प्रवेशित देखाएब।",
        "cannotlogoutnow-title": "अखन प्रस्थान नै भऽ रहल अछि",
        "cannotlogoutnow-text": "$1 क उपयोग समय प्रस्थान नै कएल जा सकएत अछि।",
        "welcomeuser": "अहाँक स्वागत अछि, $1!",
        "createacct-yourpasswordagain-ph": "कुटशब्द पुनः लिखी",
        "userlogin-remembermypassword": "हमरा सम्प्रवेशित राखी",
        "userlogin-signwithsecure": "सुरक्षित कनेक्शनक प्रयोग करी",
+       "cannotlogin-title": "अखन प्रवेश नै भऽ रहल अछि",
+       "cannotlogin-text": "प्रवेश असम्भव अछि",
        "cannotloginnow-title": "अखन प्रवेश नै भऽ रहल अछि",
        "cannotloginnow-text": "$1 क उपयोग समय प्रवेश नै कएल जा सकएत अछि।",
+       "cannotcreateaccount-title": "खाता नै बनि सकत",
+       "cannotcreateaccount-text": "प्रत्यक्ष खाता निर्माण एहि विकिपर सक्षम नै अछि।",
        "yourdomainname": "अहाँक डोमेन (प्रभावक्षेत्र):",
        "password-change-forbidden": "अहाँ ई विकिमे कुटशब्द नै बदल सकैत छी।",
        "externaldberror": "या त प्रमाणिकरण डेटाबेसमे त्रुटि भएल अछि या फेर अहाँक अपन बाह्य खाता अपडेट करैक अनुमति नै अछि।",
        "login": "सम्प्रवेश",
+       "login-security": "अपन पहचान सत्यापित करी",
        "nav-login-createaccount": "सम्प्रवेश / खाता खोली",
        "userlogin": "सम्प्रवेश/ खाता बनाबी",
        "userloginnocreate": "सम्प्रवेश",
        "createacct-email-ph": "अपन ई-मेल पता लिखी",
        "createacct-another-email-ph": "ईमेल पता प्रदान करी",
        "createaccountmail": "एक अस्थायी यादृच्छिक कूटशब्द चुनी आ ओ निर्दिष्ट ई-मेल पता पर भेजी",
+       "createaccountmail-help": "एकर उपयोग बिना पासवर्ड जानने कियो आन व्यक्तिके खाता खोलैक लिए उपयोग कएल जा सकैत अछि ।",
        "createacct-realname": "असली नाम (वैकल्पिक)",
        "createaccountreason": "कारण:",
        "createacct-reason": "कारण:",
-       "createacct-reason-ph": "अहा इगो आर दोसर खाता कियाक बनउने जा रहल छि",
+       "createacct-reason-ph": "अहाँ एक अन्य खाता कियाक बनाए रहल छी",
+       "createacct-reason-help": "खाता निर्माण लगमे ई सन्देस देखाएल जाइत।",
        "createacct-submit": "अपन खाता बनाबी",
        "createacct-another-submit": "खाता बनाबी",
-       "createacct-benefit-heading": "{{SITENAME}} अहाँ जोका लोगसभद्वारा बनाएल गेल अछि।",
+       "createacct-continue-submit": "खाता निर्माण जारी राखी",
+       "createacct-another-continue-submit": "खाता निर्माण जारी राखी",
+       "createacct-benefit-heading": "{{SITENAME}} अहाँ जका लोकसभद्वारा बनाएल गेल अछि।",
        "createacct-benefit-body1": "$1 {{PLURAL:$1|सम्पादन|सम्पादनसभ}}",
        "createacct-benefit-body2": "{{PLURAL:$1|पन्ना|पन्नासभ}}",
        "createacct-benefit-body3": "सन्निकट {{PLURAL:$1|योगदानकर्ता|योगदानकर्तासभ}}",
        "nocookieslogin": "{{SITENAME}} प्रयोक्ताक सम्प्रवेशित करबा लेल ज्ञापकक प्रयोग करैत अछि।\nअहाँ ज्ञापकक अशक्त केने छी।\nकृपा कऽ ओकरा सक्रिय करी आ फेरसँ प्रयास करी।",
        "nocookiesfornew": "प्रयोक्ता खाजा नै खुजल, कारण हम ओकर जडि पूर्ण रूपेँ नै ताकि सकलौ।\nई दृढ करी जे ज्ञापक सक्रिय अछि, ई पन्नाक फेरसँ भारित करी आ फेरसँ प्रयास करी।",
        "noname": "अहाँ वैध प्रयोक्तानाम नै देने छी।",
-       "loginsuccesstitle": "समà¥\8dपà¥\8dरवà¥\87श à¤­à¤\8fल",
+       "loginsuccesstitle": "समà¥\8dपà¥\8dरवà¥\87श à¤­à¥\87ल",
        "loginsuccess": "<strong>अहाँ सम्प्रवेश केलहुँ {{SITENAME}} \"$1\"'''क रूपमे। </strong>",
        "nosuchuser": "\"$1\" नामसँ कोनो प्रयोक्ता नै अछि।\nप्रयोक्तानाम ब्रह्मक्षर-लघ्वक्षर भेद युक्त अछि।\nअपन ह्रिजै जाँची, वा [[Special:CreateAccount|नव खाता बनाबी]] ।",
        "nosuchusershort": "\"$1\" नामक कोनो प्रयोक्ता नै अछि।\nअपन हिजए सुधारी।",
        "eauthentsent": "एकटा पावती ई-पत्र निर्धारित ई-पत्र संकेतपर पठा देल गेल अछि।\nऐ खातापर कोनो दोसर ई-पत्र पठाएल जएबासँ पहिने, अहाँकेँ ऐ ई-पत्रक निर्देशक पालन करए पड़त, जइसँ ई पुष्ट भऽ सकए जे ई खाता वास्तवमे अहींक अछि।",
        "throttled-mailpassword": "एकटा कूटशब्द स्मारक पहिनहिये पठाएल गेल अछि, {{PLURAL:$1|घण्टा|$1 घण्टा}}क भीतर।\nदुरुपयोग रोकबा लेल, मात्र एकटा कूटशब्द {{PLURAL:$1|घण्टा|$1 घण्टा}}मे पठाएल जाएत।",
        "mailerror": "ई-पत्र पठेबामे त्रुटी: $1",
-       "acct_creation_throttle_hit": "अहाँके आइ॰पि. पतासँ आएल आगंतुक चौबीस घण्टा सँ बैसी ई विकिमे {{PLURAL:$1|एक खाता|$1 खाता}} बनौलक अछि, इ समयावधिमे ई अधिकतम सिमा छी। अतः अखन ई आइ॰पि. पताके प्रयोग करए वाला आगंतुक आर कोनो खाता नै खोइल सकएत अछि ।",
+       "acct_creation_throttle_hit": "अहाँक आइपी ठेगान सँ आएल आगन्तुक $2 सँ बैसी ई विकिमे {{PLURAL:$1|एक खाता|$1 खाता}} बनौलक अछि, इ समयावधिमे ई अधिकतम सिमा छी। अतः अखन ई आइपी पताके प्रयोग करैवाला आगन्तुक आर कोनो खाता नै खोइल सकैत अछि।",
        "emailauthenticated": "अहाँक ई-पत्र सङ्केत $2 क $3 बजे सत्यापित भेल।",
        "emailnotauthenticated": "अहाँक ई-पत्र सङ्केत अखन धरि सत्यापित नै भेल अछि।\nनिचा देल गेल कोनो सुविधाक लेल अहाँक ई-पत्र नै भेजल जाएत।",
        "noemailprefs": "ई सुविधा सभ कऽ प्रयोग करएक लेल अपन विकल्पमे ई-पत्र पता राखी।",
        "cannotchangeemail": "खाता ई-पत्र सङ्केत ऐ विकिपर बदलल नै जा सकैए।",
        "emaildisabled": "ई अन्तर्जाल ई-पत्र नै पठाएत।",
        "accountcreated": "खाता खुजि गेल",
-       "accountcreatedtext": "[[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|वारà¥\8dता]]) à¤\95à¥\87 à¤²à¥\87ल à¤\96ाता à¤\96à¥\8bलल à¤\97ेल अछि।",
+       "accountcreatedtext": "[[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|वारà¥\8dता]]) à¤\95à¥\87 à¤²à¥\87ल à¤\96ाता à¤¨à¤¿à¤°à¥\8dमाण à¤­ेल अछि।",
        "createaccount-title": "{{SITENAME}}क लेल खाता बनाबी",
        "createaccount-text": "कियो अहाँक ई-पत्र सङ्केत लेल एकटा खाता {{SITENAME}} पर खोललन्हि ($4) नाम भेल \"$2\", कूटशब्द भेल \"$3\"।\nअहाँ सम्प्रवेश करी आ अपन कूटशब्द बदली।\n\nअहाँ ई सन्देशके बिसरि सकै छी, जँ ई खाता भ्रमवश बनल हुअए।",
        "login-throttled": "अहाँ ढ़ेर रास सम्प्रवेश प्रयास केलहुँ।\nफेर प्रयास करबासँ पहिने कने काल थम्हू।",
-       "login-abort-generic": "à¤\85हाà¤\81à¤\95 à¤¸à¤®à¥\8dपà¥\8dरवà¥\87श à¤¸à¤«à¤² à¤¨à¥\88 à¤­à¥\87ल- à¤°à¥\8bà¤\95ल à¤\97à¤\8fल",
-       "login-migrated-generic": "à¤\85हाà¤\81à¤\95à¥\87 à¤\96ाता à¤®à¤¾à¤\87à¤\97à¥\8dरà¥\87à¤\9f à¤\95à¤\8fल गेल अछि, आर अहाँके प्रयोक्ता नाम आब ई विकिमे नै अछि।",
-       "loginlanguagelabel": "भाषा : $1",
-       "suspicious-userlogout": "à¤\85हाà¤\81à¤\95 à¤¨à¤¿à¤·à¥\8dà¤\95à¥\8dरमणà¤\95 à¤\85नà¥\81रà¥\8bध à¤¨à¥\88 à¤®à¤¾à¤¨à¤² à¤\97à¥\87ल à¤\95ारण à¤\88 à¤²à¤¾à¤\97ल à¤\9cà¥\87 à¤\88 à¤ªà¥\81रान à¤\97वà¥\87षà¤\95à¤\95 à¤²à¤¾à¤\97ि à¤µà¤¾ à¤¦à¥\8bसराà¤\87त à¤\89पसà¥\8dमà¥\83तद्वारा पठाओल गेल छल।",
+       "login-abort-generic": "à¤\85हाà¤\81à¤\95 à¤¸à¤®à¥\8dपà¥\8dरवà¥\87श à¤¸à¤«à¤² à¤¨à¥\88 à¤­à¥\87ल- à¤°à¥\8bà¤\95ल à¤\97à¥\87ल",
+       "login-migrated-generic": "à¤\85हाà¤\81à¤\95à¥\87 à¤\96ाता à¤®à¤¾à¤\87à¤\97à¥\8dरà¥\87à¤\9f à¤\95à¥\87ल गेल अछि, आर अहाँके प्रयोक्ता नाम आब ई विकिमे नै अछि।",
+       "loginlanguagelabel": "भाषा: $1",
+       "suspicious-userlogout": "à¤\85हाà¤\81à¤\95 à¤¨à¤¿à¤·à¥\8dà¤\95à¥\8dरमणà¤\95 à¤\85नà¥\81रà¥\8bध à¤¨à¥\88 à¤®à¤¾à¤¨à¤² à¤\97à¥\87ल à¤\95ारण à¤\88 à¤²à¤¾à¤\97ल à¤\9cà¥\87 à¤\88 à¤ªà¥\81रान à¤¬à¥\8dराà¤\89à¤\9cर à¤¤à¥\81à¤\9fल à¤µà¤¾ à¤\95à¥\8dयाà¤\9aिà¤\99 à¤ªà¥\8dरà¤\95à¥\8dसà¥\80द्वारा पठाओल गेल छल।",
        "createacct-another-realname-tip": "मूल नाम वैकल्पिक अछि।\nजँ अहाँ एकरा देबा लेल प्रयोग करै छी, ई अहाँक काजक श्रेय देबा लेल एकर प्रयोग कएल जाएत।",
        "pt-login": "सम्प्रवेश",
        "pt-login-button": "सम्प्रवेश",
+       "pt-login-continue-button": "प्रवेश जारी राखी",
        "pt-createaccount": "खाता खोलल जाए",
        "pt-userlogout": "निष्क्रमण",
        "php-mail-error-unknown": "पी.एच.पी.कऽ समाद कार्य() मे अज्ञात दोष भेल।",
        "passwordreset-emailtext-user": "प्रयोक्ता $1 {{अन्तर्जाल}} पर अहाँक खाता विवरणक {{SITENAME}} लेल फेरसँ ($4) आग्रह केने छथि। ई प्रयोक्ता {{PLURAL:$3|खाता अछि|खाता सभ अछि}} ऐ ई-पत्र संकेतसँ जुड़ल: $2\n{{PLURAL:$3| ई अस्थायी कूटशब्द|ई सभ अस्थायी कूटशब्द}} खतम भऽ जाएत {{PLURAL:$5|एक दिन|$5 दिन}} मे।\nअहाँ सम्प्रवेश करू आ एकटा नव कूटशब्द आब चुनू। जँ कियो दोसर ई आग्रह केने छथि, वा जँ अहाँकेँ अपन मूल कूटशब्द मोन पड़ि गेल अछि, आ अहाँ आब ओइ कूटशब्दकेँ नै बदलऽ चाहै छी, अहाँ ऐ संदेशकेँ बिसरि सकै छी आ अपन पुरान कूटशब्दक प्रयोग जारी राखि सकै छी।",
        "passwordreset-emailelement": "प्रयोक्ता: \n$1\n\nअस्थायी कूटशब्द: \n$2",
        "passwordreset-emailsentemail": "एकटा ई-पत्र मोन पाड़बा लेल पठाओल गेल अछि।",
+       "passwordreset-invalideamil": "अवैध इमेल ठेगान",
+       "passwordreset-nodata": "प्रयोगकर्ता नाम वा इमेल ठेगान नै देल गेल छल",
        "changeemail": "ई-मेल पता परिवर्तित करी",
        "changeemail-header": "अपन ईमेल पता परिवर्तन हेतु एकरा पुरा करी। यदि अहाँ अपन वर्तमान ईमेल पता हटाबैलेल चाहैत छी, तँ एकरा खाली छोडि दी आ एकरा भेजी।",
        "changeemail-no-info": "अहाँक ई पन्नाक सोझे प्रयोग करबालेल सम्प्रवेशित हुअए पडत।",
        "changeemail-oldemail": "वर्तमान ई-मेल पता:",
        "changeemail-newemail": "नव ई-मेल पता:",
+       "changeemail-newemail-help": "यदि अहाँ अपन इमेल ठेगान रिक्त राखैलेल चाहए छी तँ अहाँ ई स्थान खाली छोडि सकैत छी। मुदा अहाँ अपन पासवर्ड बिसरि गेलापर ओकरा इमेलद्वारा प्राप्त नै करि पेबै।",
        "changeemail-none": "(कोनो नै)",
        "changeemail-password": "अहाँक {{SITENAME}} कूटशब्द:",
        "changeemail-submit": "ई-मेल बदली",
        "changeemail-throttled": "अहाँ ढेर रास सम्प्रवेश प्रयास केलहुँ।\nफेर प्रयास करबासँ पहिने कने $1 काल थम्हू।",
+       "changeemail-nochange": "कृपया कोनो नव इमेल पता प्रविष्ट करी।",
        "resettokens": "टोकन रीसेट करी",
        "resettokens-text": "जे स्तोक अहाँके खाता सँ सम्बद्ध किछु विशिष्ट व्यक्तिगत जानकारी प्रदान करएत अछि, अहाँ वोकरा एतए सँ रिसेट कऽ सकएत छी।\n\nयदि अहाँ एकरा गलती सँ केकरो देखा देनए छी वा अहाँ के खाता ह्याक भ गेल अछि तहन अहाँके एकरा रिसेट कऽ देना चाही।",
        "resettokens-no-tokens": "रीसेट करवाक लेल कोनो टोकन नै अछि।",
        "minoredit": "अल्प सम्पादन",
        "watchthis": "ई पृष्ठके ध्यानसूचीमे राखी",
        "savearticle": "पन्नाक रक्षण करी",
+       "savechanges": "रक्षण करी",
+       "publishpage": "पृष्ठ प्रकाशित करी",
+       "publishchanges": "परिवर्तन प्रकाशित करी",
        "preview": "पूर्वावलोकन",
        "showpreview": "पूर्वप्रदर्शन",
        "showdiff": "परिवर्तन देखाबी",
        "missingsummary": "<strong>स्मारक:</strong> अहाँ सम्पादन सार नै देने छी।\nजँ अहाँ फेरसँ क्लिक करब \"{{int:savearticle}}\", अहाँक सम्पादन बिना एकर संरक्षित भऽ जाएत।",
        "selfredirect": "<strong>चेतावनी:</strong> आहाँ स्वेम के ई पन्ना पुनः निर्देशीत कएर रहल छी।\nआहाँ अनुप्रेषित के लेल गलत लक्ष्य निर्दिष्ट भ्या सकएत अछि, या आहाँ गलत पन्ना कें संपादन कैर सकएत छी।\nआहाँ फेरो से \"{{int:savearticle}}\" क्लिक करएत छी, रीडायरेक्ट ओनाहो भी बनाबल जेल अछि।",
        "missingcommenttext": "कृपा कऽ अपन विचार नीचाँ प्रविष्ट करी।",
-       "missingcommentheader": "'''स्मरण:''' अहाँ कोनो विषय/ शीर्षक ऐ टिप्पणीक लेल नै देने छी।\nजँ अहाँ फेरसँ क्लिक करब \"{{int:savearticle}}\" , अहाँक सम्पादन बिना एकर संरक्षित भऽ जाएत।",
+       "missingcommentheader": "<strong>अनुस्मारक:</strong> अहाँ ई टिप्पणीके कोनो शीर्षक नै देनए छी।\nयदि अहाँ \"{{int:savearticle}}\" पर पुन: क्लिक करैत छी तँ अहाँक परिवर्तन बिना शीर्षक रक्षण कएल जाइत।",
        "summary-preview": "सारांश पूर्वावलोकन",
        "subject-preview": "विषयक झलक:",
        "previewerrortext": "अहाँक परिवर्तनके पूर्वावलोकन करहिक समय एक त्रुटि आएल।",
        "userpage-userdoesnotexist": "प्रयोक्ता खाता \"$1\" पञ्जीकृत नै अछि।\nनिश्चय करी जे की अहाँ ई पन्ना बनेबाक/ सम्पादित करबाक इच्छुक छी।",
        "userpage-userdoesnotexist-view": "प्रयोक्ता खाता \"$1\" पञ्जीकृत नै अछि।",
        "blocked-notice-logextract": "ई प्रयोक्ता अखन प्रतिबन्धित अछि।\nअद्यतन प्रतिबन्धित  वृत्तलेख लेखा सन्दर्भ लेल नीचाँ देल अछि:",
-       "clearyourcache": "'''टिप्पणी:''' संरक्षणक बाद, अहाँकेँ परिवर्तन देखबा लेल अपन गवेषकक उपस्मृतिकेँ हटबए पड़त।\n''' मोजिल्ला/ फायरफॉक्स/ सफारी:''' दाबि कऽ राखू ''शिफ्ट'' केँ ''पुनर्भारित'' क्लिक करबाक समए, वा दाबू चाहे ''Ctrl-F5'' वा ''Ctrl-R'' (''Command-R'' मैकिनटोशपर);\n'''कन्करर: ''' क्लिक करू ''पुनर्भारित करू'' वा दाबू''F5'';\n'''ओपेरा:''' उपस्मृति खतम करू ''Tools → Preferences'';\n'''इन्टरनेट एक्सप्लोरर:''' दाबि कऽ राखू ''Ctrl'' क्लिक करबा काल ''नवीकरण,'' वा दाबू ''Ctrl-F5'' ।",
+       "clearyourcache": "<strong>टिप्पणी:</strong> संरक्षणक बाद, अहाँक परिवर्तन देखबा लेल अपन ब्राउजरक उपस्मृतिक हटबए पडत।\n<strong>फायरफक्स/ सफारी:<strong> <em>सिफ्ट</em>के दाबि <em>रिलोड</em>, वा <em>Ctrl-F5</em> वा <em>Ctrl-R</em> (म्याकपर <em>⌘-R</em>)\n<strong>गुगल क्रोम:</strong> <em>Ctrl-Shift-R</em> दाबी(म्याकपर <em>⌘-Shift-R</em>)\n<strong>इन्टरनेट एक्सप्लोरर:</strong> <em>Refresh</em> क्लिक करि <em>Ctrl</em> दाबि, वा <em>Ctrl-F5</em> दाबी\n<strong>ओपेरा:</strong> <em>Menu → Settings</em> पर जाए (म्याकपर <em>Opera → Preferences</em>) आ ओकर बाद <em>Privacy & security → Clear browsing data → Cached images and files</em>\n ।",
        "usercssyoucanpreview": "<strong>सङ्केत:</strong> सङ्ग्रह करैसँ पहिने अहाँ अपन नव सियसयसक जाँच लेल \"{{int:पूर्वदृश्य देखाउ}}\" बटनक प्रयोग करी।",
        "userjsyoucanpreview": "<strong>टिप</strong>  प्रयोग करी \"{{int:showpreview}}\" बटन अपन नव जावास्क्रिप्ट संरक्षण जँचबाक लेल।",
        "usercsspreview": "''' मोन राखू जे अहाँ मात्र अपन प्रयोक्ता  सी.एस.एस. क पूर्वदृश्य देख रहल छी।'''\n''' ई अखन धरि संरक्षित नै भऽ सकल!'''",
        "previewnote": "'''मोन राखू ई मातर पूर्वावलोकन छी।'''\nअहाँक परिवर्तन अखन धरि सँचिआएल नै गेल अछि!",
        "continue-editing": "सम्पादन क्षेत्र जाए",
        "previewconflict": "ई पूर्वदृश्य देखबैए उपरका सम्पादन क्षेत्रक पाठ, ई आएत जखन अहाँ संरक्षित करब।",
-       "session_fail_preview": "''' दुखी छी! अहाँक सत्रक दत्तांश खतम भऽ गेल तै कारणसँ अहाँक सम्पादनक निपटारा नै भऽ सकल।'''\nफेरसँ प्रयास करू।\nजँ ई फेरसँ काज नै करैए, प्रयोग करू [[Special:UserLogout|निष्क्रमण]] आ फेर सम्प्रवेश करू।",
-       "session_fail_preview_html": "''' दुखी छी! हम अहाँक सम्पादनक निष्पादन नै कऽ सकलहुँ कारण सत्रक दत्तांश खतम भऽ गेल।'''\n''कारण {{अन्तर्जाल}} लग काँच एच.टी.एम.एल. दत्तांश सक्रिय छै, पूर्वदृश्य जावास्क्रिप्ट आक्रमणक डरसँ नुकाएल राखल गेल अछि।''\n'''जँ ई वैध सम्पादन प्रयास अछि, कृपा कऽ पुनः प्रयास करू।'''\nजँ ई अखनो काज नै कऽ रहल अछि, प्रयास करू [[Special:UserLogout|निष्क्रमण कऽ रहल छी]] आ फेरसँ सम्प्रवेश।",
+       "session_fail_preview": "'''क्षमा करी! सेशन डाटा नष्ट होमएक कारण अहाँक परिवर्तन रक्षण नै कएल जा सकल।'''\nकृपया पुन: प्रयास करी । यदि एकर बादो सफल नै भेल तँ कृपया [[Special:UserLogout|लग आउट]] करि पुनः सम्प्रवेश करी।",
+       "session_fail_preview_html": "क्षमा करी! सेशन डाटा नष्ट होमएक कारण अहाँक परिवर्तन रक्षण नै कएल जा सकल।\n\n<em>चूँकि {{SITENAME}} पर रव एचटिएमएल सक्षम अछि, जाभास्क्रिप्ट हमला सँ बचावक लेल झलक नै देखाएल गेल अछि।</em>\n\n<strong>अगर ई अहाँक वैध सम्पादन यत्न छल, तँ कृपया पुनः प्रयास करी।</strong>\nयदि एकर बादो सफल नै भेल तँ कृपया [[Special:UserLogout|लग आउट]] करि पुनः सम्प्रवेश करी तथा जाँची यदि अहाँक ब्राउजर एहि साइट सँ कुकिजक अनुमति दैत अछि।",
        "token_suffix_mismatch": "'''अहाँक सम्पादन अस्वीकार कऽ देल गेल अछि कारण अहाँक ग्राहक प्रेष्यमान अंक विधानक विराम चेन्ह सभकेँ नष्ट कऽ देलन्हि।'''\nई सम्पादन पन्नाक पाठकेँ दूषित होएबासँ बचेबा लेल अमान्य कऽ देल गेल।\nई कखनो काल होइए जखन अहाँ जाल आधारित अनाम दोसरा लेल चल सेवा प्रयुक्त करै छी।",
        "edit_form_incomplete": "<strong>सम्पादन आवेदनक किछु भाग वितरक धरि नै पहुँचल; एक बेर फेर देखी जे अहाँक सम्पादन दुरुस्त अछि आ फेरसँ प्रयास करी।</strong>",
        "editing": "सम्पादन होइए $1",
        "yourdiff": "अन्तर",
        "copyrightwarning": "कृपा कय बुझू जे सभटा योगदान {{SITENAME}} ई बुझि कय देल जा रहल अछि जे ई निम्नांकितक अंतर्गत अछि $2 (देखू $1 जनकारीक हेतु). जौँ अहाँ चाहैत छी जी अहाँक रचना बिना रोकटोकक संपादित नहि हो किंवा बाँटल नहि जाय, तँ एकर योगदान एतय नहि करू। <br />\nएतय अहाँ ईहो सप्पत खाइत छी जी ई अहाँक अपन रचना छी आकि अहाँ एकरा कोनो सार्वजनिक डोमेन किंवा ओह्ने कोनो मँगनीक संदर्भ-स्थलसँ कॉपी कएने छी।\n< दृढ़> सर्वाधिकार सुरक्षित कार्य एतय नहि दी।!</दृढ़>",
        "copyrightwarning2": "कृपा कऽ बुझू जे सभटा योगदान {{अन्तर्जाल}} योगदानकर्ता द्वारा सम्पादित, बदलल वा हटाएल जा सकैत अछि।. जौँ अहाँ चाहैत छी जी अहाँक रचना बिना रोकटोकक संपादित नहि हो किंवा बाँटल नहि जाय, तँ एकर योगदान एतय नहि करू। <br />\nएतय अहाँ ईहो सप्पत खाइत छी जी ई अहाँक अपन रचना छी आकि अहाँ एकरा कोनो सार्वजनिक डोमेन किंवा ओहने कोनो मँगनीक संदर्भ-स्थलसँ कॉपी कएने छी(देखू $1 वर्णन लेल)।\n''' सर्वाधिकार सुरक्षित कार्य एतय नहि दी।!'''",
+       "editpage-cannot-use-custom-model": "ई पृष्ठक मुख्य सामग्री परिवर्तित नै भेल।",
        "longpageerror": "'''भ्रम: पाठ जे अहाँ देने छी से $1 किलोबाइट नमगर अछि,  जे अधिकतम आकार $2 किलोबाइट सँ बेशी नमगर अछि।'''\nई संरक्षित नै कएल जा सकत।",
-       "readonlywarning": "''' चेतौनी: ई दत्तनिधि सुस्थापन लेल प्रतिबन्धित कएल गेल अछि, से अहाँ अपन सम्पादनकेँ अखन संरक्षित नै कऽ सकब।'''\nअहाँ पाठकेँ कर्तनलेपन द्वारा एकटा टेक्स्ट संचिकामे धऽ सकै छी आ भविष्य लेल सुरक्षित राखि सकै छी।\n\nसंचालक जे एकरा प्रतिबन्धित केलन्हि से ई कारण देलन्हि: $1",
+       "readonlywarning": "<strong>सावधान: डेटाबेस सुस्थापन लेल बन्द कएल गेल अछि, एहिलेल अहाँक सम्पादन अखन रक्षण नै कएल जा सकत।\nयदि अहाँ पाठ कपी-पेस्टद्वारा एकटा टेक्स्ट सञ्चिकामे धऽ सकै छी आ भविष्य लेल सुरक्षित राखि सकै छी।</strong>\n\nसञ्चालक जे एकरा बन्द केलन्हि से ई कारण देलन्हि: $1",
        "protectedpagewarning": "''' चेतौनी: ई पन्ना संरक्षित अछि से खाली संचालन अधिकारयुक्त प्रयोक्ता एकरा सम्पादित कऽ सकै छथि।'''\nअद्यतन वृतलेख उल्लेख नीचाँ सन्दर्भ लेल देल जा रहल अछि:",
        "semiprotectedpagewarning": "'''चेतौनी:''' ई पन्ना संरक्षित अछि से खाली पंजीकृत प्रयोक्ता एकरा सम्पादित कऽ सकै छथि।\nअद्यतन वृतलेख उल्लेख नीचाँ सन्दर्भ लेल देल जा रहल अछि:",
        "cascadeprotectedwarning": "'''चेतौनी:''' ई पन्ना संरक्षित अछि से खाली संचालन अधिकारयुक्त प्रयोक्ता एकरा सम्पादित कऽ सकै छथि, कारण ई तराउपड़ी संरक्षित {{PLURAL:$1|पन्ना|पन्ना}}  मे शामिल अछि।",
        "undo-summary-username-hidden": "नुकाएल गेल प्रयोक्ताद्वारा केल गेल परिवर्तन $1 के पूर्ववत केल गेल",
        "cantcreateaccount-text": "(<strong>$1</strong>) अनिकेत पतासँ खाता निर्माण प्रतिबन्धित कएल गेल [[User:$3|$3]]।\n$3 द्वारा देल कारण अछि ''$2''",
        "cantcreateaccount-range-text": "<strong>$1</strong> के श्रेणी में आबई वाला आई॰पी पता सऽ, जएमें आहाँ कें आई॰पी पता (<strong>$4</strong>) शामिल अछि, नया खाता के रचना [[User:$3|$3]] द्वारा अवरोधित केल गेल अछि। \n\n$3 द्वारा देल गेल कारण अछि: \"$2\"",
-       "viewpagelogs": "à¤\88 à¤ªà¤¨à¥\8dनाà¤\95 à¤µà¥\83तà¥\8dतलà¥\87à¤\96सभ देखी",
+       "viewpagelogs": "à¤\88 à¤ªà¤¨à¥\8dनाà¤\95 à¤²à¤\97 देखी",
        "nohistory": "ऐ पन्ना लेल कोनो सम्पादन इतिहास नै अछि।",
        "currentrev": "नूतन संशोधन",
        "currentrev-asof": "$1 क समकालिक तखुनका संशोधन",
        "mergehistory-empty": "कोनो संशोधन मिज्झर नै कएल जा सकैए।",
        "mergehistory-done": "$3 {{PLURAL:$3|संशोधन|संशोधन सभ}} एकर $1 सफलता पूर्वक मिज्झर कएल गेल [[:$2]] मे।",
        "mergehistory-fail": "इतिहासक मिश्रणकेँ नै कऽ सकल, कृपा कऽ पन्ना आ समए परिमितिकेँ फेरसँ जाँचू।",
+       "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-timestamps-overlap": "स्रोत अवतरण भेजैवाला अवतरणक बाद आबि रहल अछि।",
+       "mergehistory-fail-toobig": "इतिहास विलय सम्भव नै अछि कियाकि अवतरण सीमा $1 सँ अधिक {{PLURAL:$1|अवतरण|अवतरणसभ}}के स्थानान्तरित करै पडत।",
        "mergehistory-no-source": "स्रोत पन्ना $1 नै अछि।",
        "mergehistory-no-destination": "लक्ष्य पन्ना $1 नै अछि।",
        "mergehistory-invalid-source": "स्रोत पन्ना एकटा मान्य शीर्षक हेबाक चाही।",
        "searchprofile-advanced-tooltip": "बनाएल नामस्थान सभमे ताकी",
        "search-result-size": "$1 ({{PLURAL:$2|1 शब्द|$2 शब्दसभ}})",
        "search-result-category-size": "{{PLURAL:$1|1 सदस्य|$1 सदस्य}} ({{PLURAL:$2|1 उपसंवर्ग|$2 उपसंवर्ग}}, {{PLURAL:$3|1 संचिका|$3 संचिका}})",
-       "search-redirect": "(रस्ता बदलेन $1)",
+       "search-redirect": "($1 सँ पुनर्निर्देशित)",
        "search-section": "(शाखा $1)",
        "search-category": "(श्रेणी $1)",
        "search-file-match": "(फाइल सामग्रीसे मेल खेलक अछि)",
        "search-suggest": "अहाँ मोने अछि जे:$1",
+       "search-rewritten": "$1 क परिणाम देखाए रहल अछि। ई $2 हेतु खोजि रहल अछि।",
        "search-interwiki-caption": "अन्य प्रकल्प",
        "search-interwiki-default": "$1 सँ परिणाम:",
        "search-interwiki-more": "(आर)",
        "showingresultsinrange": "नीचाँ एतऽ धरि {{PLURAL:$1|'''1''' परिणाम|'''$1''' परिणाम सभ}}  #'''$2''' सँ प्रारम्भ भऽ कऽ।",
        "search-showingresults": "{{PLURAL:$4|<strong>$3</strong> में से <strong>$1</strong> परिणाम|<strong>$3</strong> में सँ परिणाम <strong>$1 - $2</strong>}}",
        "search-nonefound": "अभ्यर्थनासँ मेल खाइत कोनो परिणाम नै भेटल।",
+       "search-nonefound-thiswiki": "अभ्यर्थनासँ मेल खाइत कोनो परिणाम नै भेटल।",
        "powersearch-legend": "विशेष खोज",
        "powersearch-ns": "निर्धारकमे खोज",
        "powersearch-togglelabel": "जाँची:",
        "prefs-watchlist-token": "साकांक्ष-सूची खेप:",
        "prefs-misc": "आर",
        "prefs-resetpass": "कूटशब्द बदली",
-       "prefs-changeemail": "à¤\88-पतà¥\8dर à¤¸à¤\82à¤\95à¥\87त à¤¬à¤¦à¤²à¥\82",
+       "prefs-changeemail": "à¤\87मà¥\87ल à¤ªà¤¤à¤¾ à¤ªà¤°à¤¿à¤µà¤°à¥\8dतित à¤\95रà¥\80",
        "prefs-setemail": "ई-पत्र ठेगान निर्धारित करी",
        "prefs-email": "ई-पत्र विकल्पसभ",
        "prefs-rendering": "मुँहकान",
        "saveprefs": "सङ्ग्रह करी",
-       "restoreprefs": "सभà¤\9fा à¤ªà¥\82रà¥\8dवनिरà¥\8dधारित à¤\9aयनà¤\95à¥\87à¤\81 à¤«à¥\87रसà¤\81 à¤\86नà¥\82",
+       "restoreprefs": "सभà¤\9fा à¤ªà¥\82रà¥\8dवनिरà¥\8dधारित à¤\9aयनà¤\95à¥\87à¤\81 à¤«à¥\87रसà¤\81 à¤\86नà¥\80",
        "prefs-editing": "सम्पादन कऽ रहल छी",
        "rows": "पाँतीसभ",
        "columns": "स्तम्भसभ",
        "searchresultshead": "ताकी",
-       "stub-threshold": "सà¥\80मा <a href=\"#\" class=\"stub\">à¤\95ाà¤\9fल à¤²à¤¾à¤\97ि</a> à¤¸à¤\81à¤\9aियाà¤\8fल (à¤\85षà¥\8dà¤\9fà¤\95):",
+       "stub-threshold": "à¤\86धार à¤²à¤¿à¤\99à¥\8dà¤\95 à¤¹à¥\87तà¥\81 à¤ªà¥\8dरारà¥\82पण ($1):",
        "stub-threshold-sample-link": "उदाहरण",
        "stub-threshold-disabled": "अशक्त कएल",
        "recentchangesdays": "आइ-काल्हिक परिवर्तनमे कतेक दिन देखाएल गेल:",
        "prefs-tokenwatchlist": "टोकन",
        "prefs-diffs": "अन्तर",
        "prefs-help-prefershttps": "इ प्राथमिकता अहाँके फेर स सम्प्रवेश करलाक बाद प्रभाव पडत।",
+       "prefswarning-warning": "अहाँ अपन पसन्दमे एहन परिवर्तन केनए छी जे अखनि धरि रक्षण नै केल गेल अछि। यदि अहाँ \"$1\" पर बिना क्लिक केनए ई पृष्ठ छोडि देबै तँ अहाँक पसन्द अपडेट नै केल जाइत।",
        "prefs-tabs-navigation-hint": "सुझाव: अहाँ टैब्स सूचीमे टैब्सके बीच आवागमन करवाक लेल बाम आर दाहिना बागलके कुंजिसभके उपयोग कइर सकैत छी।",
        "userrights": "प्रयोक्ता अधिकारक प्रबन्धन",
        "userrights-lookup-user": "प्रयोक्ता समूहसभक प्रबन्ध करी",
        "right-delete": "पन्ना मेटाबी",
        "right-bigdelete": "बेसी इतिहास भएल पन्ना सभ मेटाबी",
        "right-deletelogentry": "विशिष्ट लग प्रविष्टिसभके नुकाउ आ देखाउ",
-       "right-deleterevision": "निरà¥\8dधारित à¤¸à¤\82शà¥\8bधित à¤ªà¤¨à¥\8dना à¤®à¥\87à¤\9fाà¤\89 à¤\86 à¤«à¥\87रसà¤\81 à¤\86नà¥\82",
+       "right-deleterevision": "पà¥\83षà¥\8dठसभà¤\95 à¤µà¤¿à¤¶à¤¿à¤·à¥\8dà¤\9f à¤\85वतरण à¤¹à¤\9fाबà¥\80 à¤¤à¤¥à¤¾ à¤ªà¥\81नरà¥\8dसà¥\8dथापित à¤\95रà¥\80",
        "right-deletedhistory": "मेटाएल इतिहास प्रविष्टि देखू, बिना लागिक पाठक",
        "right-deletedtext": "मेटाएल पाठ आ दूटा मेटाएल संशोधनक बीचक परिवर्तन देखी",
        "right-browsearchive": "मेटाएल पन्ना ताकी",
        "right-override-export-depth": "५ परत धरि जा  पन्ना सभ निर्यात, जइमे लागिबला पन्ना सभ शामिल अछि, करू।",
        "right-sendemail": "ई-पत्र दोसर प्रयोक्ता लोकनिकेँ पठाउ",
        "right-passwordreset": "कूटशब्द पुनर्निर्धारण ई-पत्र देखू",
-       "right-managechangetags": "डेटाबेस से [[Special:Tags|नुकाबू]] बनाबु आर हटाबु",
+       "right-managechangetags": "[[Special:Tags|ट्यागसभ]] बनाबी आ नुकाबी",
        "right-applychangetags": "प्रयोग में लाबू [[Special:Tags|tags]] कक्रो बदलाव के साथ।",
        "right-changetags": "जमा करु आर हटाबु स्वतंत्र [[Special:Tags|टैग]] व्यक्तिगत अवतरण आर लॉग प्रविक्ति पे",
+       "right-deletechangetags": "डेटाबेस सँ [[Special:Tags|ट्यागसभ]] मेटाबी",
        "grant-generic": "\"$1\" अधिकार सङ्ग्रह",
        "grant-group-page-interaction": "पृष्ठसभसँ जोडी",
        "grant-group-file-interaction": "मिडियासँ जोडी",
-       "newuserlogpage": "प्रयोक्ता रचना वृत्तलेख",
+       "grant-group-watchlist-interaction": "ध्यानसूची सँ मेल करी",
+       "grant-group-email": "इमेल पठाबी",
+       "grant-group-high-volume": "उच्च कार्य गतिविधि करी",
+       "grant-group-customization": "पसन्द आ तय",
+       "grant-group-administration": "प्रबन्धकीय कार्य करी",
+       "grant-group-private-information": "अपन सम्बन्धमे निजी डेटा आनी",
+       "grant-group-other": "अन्य गतिविधि",
+       "grant-blockusers": "प्रतिबन्धित आ अप्रतिबन्धित करनाए",
+       "grant-createaccount": "खाता खोलल जाए",
+       "grant-createeditmovepage": "निर्माण, सम्पादन, आ स्थानान्तरण करनाए",
+       "grant-delete": "लेख, अवतरण आ लग हटेनाए",
+       "grant-editinterface": "मिडियाविकि नामस्थान आ सदस्य सिएसएस/जेएस सम्पादित करनाए",
+       "grant-editmycssjs": "अपन सदस्य सिएसएस/जेएस सम्पादित करी",
+       "grant-editmyoptions": "अपन सदस्य पसन्द सम्पादित करी",
+       "grant-editmywatchlist": "अपन साकांक्षसूची सम्पादित करी",
+       "grant-editpage": "बनल पृष्ठ सम्पादित करी",
+       "grant-editprotected": "सुरक्षित पृष्ठ सम्पादित करी",
+       "grant-highvolume": "अत्यधिक तेजी सँ सम्पादन",
+       "grant-oversight": "सदस्य नुकाबी आ अवतरण हटाबी",
+       "grant-patrol": "पृष्ठसभके जाँचल चिन्हित करी",
+       "grant-privateinfo": "निजी जानकारी आनी",
+       "grant-protect": "पृष्ठसभ सुरक्षित व असुरक्षित करनाए",
+       "grant-rollback": "पृष्ठ सँ सम्पादन पूर्ववत केनाए",
+       "grant-sendemail": "अन्य प्रयोगकर्ताके इ-मेल भेजी",
+       "grant-uploadeditmovefile": "फाइल अपलोड, बदलनाए, स्थानान्तरण करनाए",
+       "grant-uploadfile": "नव सञ्चिकासभ उपारोपित करी",
+       "grant-basic": "सामान्य अधिकार",
+       "grant-viewdeleted": "हटाएल फाइल व पृष्ठ देखी",
+       "grant-viewmywatchlist": "अपन साकांक्षसूची देखी",
+       "newuserlogpage": "प्रयोक्ता रचना लग",
        "newuserlogpagetext": "ई प्रयोक्ता निर्माणक वृत्तलेख अछि।",
        "rightslog": "प्रयोक्ता अधिकार वृत्तलेख",
        "rightslogtext": "ई प्रयोक्ता अधिकार परिवर्तन सभक वृतलेख छी।",
        "action-read": "ई पन्ना पढी",
        "action-edit": "ई पन्नाक सम्पादित करी",
-       "action-createpage": "पृष्ठ बनाबी",
-       "action-createtalk": "वार्ता पन्ना बनाबी",
+       "action-createpage": "à¤\88 à¤ªà¥\83षà¥\8dठ à¤¬à¤¨à¤¾à¤¬à¥\80",
+       "action-createtalk": "à¤\88 à¤µà¤¾à¤°à¥\8dता à¤ªà¤¨à¥\8dना à¤¬à¤¨à¤¾à¤¬à¥\80",
        "action-createaccount": "ई प्रयोक्ता खाता बनाबी",
+       "action-autocreateaccount": "स्वतः बाहरी सदस्य खाता बनाबी",
        "action-history": "पन्नाक इतिहास मिज्झर करी",
        "action-minoredit": "ऐ सम्पादनके मामूली कही",
        "action-move": "ई पृष्ठके स्थानान्तरित करी",
        "action-viewmyprivateinfo": "अपन व्यक्तिगत जानकारी देखु",
        "action-editmyprivateinfo": "अपन व्यक्तिगत जानकारी सम्पादित करु",
        "action-editcontentmodel": "एक पन्ना के सामग्री मॉडल कें सम्पादन।",
-       "action-managechangetags": "डà¥\87à¤\9fाबà¥\87स à¤¸à¥\87 à¤\9aिपà¥\8dपि à¤¬à¤¨à¤¾à¤¬à¥\81 à¤\86र à¤¹à¤\9fाबà¥\81",
+       "action-managechangetags": "à¤\9fà¥\8dयाà¤\97 à¤¬à¤¨à¤¾à¤¬à¥\80 à¤\86 à¤¸à¤\95à¥\8dषम (à¤\85सà¤\95à¥\8dषम) à¤\95रà¥\80",
        "action-applychangetags": "आहाँ के बदलाव के साथ टैग जोडू।",
        "action-changetags": "जमा करु आर हटाबु स्वतंत्र टैग व्यक्तिगत अवतरण आर लॉग प्रविक्ति पे",
+       "action-deletechangetags": "डेटाबेस सँ ट्याग मेटाबी",
+       "action-purge": "पृष्ठक क्यास खाली करी",
        "nchanges": "$1 {{PLURAL:$1|परिवर्त्तन|परिवर्त्तन}}",
        "enhancedrc-since-last-visit": "$1 {{PLURAL:$1|अंतिम बेर देखला के बाद स}}",
        "enhancedrc-history": "इतिहास",
        "recentchanges-label-plusminus": "पन्ना आकार ई बाइट सङ्ख्या सँ बदलल गेल",
        "recentchanges-legend-heading": "<strong>कुञ्जी:</strong>",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} ([[Special:NewPages|नव पन्नसभक सूची]] सेहो देखी)",
+       "recentchanges-submit": "देखाबी",
        "rcnotefrom": "नीचाँमे '''$2''' सँ भेल परिवर्तन अछि ('''$1''' धरि देखाएल)।",
        "rclistfrom": "$3 $2 सँ शुरू भेल नव परिवर्तन देखी",
        "rcshowhideminor": "$1 अल्प सम्पादन",
        "rcshowhideminor-show": "देखाबी",
        "rcshowhideminor-hide": "नुकाबी",
-       "rcshowhidebots": "$1 स्वचालक",
+       "rcshowhidebots": "स्वचालक $1",
        "rcshowhidebots-show": "देखाबी",
        "rcshowhidebots-hide": "नुकाबी",
        "rcshowhideliu": "पञ्जीकृत प्रयोगकर्तासभ $1",
        "rcshowhidemine": "$1 हमर सम्पादनसभ",
        "rcshowhidemine-show": "देखाबी",
        "rcshowhidemine-hide": "नुकाबी",
+       "rcshowhidecategorization": "$1 पृष्ठ श्रेणीकरण",
        "rcshowhidecategorization-show": "देखाबी",
        "rcshowhidecategorization-hide": "नुकाबी",
        "rclinks": "पिछला $2 दिनमे भएल $1 परिवर्तन देखाबी<br />$3",
        "boteditletter": "ब",
        "unpatrolledletter": "!",
        "number_of_watching_users_pageview": "[$1 ध्यान राखैवाला {{PLURAL:$1|प्रयोक्ता|प्रयोक्तासभ}}]",
-       "rc_categories": "सà¤\82वरà¥\8dà¤\97 à¤¸à¥\80मित (\"|\" à¤¸à¤\81 à¤¹à¤\9fाà¤\89)",
-       "rc_categories_any": "कोनो",
+       "rc_categories": "शà¥\8dरà¥\87णà¥\80सभ à¤§à¤°à¤¿ à¤¸à¥\80मà¥\80त à¤°à¤¾à¤\96à¥\80 (\"|\" à¤¸à¤\81 à¤\85लà¤\97 à¤\95रà¥\80)",
+       "rc_categories_any": "कोनो भी चुनिन्दा",
        "rc-change-size": "$1",
        "rc-change-size-new": "परिवर्तनक बाद $1 {{PLURAL:$1|बाइट}}",
        "newsectionsummary": "/* $1 */ नव अनुभाग",
        "recentchangeslinked-summary": "ई विशेष पन्नासँ सम्बद्ध पन्ना सभमे (आकि कोनो विशेष वर्गक समूहमे) भेल परिवर्तनक सूची छी ।\n[[Special:Watchlist|your watchlist]]  पर पन्नासभ '''गाढ़''' अछि।",
        "recentchangeslinked-page": "पन्नाक नाम:",
        "recentchangeslinked-to": "देल पन्नाक सम्बन्धी पन्नामे परिवर्तन देखाबी",
+       "recentchanges-page-added-to-category": "[[:$1]] श्रेणीमे जुडल",
+       "recentchanges-page-removed-from-category": "[[:$1]] श्रेणी सँ हटल",
+       "autochange-username": "मिडियाविकि स्वतः परिवर्तन",
        "upload": "फाइल अपलोड करी",
        "uploadbtn": "फाइल अपलोड",
        "reuploaddesc": "उपारोपण रद्द करी आ उपारोपण आवेदन-पत्रपर जाए।",
        "upload-recreate-warning": "'''चेतौनी: ऐ नामक संचिका मेटा वा हटा देल गेल अछि।'''",
        "uploadtext": "निचुक्का पत्र संचिका उपारोपित करबा लेल प्रयोग करू।\nपहिलुका उपारोपित संचिका देखबा वा तकबा लेल जाउ [[Special:FileList|उपारोपित संचिका सभक सूची]], (पुनः) उपारोपित सेहो सम्प्रवेशित अछि [[Special:Log/upload|उपारोपित वृत्तलेख]] मे, मेटाएल सभ [[Special:Log/delete|मेटाएल वृत्तलेख]] मे।\nपन्नमे एकटा संचिका देबा लेल, ऐ पत्र सभमेसँ कोनो लागिक प्रयोग करू:\n* '''<code><nowiki>[[</nowiki>{{ns:file}}<nowiki>:File.jpg]]</nowiki></code>''' संचिकाक पूर्ण संस्करण देखबा लेल\n* '''<code><nowiki>[[</nowiki>{{ns:file}}<nowiki>:File.png|200px|thumb|left|alt text]]</nowiki></code>'''  २०० चित्राणु चाकर प्रकटन एकटा बक्शामे \"वैकल्पिक पाठ\" वामा कात वर्णनक रूपमे लिखल प्रयोग करू\n* '''<code><nowiki>[[</nowiki>{{ns:media}}<nowiki>:File.ogg]]</nowiki></code>''' बिना संचिका देखेने सोझे संचिकाक लागि देब",
        "upload-permitted": "अनुमतित फाइल  {{PLURAL:$2|प्रकार}}: $1।",
-       "upload-preferred": "मà¥\8bनपसिनà¥\8dन à¤¸à¤\82à¤\9aिà¤\95ा à¤ªà¥\8dरà¤\95ार:$1 ।",
-       "upload-prohibited": "पà¥\8dरतिबनà¥\8dधित à¤¸à¤\82à¤\9aिà¤\95ा à¤ªà¥\8dरà¤\95ार:$1 ।",
+       "upload-preferred": "पसनà¥\8dदिदा à¤«à¤¾à¤\87ल {{PLURAL:$2|पà¥\8dरà¤\95ार|पà¥\8dरà¤\95ारसभ}}: $1।",
+       "upload-prohibited": "पà¥\8dरतिबनà¥\8dधित à¤¸à¤\9eà¥\8dà¤\9aिà¤\95ा {{PLURAL:$2|पà¥\8dरà¤\95ार|पà¥\8dरà¤\95ारसभ}}:$1 ।",
        "uploadlogpage": "उपारोपण वृत्तलेख",
        "uploadlogpagetext": "नीचाँ अद्यतन सञ्चिका उपारोपणक वर्णन अछि।\nदेखी [[Special:NewFiles|नव सञ्चिकाक बखारी]] बेसी स्पष्ट समुच्चा दृश्य लेल।",
        "filename": "सञ्चिका नाम",
        "uploaddisabledtext": "संचिका उपारोपण सभ अशक्त अछि।",
        "php-uploaddisabledtext": "पी.एच.पी.मे संचिका उपारोपण अशक्त अछि।\nकृपा कऽ संचिका उपारोपण विकल्प जाँचू।",
        "uploadscripted": "ई संचिका पर्यंकभाषा वा कूटलिपि युक्त अछि जे गवेषक द्वारा गलत रूपमे व्याख्यायित कएल जा सकैए।",
+       "upload-scripted-pi-callback": "ओ फाइल अपलोड नै केल जा सकैत अछि जाहिमे एक्सएमएल-स्टाइलसिट प्रसंस्करण निर्देश समाविष्ट अछि।",
+       "uploaded-script-svg": "अपलोड केल गेल एसभिजी फाइलमे स्क्रिप्ट अवयव \"$1\" पाबल गेल।",
        "uploadscriptednamespace": "इ एस॰वी॰जी फाइलमे अमान्य नामस्थान \"$1\" अछि।",
        "uploadinvalidxml": "अपलोड केएल गेल फाइलमे स्थित XML पार्स नै केएल जा सकैत अछि।",
        "uploadvirus": "ई संचिका विषविधियुक्त अछि।\nवर्णन:$1",
        "uploadstash-summary": "ई पन्ना उपारोपित संचिका सभक प्रवेश द्वार छी (वा उपारोपणक प्रक्रियामे) मुदा अखन धरि विकीमे प्रकाशित नै भेल अछि। ई सभ संचिका प्रयोक्ताक अतिरिक्त ककरो द्वारा देखल नै जा सकैए।",
        "uploadstash-clear": "नुकाएल बखारी सभक संचिकाकेँ साफ खतम करू",
        "uploadstash-nofiles": "अहाँ लग कोनो नुकाएल संचिका सभ नै अछि।",
-       "uploadstash-badtoken": "ओइ कार्यक सम्पादन असफल रहल, प्रायः अहाँक सम्पादन योग्यता खतम भऽ गेल अछि। फेरसँ प्रयास करू।",
-       "uploadstash-errclear": "सà¤\82à¤\9aिà¤\95ा à¤¸à¤­à¤\95à¥\87à¤\81 à¤\96तम à¤\95रब असफल रहल।",
+       "uploadstash-badtoken": "ओ कार्यक सम्पादन असफल रहल, प्रायः अहाँक सम्पादन योग्यता खतम भऽ गेल अछि। फेर सँ प्रयास करी।",
+       "uploadstash-errclear": "फाà¤\87लसभà¤\95à¥\87 à¤¸à¤¾à¤« à¤\95रनाà¤\8f असफल रहल।",
        "uploadstash-refresh": "संचिका सभक सूचीकेँ ताजा करू।",
+       "uploadstash-thumbnail": "छवि देखी",
        "invalid-chunk-offset": "एकट्ठे अमान्य बौस्तु",
        "img-auth-accessdenied": "प्रवेश प्रतिबन्धित",
        "img-auth-nopathinfo": "बाटक जानकारी नै अछि।\nअहाँक वितरक ऐ सूचनाकेँ प्रसारित नै कऽ सकत।\nई सी.जी.आइ.आधारित अछि आ चित्र-समर्थन केँ समर्थन नै दऽ सकत।\n[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Image_Authorization देखू image authorization.]",
        "randompage-nopages": "ऐमे दोसर पन्ना नै अछि {{PLURAL:$2|namespace|namespaces}}: $1 ।",
        "randomincategory": "श्रेणी में यादृच्छिक (रैंडम) पन्ना",
        "randomincategory-invalidcategory": "\"$1\" एक मान्य श्रेणी नाम नै अछि।",
+       "randomincategory-nopages": "[[:Category:$1|$1]] श्रेणीमे कोनो पृष्ठ नै अछि।",
        "randomincategory-category": "श्रेणी:",
+       "randomincategory-legend": "श्रेणीमे यादृच्छिक पृष्ठ",
+       "randomincategory-submit": "जाए",
        "randomredirect": "मिज्झर बदलेनबला लागि",
        "randomredirect-nopages": "नामस्थान \"$1\" मे कोनो बदलेनबला लागि नै अछि।",
        "statistics": "सांख्यिकी",
        "statistics-users": "पञ्जीकृत [[Special:ListUsers|प्रयोक्ता]]",
        "statistics-users-active": "सक्रिय प्रयोक्ता",
        "statistics-users-active-desc": "प्रयोक्ता जे अन्तिम {{PLURAL:$1|दिन|$1 दिन}} मे कोनो काज केने छथि",
+       "pageswithprop": "पृष्ठ जाहिमे पृष्ठ गुण अछि",
+       "pageswithprop-legend": "पृष्ठ जाहिमे पृष्ठ गुण अछि",
+       "pageswithprop-text": "ई पृष्ठ पृष्ठ गुणक उपयोग करि रहल पन्नासभ सूचीबद्ध करैत अछि।",
+       "pageswithprop-prop": "गुणक नाम:",
        "pageswithprop-submit": "जाए",
+       "pageswithprop-prophidden-long": "लम्बा पाठक गुण नुकाएल ($1) अछि",
+       "pageswithprop-prophidden-binary": "बाइनरी गुण ($1) नुकाएल अछि।",
        "doubleredirects": "द्वितीयक लागएबला बदलेन",
        "doubleredirectstext": "ई पन्ना ओइ पन्ना सभक संकलन छी जे बदलेन करैए दोसर बदलेनबला पन्नासँ।\nप्रत्येक पाँती पहिल आ दोसर बदलेनक लागि रखने अछि आ संगे दोसर बदलेनक लक्ष्य सेहो, जे वास्तवमे \"वास्तव\" लक्ष्य पन्ना अछि, जकरापर पहिल बदलेनकेँ जेबाक चाही। \n <del>Crossed out</del> प्रविष्टिक हल भेटल अछि।",
        "double-redirect-fixed-move": "[[$1]] घसकाएल गेल।\nई आब [[$2]] दिस जा रहल अछि।",
        "booksources-invalid-isbn": "देल आइ.एस.बी.एन. संख्या मान्य नै बुझाइत अछि; कृपा कऽ मूल स्रोतसँ द्वितीयक बनेबा काल भेल भ्रमकेँ जाँचू।",
        "specialloguserlabel": "कर्ता:",
        "speciallogtitlelabel": "प्रयोजन (शीर्षक अथवा {{ns:user}}:प्रयोगकर्तानाम):",
-       "log": "वृत्तलेख",
+       "log": "लौग",
+       "logeventslist-submit": "देखाबी",
        "all-logs-page": "सभ सार्वजनिक वृत्तलेख",
        "alllogstext": "{{अन्तर्जाल}} क सभटा उपलब्ध वृत्तलेखक संयुक्त दृश्य।\nअहाँ दृश्यकेँ संकीर्ण करबा लेल वृत्तलेखक एकटा प्रकार चुनि सकै छी, प्रयोक्तानाम (ब्रह्मक्षर-लघ्वक्षर विचारणीय), वा प्रभावित पन्ना (एतौ ब्रह्मक्षर-लघ्वक्षर विचारणीय)।",
        "logempty": "वृत्तलेखमे कोनो मेल खाइबला बौस्तु नै।",
        "log-title-wildcard": "खोज शीर्षक सभ ऐ पाठसँ प्रारम्भ",
        "showhideselectedlogentries": "देखाबी/ नुकाबी चयनित लग",
        "log-edit-tags": "चुनल गेल लग प्रविक्तिसभ एक सम्पादन ट्याग",
+       "checkbox-select": "चुनी: $1",
+       "checkbox-all": "सभटा",
+       "checkbox-none": "कोनो नै",
+       "checkbox-invert": "बदली",
        "allpages": "सभ पन्ना",
        "nextpage": "अगिला पन्ना ($1)",
        "prevpage": "पहिलुका पन्ना ($1)",
        "cachedspecial-viewing-cached-ts": "अहाँ इ पृष्ठ के क्यास कएल गएल अवतरण देख रहल छी, जे कि संभवतः वर्तमान अवस्था सँ भिन्न भऽ सकएत अछि।",
        "cachedspecial-refresh-now": "लब्का देखु",
        "categories": "श्रेणीसभ",
+       "categories-submit": "देखाबी",
        "categoriespagetext": "ई {{PLURAL:$1|संवर्गमे अछि|संवर्ग सभमे अछि}} पन्ना वा मीडिया।\n[[Special:UnusedCategories|Unused categories]] एतए देखाएल नै अछि।\nईहो देखू [[Special:WantedCategories|wanted categories]]।",
        "categoriesfrom": "पन्ना प्रदर्शन प्रारम्भ भेल:",
        "deletedcontributions": "मेटाएल प्रयोक्ता योगदान",
        "listusers-blocked": "(प्रतिबन्धित)",
        "activeusers": "सक्रिय प्रयोक्ता सभक सूची",
        "activeusers-intro": "ई ओहेन प्रयोक्ता सभक सूची अछि जे पछिला $1 {{PLURAL:$1|दिन|दिन}} मे किछु सक्रियता देखेने छथि।",
-       "activeusers-count": "$1 {{PLURAL:$1|समà¥\8dपादन}} à¤µà¤¿à¤\97त $3 {{PLURAL:$3|दिन|दिन}}मे",
+       "activeusers-count": "$1 {{PLURAL:$1|à¤\95ारà¥\8dय}} à¤ªà¤¿à¤\9bला $3 {{PLURAL:$3|दिन|दिनसभ}}मे",
        "activeusers-from": "प्रयोक्ता प्रदर्शन प्रारम्भ भेल:",
        "activeusers-hidebots": "स्वचालक नुकाबी",
        "activeusers-hidesysops": "प्रबन्धक नुकाबी",
        "activeusers-noresult": "कोनो प्रयोक्ता नै भेटल",
+       "activeusers-submit": "सक्रिय प्रयोगकर्ता देखाबी",
        "listgrouprights": "प्रयोगकर्ता समूह अधिकार",
        "listgrouprights-summary": "ई सभ प्रयोक्ता संवर्गक एकटा सूची अछि जे ऐ विकीपरपरिभाषित अछि ओकर संसर्गित प्रवेश अधिकारक संग।\nएतए [[{{MediaWiki:Listgrouprights-helppage}}|additional information]] व्यक्तिगत अधिकार लेल भऽ सकैए।",
        "listgrouprights-key": "* <span class=\"listgrouprights-granted\">देल अधिकार</span>\n* <span class=\"listgrouprights-revoked\">निकालल अधिकार</span>",
        "listgrouprights-namespaceprotection-header": "नामस्थान प्रतिबन्धित",
        "listgrouprights-namespaceprotection-namespace": "नामस्थान",
        "listgrouprights-namespaceprotection-restrictedto": "सांच(सभ) के संपादन करए लेल",
+       "listgrants": "प्रदान",
+       "listgrants-summary": "ई प्रदान केल गेल सूची छी। सदस्य अपन खाताक अनुपयोगक द्वारा उपयोग करि सकैत अछि, मुदा मात्र किछ सीमित अधिकार धरि। ई अधिकार सदस्यद्वारा देल गेल अधिकार धरि सीमित रहैत अछि । एतय [[{{MediaWiki:Listgrouprights-helppage}}|अन्य जानकारी]] सेहो अछि, जे एक अधिकारक बारेमे बताबैत अछि।",
+       "listgrants-grant": "अधिकार",
+       "listgrants-rights": "अधिकार",
        "trackingcategories": "श्रेणीके ट्रयाक करु",
+       "trackingcategories-summary": "ई पृष्ठ पर ओ जोडवाला श्रेणीसभक सूची मिलैत अछि जे स्वतः रूप सँ मिडियाविकि सफ्टवेयरद्वारा बनैत अछि। ओ सभक नाम सम्बन्धित प्रणाली सन्देस बदलै सँ {{ns:8}} नामस्थानमे बदलल जा सकैत अछि।",
        "trackingcategories-msg": "चिह्नित श्रेणी",
        "trackingcategories-name": "सन्देश नाम",
        "trackingcategories-desc": "श्रेणी समावेशीकरण मापदण्ड",
        "wlheader-showupdated": "पन्ना सभ जे अहाँक एतए अन्तिम बेर अएलाक बाद बदलल अछि तकर सूची देल अछि '''गाढ़''' मे",
        "wlnote": "नीचाँ {{PLURAL:$1|is the last change|are the last '''$1''' changes}} अन्तिम {{PLURAL:$2|hour|'''$2''' hours}} $3, $4 जेना।",
        "wlshowlast": "देखाउ अन्तिम $1 घण्टा $2 दिन",
+       "watchlist-hide": "नुकाबी",
+       "watchlist-submit": "देखाबी",
+       "wlshowtime": "समय श्रेणी देखाबी:",
+       "wlshowhideminor": "छोट सम्पादन",
+       "wlshowhidebots": "स्वचालक",
+       "wlshowhideliu": "पञ्जीकृत प्रयोक्तासभ",
+       "wlshowhideanons": "बेनामी प्रयोक्तासभ",
+       "wlshowhidepatr": "परीक्षित सम्पादन",
+       "wlshowhidemine": "हमर सम्पादन",
+       "wlshowhidecategorization": "पृष्ठ श्रेणीकरण",
        "watchlist-options": "साकांक्षसूचीक विकल्प",
        "watching": "ताकिमे...",
        "unwatching": "छोडल ...",
        "enotif_subject_deleted": "{{SITENAME}} पन्ना $1 के {{gender:$2|$2}} हटेलक",
        "enotif_subject_created": "{{SITENAME}} पन्ना $1 को {{gender:$2|$2}} बनेलक",
        "enotif_subject_moved": "{{SITENAME}} पृष्ठ $1 के {{gender:$2|$2}} घसकेलक",
+       "enotif_subject_restored": "{{SITENAME}} पृष्ठ $1 के {{gender:$2|$2}}द्वारा पुनर्स्थापित करल गेल अछि",
+       "enotif_subject_changed": "{{SITENAME}} पृष्ठ $1 के {{gender:$2|$2}}द्वारा परिवर्तित केल गेल अछि",
+       "enotif_body_intro_deleted": "{{SITENAME}} पृष्ठ $1 के {{gender:$2|$2}}द्वारा $PAGEEDITDATE क मेटाए देलक, देखी $3।",
+       "enotif_body_intro_created": "{{SITENAME}} पृष्ठ $1 के {{gender:$2|$2}}द्वारा $PAGEEDITDATE क बनाएल अछि, वर्तमान अवतरणक लेल $3 देखी।",
+       "enotif_body_intro_moved": "{{SITENAME}} पृष्ठ $1 के {{gender:$2|$2}}द्वारा $PAGEEDITDATE क स्थानान्तरित केनए अछि, वर्तमान अवतरणक लेल $3 देखी।",
+       "enotif_body_intro_restored": "{{SITENAME}} पृष्ठ $1 के {{gender:$2|$2}}द्वारा $PAGEEDITDATE क पुनर्स्थापित केनए अछि, वर्तमान अवतरणक लेल $3 देखी।",
+       "enotif_body_intro_changed": "{{SITENAME}} पृष्ठ $1 के {{gender:$2|$2}}द्वारा $PAGEEDITDATE क परिवर्तित केनए अछि, वर्तमान अवतरणक लेल $3 देखी।",
        "enotif_lastvisited": "देखू $1 अपन अन्तिम बेर अएलाक बादक परिवर्तन लेल।",
        "enotif_lastdiff": "ऐ परिवर्तनकेँ देखबा लेल $1 देखू।",
        "enotif_anon_editor": "गुप्त प्रयोक्ता $1",
        "deletepage": "पन्ना मेटाउ",
        "confirm": "पक्का छी",
        "excontent": "विषय छल:\"$1\"",
-       "excontentauthor": "पाठ छल:\"$1\" (आ एकमात्र योगदान दैबला छल \"[[Special:Contributions/$2|$2]]\")",
+       "excontentauthor": "पाठ छल:\"$1\" (आ एकमात्र योगदान दैबला छल \"[[Special:Contributions/$2|$2]]\" ([[User talk:$2|वार्ता]])",
        "exbeforeblank": "खतम होएबाक पहिने पाठ छल:\"$1\"",
        "delete-confirm": "$1 के मेटाबी",
        "delete-legend": "मेटाबी",
        "historywarning": "'''चेतौनी:''' जे पन्ना अहाँ मेटबैबला छी तकर इतिहास अछि लगभग $1 {{PLURAL:$1|revision|revisions}}:",
+       "historyaction-submit": "देखाबी",
        "confirmdeletetext": "अहाँ सभटा इतिहासक संग ऐ पन्नाकेँ हटाबऽ जा रहल छी।\nअहाँ ई सुनिश्चित करू जे अहाँ ई करऽ चाहै छी, अहाँकेँ एकर परिणामक अवगति अछि आ अहाँ ई ऐ [[{{MediaWiki:Policy-url}}|नीति]] क अनुसार कऽ रहल छी।",
        "actioncomplete": "क्रिया पूर्ण",
        "actionfailed": "कार्य नै भेल",
        "delete-toobig": "ऐ पन्नामे बड्ड बेसी सम्पादन इतिहास अछि, $1 सँ बेसी {{PLURAL:$1|revision|revisions}}।\nओइ सभ पन्नाक मेटाएब प्रतिबन्धित कएल गेल अछि जइसँ आकस्मिक क्षति नै हुअए {{जालस्थलक}}।",
        "delete-warning-toobig": "ऐ पन्नामे बड्ड सम्पादन इतिहास अछि, $1 सँ बेसी {{PLURAL:$1|revision|revisions}}।\nएकरा मेटेलापर दत्तनिधि क्रिया {{जालस्थल}} खतरामे पड़त;\nसतर्कीसँ आगाँ बढ़ू।",
        "deleteprotected": "अहाँ इ पन्ना नै मेटा सकए छी कियाकि ई सुरक्षण कएल गेल अछि",
-       "deleting-backlinks-warning": "'''चेतौनी:''' जे पृष्ठ अहाँ हटावए लेल जा रहल छी वोकरा में  [[Special:WhatLinksHere/{{FULLPAGENAME}}|अन्य पृष्ठ]] जुड़एत अछि अथवा वोकरा ट्रान्सक्ल्युड करएत अछि।",
+       "deleting-backlinks-warning": "<strong>चेतावनी:</strong> जे पृष्ठ अहाँ मेटाबै लेल जा रहल छी ओ  [[Special:WhatLinksHere/{{FULLPAGENAME}}|अन्य पृष्ठसभ]] सँ जुडल अछि अथवा ट्रान्सक्ल्युड करैत अछि।",
        "rollback": "प्रत्यावर्तित सम्पादन",
        "rollbacklink": "प्रत्यावर्तन",
        "rollbacklinkcount": "$1 {{PLURAL:$1|सम्पादन}} पूर्ववत करी",
        "revertpage": "सम्पादन आपस कएल गेल [[Special:Contributions/$2|$2]] ([[User talk:$2|talk]]) सँ अन्तिम संशोधन धरि एकरा द्वारा [[User:$1|$1]]।",
        "revertpage-nouser": "(प्रयोक्ताक नाम हटा देल गेल अछि) द्वारा केल गेल संपादनकेँ फेरसँ पुरान स्थितिमे आनि कऽ एकर पहिलुक [[User:$1|$1]] सँ बनल संस्करणकेँ फेरसँ ताजा संस्करण बनाऊ।",
        "rollback-success": "$1 केर सम्पादन हटाबी। \n$2 केर सम्पादित आखिरी अवतरणक पुनर्स्थापित करल गेल।",
+       "rollback-success-notify": "$1द्वारा पूर्ववत सम्पादन;\n$2द्वारा केल अन्तिम अवतरण पर वापस। [$3 परिवर्तन देखाबी]",
        "sessionfailure-title": "सत्र विफल भ गेल",
        "sessionfailure": "एहन लागैत अछि जे अहां के लागिन सत्र में कोनो त्रुटि अछि. सत्र अपहरण से बचाबय  सं सावधानीक लेल अहां के अहि क्रियाकलाप क रद्द क देल गेल. अहां पाछां के पृष्ठ पर जौउ आ पृष्ठ के फेर सं लोड क दोबारा कोशिश करू.",
-       "protectlogpage": "सुरक्षा लग",
+       "changecontentmodel": "पृष्ठ सामग्री मोडल परिवर्तन करी",
+       "changecontentmodel-legend": "पृष्ठ सामग्रीक नमूना",
+       "changecontentmodel-title-label": "पृष्ठ शीर्षक",
+       "changecontentmodel-model-label": "नव सामग्रीक नमूना",
+       "changecontentmodel-reason-label": "कारण:",
+       "changecontentmodel-submit": "परिवर्तन",
+       "changecontentmodel-success-title": "सामग्री नमूना परिवर्तन भेल",
+       "changecontentmodel-success-text": "[[:$1]]के सामग्रीक प्रकार परिवर्तित भेल।",
+       "changecontentmodel-cannot-convert": "[[:$1]]क सामग्री प्रकार $2 मे नै परिवर्तित केल जा सकल।",
+       "changecontentmodel-nodirectediting": "$1 सामग्री सीधा सम्पादन समर्थित नै करैत अछि",
+       "changecontentmodel-emptymodels-title": "कोनो सामग्री प्रारूप उपलब्ध नै",
+       "changecontentmodel-emptymodels-text": "[[:$1]]मे रहल सामग्री प्रकार परिवर्तित नै केल जा सकत।",
+       "log-name-contentmodel": "सामग्री परिवर्तन लग",
+       "log-description-contentmodel": "आयोजन जे ई पृष्ठक सामग्री सँ एनमेन होए",
+       "logentry-contentmodel-new": "$1द्वारा  $3 पृष्ठक {{GENDER:$2|निर्माण}} कोनो बिना मूल सामग्री प्रारूपके \"$5\"",
+       "logentry-contentmodel-change": "$1द्वारा $3 पृष्ठक सामग्री \"$4\" सँ \"$5\" {{GENDER:$2|परिवर्तित केलक}}",
+       "logentry-contentmodel-change-revertlink": "पूर्ववत करी",
+       "logentry-contentmodel-change-revert": "पूर्ववत करी",
+       "protectlogpage": "सुरक्षा लौग",
        "protectlogtext": "नीचाँ किछु पन्ना सुरक्षा परिवर्तनक सूची अछि।\nदेखू [[Special:ProtectedPages|protected pages list]] लगक कार्यरत पन्ना सुरक्षाकऽ सूची लेल।",
        "protectedarticle": "रक्षित \"[[$1]]\" कएल गेल",
        "modifiedarticleprotection": "\"[[$1]]\" लेल बदलैत रक्षा स्तर",
        "protect-locked-blocked": "अहाँ प्रतिबन्धमे रहि कऽ सुरक्षा स्तर नै बदलि सकै छी।\nएतए पन्ना '''$1''' लेल वर्तमान नियत कएल विकल्प अछि:",
        "protect-locked-dblock": "सक्रिय दत्तनिधि प्रतिबन्धक कारण सुरक्षा स्तर नै बदलल जा सकैए।\nएतए '''$1''' लेल वर्तमान नियत विकल्प देल अछि:",
        "protect-locked-access": "अहाँक खाता अहाँकेँ रक्षा स्तरमे परिवर्तनक अधिकार नै दैत अछि।\nएतए '''$1'''पन्नाक वर्तमान परिस्थिति देल गेल अछि:",
-       "protect-cascadeon": "à¤\88 à¤ªà¤¨à¥\8dना à¤\85à¤\96न à¤°à¤\95à¥\8dषित à¤\85à¤\9bि à¤\95ारण à¤\88 à¤\90 à¤®à¥\87 à¤¸à¤®à¥\8dमिलित à¤\85à¤\9bि {{PLURAL:$1|पनà¥\8dना, à¤\9cà¥\87 à¤\85à¤\9bि|पनà¥\8dना à¤¸à¤­, à¤\9cà¥\87 à¤¸à¤­ à¤\85à¤\9bि}} à¤¤à¤°à¤¾à¤\89पड़à¥\80 à¤°à¤\95à¥\8dषण à¤²à¤¾à¤\97à¥\82।\nà¤\85हाà¤\81 à¤\90 à¤ªà¤¨à¥\8dनाà¤\95 à¤°à¤\95à¥\8dषा à¤¸à¥\8dतरà¤\95à¥\87à¤\81 à¤¬à¤¦à¤²à¤¿ à¤¸à¤\95à¥\88 à¤\9bà¥\80, à¤®à¥\81दा à¤¤à¤¾à¤\87 à¤¸à¤\81 à¤¤à¤°à¤¾à¤\89पड़à¥\80 à¤°à¤\95à¥\8dषापर à¤\85सर à¤¨à¥\88 à¤ªà¤¡à¤¼त।",
+       "protect-cascadeon": "à¤\88 à¤ªà¤¨à¥\8dना à¤\85à¤\96न à¤¸à¤\82रà¤\95à¥\8dषित à¤\85à¤\9bि à¤\95ियाà¤\95à¥\80 à¤\8fहिमà¥\87 {{PLURAL:$1|पनà¥\8dना, à¤\9cà¥\87 à¤\85à¤\9bि|पनà¥\8dना à¤¸à¤­, à¤\9cà¥\87 à¤¸à¤­ à¤\85à¤\9bि}} à¤\95à¥\8dयासà¤\95à¥\87डिà¤\99 à¤¸à¤\82रà¤\95à¥\8dषण à¤¸à¤\95à¥\8dषम à¤\85à¤\9bि।\nà¤\85हाà¤\81 à¤\88 à¤ªà¤¨à¥\8dनाà¤\95 à¤¸à¥\81रà¤\95à¥\8dषा à¤¸à¥\8dतर à¤¬à¤¦à¤²à¤¿ à¤¸à¤\95à¥\88त à¤\9bà¥\80, à¤®à¥\81दा à¤¤à¤¾à¤¹à¤¿ à¤¸à¤\81 à¤\95à¥\8dयासà¤\95à¥\87डिà¤\99 à¤°à¤\95à¥\8dषापर à¤\85सर à¤¨à¥\88 à¤ªà¤¡त।",
        "protect-default": "सभ प्रयोक्ताकेँ अधिकार दएल जाए",
        "protect-fallback": "\"$1\" अधिकार भेल प्रयोक्तासभके अनुमति दएल जाए",
        "protect-level-autoconfirmed": "मात्र स्वत: स्थापित प्रयोक्ताकेँ अनुमति दएल जाए",
        "undeletepagetext": "ई {{PLURAL:$1|page has been deleted but is|$1 pages have been deleted but are}} अखनो जोगाएल पेटारमे अछि आ फेरसँ आनल नै जा सकैए।\nई जोगाएल पेटार बीच-बीचमे साफ करबाक चाही।",
        "undelete-fieldset-title": "संशोधन सभकेँ घुराउ",
        "undeleteextrahelp": "'''''{{int:undeletebtn}}''''' केँ क्लिक करू पन्नाक पूर्ण इतिहास अनबा लेल, सभटा विकल्पबक्सासँ चेन्ह हटाउ।\n'''''{{int:undeletebtn}}''''' क्लिक करू छाँटल मौलिक आकारमे अनबा लेल, संशोधन सभकेँ अनबा लेल सम्बन्धित बक्सा सभमे चेन्ह लगाउ।",
-       "undeleterevisions": "$1{{PLURAL:$1|संशोधन|संशोधन सभ}} पेटारमे जोगाएल",
+       "undeleterevisions": "$1{{PLURAL:$1|संशोधन|संशोधनसभ}} मेटाएल",
        "undeletehistory": "जँ अहाँ पन्नाकेँ फेरसँ अनै छी, सभटा संशोधन पुरान स्तरपर संशोधित भऽ जाएत।\nमेटेलाक बाद जँ एकटा नव पन्ना ओही नामसँ बनाएल गेल, आनल संशोधन सभ पुरान इतिहासमे आएत।",
        "undeleterevdel": "पुनः अननाइ सफल नै हएत जँ ई पन्नाक शीर्ष वा संचिका संशोधनकेँ आंशिक रूपेँ मेटबैए।\nओहेन स्थितिमे, अहाँ सभसँ नव मेटाएल संशोधनक आग्रह खतम कऽ सकै छी वा सोझाँ आनि सकै छी।",
        "undeletehistorynoadmin": "ई पन्ना मेटा देल गेल अछि।\nमेटेबाक कारण नीचाँक सारांशमे देल गेल अछि, प्रयोक्ता विवरणक संग जे ऐ पन्नाकेँ मेटेबासँ पूर्व संशोधित केने छथि।\nऐ मेटाएल संशोधन सभक पाठ मात्र संचालक सभ लग उपलब्ध अछि।",
        "undeletedrevisions": "{{PLURAL:$1|1 revision|$1 revisions}} घुराएल",
        "undeletedrevisions-files": "{{PLURAL:$1|1 संशोधन|$1 संशोधन}} and {{PLURAL:$2|1 संचिका|$2 संचिका}} आनल",
        "undeletedfiles": "{{PLURAL:$1|1 संचिका|$1 संचिका सभ}} आनल",
-       "cannotundelete": "फà¥\87रसà¤\81 à¤¨à¥\88 à¤\86बि à¤¸à¤\95ल:\n$",
+       "cannotundelete": "à¤\95िà¤\9b à¤µà¤¾ à¤¸à¤­ à¤®à¥\87à¤\9fाà¤\8fल à¤µà¤¾à¤ªà¤¿à¤¸ à¤\85सफल:\n$1",
        "undeletedpage": "'''$1 के पुनर्स्थापित करल गेल अछि'''\n\nलग पास में हटाओल गेल आ पुनर्स्थापित कएल गेल पन्ना सभके जानकारी के लेल [[Special:Log/delete|हटाओल गेल लग]] देखु।",
        "undelete-header": "हालक मेटाएल पन्ना के लेल [[Special:Log/delete|हटाएल लग]] देखू।",
        "undelete-search-title": "मेटाएल गेल पृष्ठ ताकी",
        "namespace": "चेन्हासी समूह:",
        "invert": "उनटा चयन",
        "tooltip-invert": "ऐ बक्साकेँ सही करू पन्ना परिवर्तनकेँ नुकेबा लेल चयनित नामस्थानक भीतर (आ संग लागल नामस्थान जँ सही कएल अछि तखन)",
+       "tooltip-whatlinkshere-invert": "चुनल गेल नामस्थान पृष्ठसभ सँ लिङ्कसभ नुकाबैक लेल ई सन्दूकके चिन्हित करी",
        "namespace_association": "सम्बद्ध चेन्हासी",
        "tooltip-namespace_association": "ई बक्साकेँ सही करी जइसँ वार्ता आ विषय नामस्थान समाहित कएल जा सकए चुनल नामस्थानमे",
        "blanknamespace": "(मुख्य)",
        "sp-contributions-newbies-sub": "नब प्रयोक्ताकऽ लेल",
        "sp-contributions-newbies-title": "नब प्रयोक्ताकऽ योगदान",
        "sp-contributions-blocklog": "प्रतिबन्धित वृत्तलेख",
-       "sp-contributions-suppresslog": "मेटाएल प्रयोक्ता योगदान सभ",
-       "sp-contributions-deleted": "प्रयोक्ताकऽ मेटाएल योगदान सभ",
+       "sp-contributions-suppresslog": "{{GENDER:$1|प्रयोगकर्ता}} योगदान दबाबी",
+       "sp-contributions-deleted": "{{GENDER:$1|प्रयोगकर्ता}}क मेटाएल योगदान",
        "sp-contributions-uploads": "उपारोपण",
        "sp-contributions-logs": "वृत्तलेख सभ",
        "sp-contributions-talk": "वार्त्ता",
        "sp-contributions-username": "अनिकेत संकेत वा प्रयोक्तानाम:",
        "sp-contributions-toponly": "मात्र ओइ सम्पादनकेँ देखाउ जे अद्यतन संशोधन छी।",
        "sp-contributions-newonly": "मात्र ओइ सम्पादन देखाउ जे पृष्ठ निर्मित भेल अछि",
+       "sp-contributions-hideminor": "अल्प सम्पादन नुकाबी",
        "sp-contributions-submit": "ताकू",
        "whatlinkshere": "एतय कोन लिङ्क अछि",
        "whatlinkshere-title": "\"$1\" सँ सम्बन्धित पन्नासभ",
        "whatlinkshere-hideredirs": "$1 पुनर्निर्देश",
        "whatlinkshere-hidetrans": "$1 ट्रान्स्क्ल्युजन्स",
        "whatlinkshere-hidelinks": "$1 लिङ्क",
-       "whatlinkshere-hideimages": "$1 à¤«à¤¾à¤\87ल à¤\9cडà¥\80 à¤¸à¤­",
+       "whatlinkshere-hideimages": "$1 à¤«à¤¾à¤\87ल à¤²à¤¿à¤\99à¥\8dà¤\95",
        "whatlinkshere-filters": "चलनीसभ",
+       "whatlinkshere-submit": "जाए",
        "autoblockid": "स्वतःप्रतिबन्धित #$1",
        "block": "प्रयोक्ताकेँ प्रतिबन्धित करू",
-       "unblock": "प्रयोक्ताकेँ प्रतिबन्धसँ हटाउ",
+       "unblock": "प्रयोक्ताकेँ प्रतिबन्ध सँ हटाबी",
        "blockip": "{{GENDER:$1|प्रयोक्ता}}क प्रतिबन्धित करी",
        "blockip-legend": "प्रयोक्ताकेँ प्रतिबन्धित करू",
        "blockiptext": "नीचाँक आवेदनक प्रयोग कोनो खास अनिकेत वा प्रयोक्तानामक लिखैक प्रवेशकेँ प्रतिबन्धित करबा लेल करू।\nई अतत्तः करैबलाक विरुद्ध प्रयुक्त हुअए, आ एकर अनुसार [[{{MediaWiki:Policy-url}}|policy]]।\nनीचाँ स्पष्ट कारण लिखू (जेना, खास पन्नाकेँ देखबैत जतए अतत्तः कएल गेल अछि)।",
        "ipb-unblock": "प्रयोक्ता वा अनिकेतकें अप्रतिबंधित करू",
        "ipb-blocklist": "अखुनका प्रतिबंधित देखू",
        "ipb-blocklist-contribs": "$1 लेल अवदान",
-       "unblockip": "प्रयोक्ताकेँ प्रतिबन्धसँ हटाउ",
+       "ipb-blocklist-duration-left": "$1 बाकी",
+       "unblockip": "प्रयोक्ताकेँ प्रतिबन्ध सँ हटाबी",
        "unblockiptext": "पहिनेसँ प्रतिबन्धित अनिकेत वा प्रयोक्तानामकेँ लिखबाक अधिकार देबा लेल निचुलका आवेदन भरू।",
        "ipusubmit": "ई  प्रतिबन्ध हटाउ",
        "unblocked": "[[User:$1|$1]] अप्रतिबन्धित कएल गेल",
        "block-log-flags-hiddenname": "प्रयोक्तानाम नुकाएल",
        "range_block_disabled": "समूह खण्ड बनेबाक संचालकक क्षमता अशक्त कएल गेल।",
        "ipb_expiry_invalid": "खतम हेबाक समए सही नै अछि।",
+       "ipb_expiry_old": "समाप्ती समय बीत चुकल अछि।",
        "ipb_expiry_temp": "नुकाएल प्रयोक्तानाम खण्ड स्थायी हेबाक चाही।",
        "ipb_hide_invalid": "ऐ खाताकेँ द्बा नै सकलौं; ऐ मे बड्ड बेसी सम्पादन हएत।",
        "ipb_already_blocked": "\"$1\" पहिनहियेसँ प्रतिबन्धित अछि",
        "proxyblockreason": "अहाँक अनिकेत पता प्रतिबन्धित भेल अछि कारण ई सोझे-सोझ दोसराइत अछि।\nअहाँ अपन अन्तर्जाल सेवा दाता वा तकनीकी सहायकसँ सम्पर्क करू आ ऐ गम्भीर सुरक्षा समस्याक सूचना दिअ।",
        "sorbsreason": "अहाँक अनिकेत सूचित अछि सोझे-सोझ दोसराइतक रूपमे {{जालस्थल}} क डी.एन.एस.बी.एल.मे।",
        "sorbs_create_account_reason": "अहाँक अनिकेत एतए सूचित अछि खुजल दोसराइत सन डी.एन.बी.एस.एल. मे जे प्रयोग कएल जाइए {{अन्तर्जाल}} द्वारा।",
+       "xffblockreason": "एक आइपी पता जे एक्स-फरवार्डेड-डर हेडरमे मौजूद छल, या तँ अहाँक छी या ओ प्रक्सी सर्भरक अछि जेकर अहाँ प्रयोग करि रहल छी आ ओहि पर प्रतिबन्ध लगाएल गेल अछि। वास्तविक कारण छल: $1",
        "cant-see-hidden-user": "जै प्रयोक्ताकेँ अहाँ प्रतिबन्धित करऽ चाहै छी से पहिनहियेसँ प्रतिबन्धित आ अदृश्य अछि।\nकारण अहाँ लग प्रयोक्ताकेँ अदृश्य करबाक अधिकार नै अछि, अहाँ प्रयोक्ताक प्रतिबन्धकेँ देख वा सम्पादित नै कऽ सकै छी।",
        "ipbblocked": "अहाँ दोसर प्रयोक्ताकेँ प्रतिबन्धित वा अप्रतिबन्धित नै कऽ सकै छी, कारण अहाँ स्वयं प्रतिबन्धित छी",
        "ipbnounblockself": "अहाँ अपने अप्रतिबन्धित नै भऽ सकै छी",
        "lockdbsuccesstext": "दत्तनिधि प्रतिबन्ध लगाएल गेल| <br />\nमोन राखू [[Special:UnlockDB|remove the lock]]अहांक रखरखाव ख़तम भेलाक बाद ।",
        "unlockdbsuccesstext": "दत्तनिधि अप्रतिबंधित ।",
        "lockfilenotwritable": "दत्तांशनिधि प्रतिबन्ध संचिका लिखबा योग्य नै अछि।\nदत्तांशनिधिकेँ प्रतिबन्धित वा अप्रतिबन्धित करबा लेल एकरा जाल वितरक द्वारा लिखबा योग्य हेबाक चाही।",
+       "databaselocked": "डाटाबेस पहिने सँ बन्द अछि।",
        "databasenotlocked": "दत्तांशनिधि प्रतिबन्धित नै अछि।",
        "lockedbyandtime": "(द्वारा {{GENDER:$1|$1}} केँ $2 बजे $3)",
        "move-page": "$1 स्थानान्तरित करी",
        "move-page-legend": "पृष्ठ स्थानान्तरण",
-       "movepagetext": "नà¥\80à¤\9aाà¤\81à¤\95 à¤«à¥\89रà¥\8dमà¤\95 à¤ªà¥\8dरयà¥\8bà¤\97 à¤ªà¤¨à¥\8dनाà¤\95 à¤¨à¤¾à¤® à¤¬à¤¦à¤²à¤¿ à¤¦à¥\87त, à¤\8fà¤\95र à¤¸à¤­à¤\9fा à¤\87तिहासà¤\95à¥\87à¤\81 à¤¨à¤µ à¤¨à¤¾à¤®à¤\95 à¤\85नà¥\8dतरà¥\8dà¤\97त à¤°à¤¾à¤\96ि à¤¦à¥\87त।\nपà¥\81रान à¤¶à¥\80रà¥\8dषà¤\95 à¤¨à¤µ à¤ªà¤¨à¥\8dना à¤²à¥\87ल à¤\8fà¤\95à¤\9fा à¤\98à¥\81रबà¥\88बला à¤ªà¤¨à¥\8dना à¤¬à¤¨à¤¿ à¤\9cाà¤\8fत।\nà¤\85हाà¤\81 à¤\98à¥\81रबà¥\88बला à¤ªà¤¨à¥\8dनाà¤\95à¥\87à¤\81 à¤\85दà¥\8dयतन à¤\95ऽ à¤¸à¤\95à¥\88 à¤\9bà¥\80 à¤\9cà¥\87 à¤®à¥\82ल à¤¶à¥\80रà¥\8dषà¤\95पर à¤¸à¥\8dवà¤\9aालित à¤°à¥\82पà¥\87à¤\81 à¤\9cाà¤\87त à¤\85à¤\9bि।\nà¤\9cà¥\8cà¤\82 à¤\85हाà¤\81 à¤\88 à¤¨à¥\88 à¤\95रबाà¤\95 à¤¨à¤¿à¤°à¥\8dणय à¤\95रà¥\88 à¤\9bà¥\80, à¤¨à¤¿à¤¶à¥\8dà¤\9aय à¤\95रà¥\82 à¤¤à¤\95बा à¤²à¥\87ल [[Special:DoubleRedirects|double]] à¤µà¤¾\n[[Special:BrokenRedirects|broken redirects]]\nà¤\85हाà¤\81 à¤\90 à¤²à¥\87ल à¤\9cिमà¥\8dमà¥\80दार à¤\9bà¥\80 à¤\9cà¥\87 à¤¸à¤®à¥\8dबनà¥\8dधित à¤²à¤¿à¤\82à¤\95 à¤\93तà¥\88 à¤\9cाà¤\8f à¤\9cतà¤\8f à¤\93à¤\95रा à¤\9cà¥\87बाà¤\95 à¤\9aाहà¥\80।\n\nमà¥\8bन à¤°à¤¾à¤\96à¥\82 à¤\95ि à¤ªà¤¨à¥\8dना '''नà¥\88''' à¤\98सà¤\95ाà¤\89 à¤\9cà¥\8cà¤\82 à¤¨à¤µ à¤¶à¥\80रà¥\8dषà¤\95पर à¤ªà¤¹à¤¿à¤¨à¤¹à¤¿à¤¯à¥\87सà¤\81 à¤ªà¤¨à¥\8dना à¤\85à¤\9bि, à¤\86 à¤¤à¤\96नà¥\87 à¤\88 à¤\95रà¥\82 à¤\9cà¤\96न à¤\93 à¤\96ालà¥\80 à¤¹à¥\81à¤\85à¤\8f à¤µà¤¾ à¤\93 à¤\8fà¤\95à¤\9fा à¤\98à¥\81मबà¥\88बला à¤ªà¤¨à¥\8dना à¤¹à¥\81à¤\85à¤\8f à¤µà¤¾ à¤\93à¤\87 à¤ªà¤¨à¥\8dनाà¤\95 à¤\95à¥\8bनà¥\8b à¤­à¥\82तà¤\95ालà¤\95 à¤¸à¤®à¥\8dपादन à¤\87तिहास à¤¨à¥\88 à¤¹à¥\81à¤\85à¤\8f।\nà¤\8fà¤\95र à¤®à¤¾à¤¨à¥\87 à¤­à¥\87ल à¤\9cà¥\87 à¤\85हाà¤\81 à¤\95à¥\8bनà¥\8b à¤ªà¤¨à¥\8dनाà¤\95 à¤¨à¤¾à¤® à¤ªà¤°à¤¿à¤µà¤°à¥\8dतन à¤\95ऽ à¤ªà¤¾à¤\9bाà¤\81 à¤²à¤½ à¤\9cा à¤¸à¤\95à¥\88 à¤\9bà¥\80 à¤\9cतà¤\8f à¤\8fà¤\95र à¤¨à¤¾à¤®à¤®à¥\87 à¤ªà¤°à¤¿à¤µà¤°à¥\8dतन à¤\95à¤\8fल à¤\97à¥\87ल à¤°à¤¹à¤\8f à¤\9cà¥\8cà¤\82 à¤\85हाà¤\81सà¤\81 à¤\97लतà¥\80 à¤­à¥\87ल à¤\85à¤\9bि, à¤\86 à¤\85हाà¤\81 à¤\93à¤\87 à¤ªà¤¨à¥\8dनाà¤\95à¥\87à¤\81 à¤«à¥\87रसà¤\81 à¤¦à¥\8bबारा à¤¨à¥\88 à¤²à¤¿à¤\96 à¤¸à¤\95à¥\88 à¤\9bà¥\80।\n\n\n'''à¤\9aà¥\87तà¥\8cनà¥\80!'''\nà¤\88 à¤\8fà¤\95à¤\9fा à¤²à¥\8bà¤\95पà¥\8dरिय à¤ªà¤¨à¥\8dनाà¤\95 à¤²à¥\87ल à¤\8fà¤\95à¤\9fा à¤­à¤¯à¤\82à¤\95र à¤\86 à¤¬à¤¿à¤¨à¤¾ à¤\86शाà¤\95 à¤\95à¤\8fल à¤ªà¤°à¤¿à¤µà¤°à¥\8dतन à¤­à¤½ à¤¸à¤\95à¥\88à¤\8f।\nà¤\86à¤\97ाà¤\81 à¤¬à¤¢à¤¼à¥\88सà¤\81 à¤ªà¤¹à¤¿à¤¨à¥\87 à¤\85हाà¤\81 à¤\88 à¤¸à¥\81निशà¥\8dà¤\9aित à¤\95रà¥\82 जे अहाँ एकर परिणाम बुझै छी।",
+       "movepagetext": "नà¥\80à¤\9aाà¤\81à¤\95 à¤«à¤°à¥\8dमà¤\95 à¤ªà¥\8dरयà¥\8bà¤\97 à¤ªà¤¨à¥\8dनाà¤\95 à¤¨à¤¾à¤® à¤¬à¤¦à¤²à¤¿ à¤¦à¥\87त, à¤\8fà¤\95र à¤¸à¤­à¤\9fा à¤\87तिहास à¤¨à¤µ à¤¨à¤¾à¤®à¤\95 à¤\85नà¥\8dतरà¥\8dà¤\97त à¤°à¤¾à¤\96ि à¤¦à¥\87त।\nपà¥\81रान à¤¶à¥\80रà¥\8dषà¤\95 à¤¨à¤µ à¤ªà¤¨à¥\8dना à¤²à¥\87ल à¤\8fà¤\95à¤\9fा à¤ªà¥\81नारà¥\8dनिरà¥\8dदà¥\87शित à¤ªà¤¨à¥\8dना à¤¬à¤¨à¤¿ à¤\9cाà¤\87त।\nà¤\85हाà¤\81 à¤ªà¥\81नरà¥\8dनिरà¥\8dदà¥\87शन à¤ªà¤¨à¥\8dनाà¤\95 à¤\85दà¥\8dयतन à¤\95ऽ à¤¸à¤\95à¥\88 à¤\9bà¥\80 à¤\9cà¥\87 à¤®à¥\82ल à¤¶à¥\80रà¥\8dषà¤\95पर à¤¸à¥\8dवà¤\9aालित à¤°à¥\82पà¥\87à¤\81 à¤\9cाà¤\87त à¤\85à¤\9bि।\nà¤\9cà¥\8cà¤\82 à¤\85हाà¤\81 à¤\88 à¤¨à¥\88 à¤\95रबाà¤\95 à¤¨à¤¿à¤°à¥\8dणय à¤\95रà¥\88 à¤\9bà¥\80, à¤¨à¤¿à¤¶à¥\8dà¤\9aय à¤\95रà¥\80 à¤¤à¤\95बा à¤²à¥\87ल [[Special:DoubleRedirects|बहà¥\81 à¤ªà¥\81नरà¥\8dनिरà¥\8dदà¥\87शन]] à¤µà¤¾\n[[Special:BrokenRedirects|तà¥\81à¤\9fल à¤ªà¥\81नरà¥\8dनिरà¥\8dदà¥\87शन]]\nà¤\85हाà¤\81 à¤\88 à¤²à¥\87ल à¤\9cिमà¥\8dमà¥\87दार à¤\9bà¥\80 à¤\9cà¥\87 à¤¸à¤®à¥\8dबनà¥\8dधित à¤²à¤¿à¤\99à¥\8dà¤\95 à¤\93तà¥\88 à¤\9cाà¤\8f à¤\9cतà¤\8f à¤\93à¤\95रा à¤\9cà¥\87बाà¤\95 à¤\9aाहà¥\80।\n\nमà¥\8bन à¤°à¤¾à¤\96à¥\82 à¤\95ि à¤ªà¤¨à¥\8dना <strong>नà¥\88</strong> à¤¸à¥\8dथानानà¥\8dतरित à¤\9cà¥\8cà¤\82 à¤¨à¤µ à¤¶à¥\80रà¥\8dषà¤\95पर à¤ªà¤¹à¤¿à¤¨à¤¹à¤¿à¤¯à¥\87सà¤\81 à¤ªà¤¨à¥\8dना à¤\85à¤\9bि, à¤\86 à¤¤à¤\96नà¥\87 à¤\88 à¤\95रà¥\80 à¤\9cà¤\96न à¤\93 à¤\96ालà¥\80 à¤¹à¥\81à¤\85à¤\8f à¤µà¤¾ à¤\93 à¤\8fà¤\95à¤\9fा à¤ªà¥\81नरà¥\8dनिरà¥\8dदà¥\87शित à¤ªà¤¨à¥\8dना à¤¹à¥\81à¤\85à¤\8f à¤µà¤¾ à¤\93à¤\87 à¤ªà¤¨à¥\8dनाà¤\95 à¤\95à¥\8bनà¥\8b à¤­à¥\82तà¤\95ालà¤\95 à¤¸à¤®à¥\8dपादन à¤\87तिहास à¤¨à¥\88 à¤¹à¥\81à¤\85à¤\8f।\nà¤\8fà¤\95र à¤®à¤¾à¤¨à¥\87 à¤­à¥\87ल à¤\9cà¥\87 à¤\85हाà¤\81 à¤\95à¥\8bनà¥\8b à¤ªà¤¨à¥\8dनाà¤\95 à¤¨à¤¾à¤® à¤ªà¤°à¤¿à¤µà¤°à¥\8dतन à¤\95ऽ à¤ªà¤¾à¤\9bाà¤\81 à¤²à¤½ à¤\9cा à¤¸à¤\95à¥\88 à¤\9bà¥\80 à¤\9cतà¤\8f à¤\8fà¤\95र à¤¨à¤¾à¤®à¤®à¥\87 à¤ªà¤°à¤¿à¤µà¤°à¥\8dतन à¤\95à¤\8fल à¤\97à¥\87ल à¤°à¤¹à¤\8f à¤\9cà¥\8cà¤\82 à¤\85हाà¤\81सà¤\81 à¤\97लतà¥\80 à¤­à¥\87ल à¤\85à¤\9bि, à¤\86 à¤\85हाà¤\81 à¤\93à¤\87 à¤ªà¤¨à¥\8dनाà¤\95à¥\87à¤\81 à¤«à¥\87रसà¤\81 à¤¦à¥\8bबारा à¤¨à¥\88 à¤²à¤¿à¤\96 à¤¸à¤\95à¥\88 à¤\9bà¥\80।\n\n\n<strong>à¤\9aà¥\87तावनà¥\80!</strong>\nà¤\88 à¤\8fà¤\95à¤\9fा à¤²à¥\8bà¤\95पà¥\8dरिय à¤ªà¤¨à¥\8dनाà¤\95 à¤²à¥\87ल à¤\8fà¤\95à¤\9fा à¤­à¤¯à¤\82à¤\95र à¤\86 à¤¬à¤¿à¤¨à¤¾ à¤\86शाà¤\95 à¤\95à¤\8fल à¤ªà¤°à¤¿à¤µà¤°à¥\8dतन à¤­à¤½ à¤¸à¤\95à¥\88à¤\8f।\nà¤\86à¤\97ाà¤\81 à¤¬à¤¢à¥\88सà¤\81 à¤ªà¤¹à¤¿à¤¨à¥\87 à¤\85हाà¤\81 à¤\88 à¤¸à¥\81निशà¥\8dà¤\9aित à¤\95रà¥\80 जे अहाँ एकर परिणाम बुझै छी।",
        "movepagetext-noredirectfixer": "नीचाँक फॉर्मक प्रयोग पन्नाक नाम बदलि देत, एकर सभटा इतिहासकेँ नव नामक अन्तर्गत राखि देत।\nपुरान शीर्षक नव पन्ना लेल एकटा घुरबैबला पन्ना बनि जाएत।\nनिश्चय करू तकबा लेल [[Special:DoubleRedirects|double]] वा[[Special:BrokenRedirects|broken redirects]]।\nअहाँ ऐ लेल जिम्मीदार छी जे सम्बन्धित लिंक ओतै जाए जतए ओकरा जेबाक चाही।\n\nमोन राखू कि पन्ना '''नै''' घसकत जौं नव शीर्षकपर पहिनहियेसँ पन्ना अछि, आ तखने ई करू जखन ओ खाली हुअए वा ओ एकटा घुमबैबला पन्ना हुअए वा ओइ पन्नाक कोनो भूतकालक सम्पादन इतिहास नै हुअए।\nएकर माने भेल जे अहाँ कोनो पन्नाक नाम परिवर्तन कऽ पाछाँ लऽ जा सकै छी जतए एकर नाममे परिवर्तन कएल गेल रहए जौं अहाँसँ गलती भेल अछि, आ अहाँ ओइ पन्नाकेँ फेरसँ दोबारा नै लिख सकै छी।\n\n\n'''चेतौनी!'''\nई एकटा लोकप्रिय पन्नाक लेल एकटा भयंकर आ बिना आशाक कएल परिवर्तन भऽ सकैए।\nआगाँ बढ़ैसँ पहिने अहाँ ई सुनिश्चित करू जे अहाँ एकर परिणाम बुझै छी।",
        "movepagetalktext": "सम्बन्धित चौबटिया पन्ना स्वचालित रूपेँ घसकत एकर संग '''जौं:'''\n*एकटा खाली-नै चौबटिया पन्ना पहिनहियेसँ नव नामक संग अछि, वा\n*अहाँ नीचाँक बॉक्स टिक हटा दी।\n\nताइ परिस्थितिमे, अहाँकेँ अपनेसँ पन्नाकेँ, आवश्यकतानुसार, घसकाबऽ वा मिज्झर करऽ पड़त।",
        "moveuserpage-warning": "'''चेतौनी!'''अहाँ एकटा प्रयोक्ता पन्ना घसका रहल छी | मोन राखू कि खाली पन्ना घसकत आ प्रयोक्ताक नाम ''नै'' बदलत ।",
        "movenotallowedfile": "अहाँकेँ संचिका सभकेँ घसकेबाक अधिकार नै अछि।",
        "cant-move-user-page": "अहाँकेँ प्रयोक्ता पन्ना सभकेँ घसकेबाक अधिकार नै अछि (उपपन्ना सभकेँ छोड़ि कऽ)।",
        "cant-move-to-user-page": "अहाँकेँ कोनो पन्नाकेँ प्रयोक्ता पन्ना लग घसकेबाक अधिकार नै अछि (प्रयोक्ता उपपन्ना लग छोड़ि कऽ)।",
-       "newtitle": "नव शीर्षकपर:",
+       "newtitle": "नव शीर्षक:",
        "move-watch": "लिङ्क पन्ना आ लक्षित पन्ना देखी",
        "movepagebtn": "नाम परिवर्तन करी",
        "pagemovedsub": "घसकल",
        "movenosubpage": "अहि पन्ना कऽ कोनो उप पन्ना नहि अछि।",
        "movereason": "कारण:",
        "revertmove": "फेरसँ वएह",
-       "delete_and_move_text": "==हटाबैक जरूरत==\nलक्ष्य पृष्ठ \"[[:$1]]\" पहिने सें अस्तित्व में अछि. \nनाम के बदलहि ले की अहां एकरा हटाबय चाहैत छी ?",
+       "delete_and_move_text": "लक्ष्य पृष्ठ \"[[:$1]]\" पहिने सँ अस्तित्वमे अछि।\nअहाँ एकरा स्थानान्तरण करै लेल एकरा मेटाबैलेल चाहै छी?",
        "delete_and_move_confirm": "हँ, पन्ना मेटाउ",
        "delete_and_move_reason": "\"[[$1]]\" सँ घसकेबा लेल जगह बनेबा लेल मेटाएल गेल",
        "selfmove": "स्रोत आ लक्ष्यक शीर्षक एक अछि;\nपृष्ठ अप्पन ठाम पर स्थानांतरित नहि भ सकत.",
        "immobile-target-namespace-iw": "अंतरविकी लिँक पन्ना घसकेबा लेल उचित लक्ष्य नै अछि।",
        "immobile-source-page": "अहि पृष्ठ के अहां कतौ नहि ल जा सकब",
        "immobile-target-page": "ओइ लक्ष्य शीर्षक धरि नै घसका सकल।",
+       "bad-target-model": "वाञ्छित स्थान भिन्न सामग्री नमूनाक प्रयोग करैत अछि। $1 के बदलि $2 नै केल जा सकैत अछि।",
        "imagenocrossnamespace": "संचिकाकेँ गएर संचिका नामस्थान धरि नै लए जा सकल।",
        "nonfile-cannot-move-to-file": "गएर संचिकाकेँ  संचिका नामस्थान धरि नै लए जा सकल।",
        "imagetypemismatch": "नव संचिका विस्तारक अपन प्रकारसँ मेल नै खाइए।",
        "move-leave-redirect": "एक पुनर्निर्देशन पाछा छोडी",
        "protectedpagemovewarning": "''' चेतौनी: ई पन्ना संरक्षित अछि से खाली संचालन अधिकारयुक्त प्रयोक्ता एकरा घुसका सकैत छथि।'''\nनव वृतलेख उल्लेख नीचाँ सन्दर्भ लेल देल जा रहल अछि:",
        "semiprotectedpagemovewarning": "'''नोट:''' ई पन्ना संरक्षित अछि से खाली पंजीकृत प्रयोक्ता एकरा घुसका सकैत छथि।\nनव वृतलेख उल्लेख नीचाँ सन्दर्भ लेल देल जा रहल अछि:",
-       "move-over-sharedrepo": "[[:$1]] अछि एकटा साझी बखारीमे। कोनो संचिकाकेँ ऐ नामसँ अनलापर साझीबला एकटा संचिका मेटा जाएत।",
+       "move-over-sharedrepo": "साझा बखारीमे [[:$1]] अछि। कोनो सञ्चिकाके ई नाम सँ आनलापर एकटा सञ्चिका मेटा जाइत।",
        "file-exists-sharedrepo": "साझी बखारीमे ऐ नामसँ पहिनहियेसँ एकटा संचिका अछि।\nकृपा कऽ दोसर नाम चुनू।",
-       "export": "पनà¥\8dना à¤¸à¤­à¤\95à¥\87à¤\81 à¤ªà¤ à¤¾à¤\89",
+       "export": "पà¥\83षà¥\8dठसभ à¤¨à¤¿à¤°à¥\8dयात à¤\95रà¥\80",
        "exporttext": "अहाँ पाठ आ कोनो पन्ना/ वा पन्ना-सभक सम्पादन इतिहासकेँ दोसर ठाम कोनो एक्स.एम.एल. संचिकामे लपेट कऽ पठा सकै छी।\nई कोनो दोसर विकीमे मीडियाविकीक प्रयोग कऽ [[Special:Import|import page]] द्वारा आयात कएल जा सकैए।\n\nपन्ना सभक निर्यात लेल, नीचाँक पाठ बक्शामे शीर्षक सभ भरू, प्रति पाँती एक शीर्षक, आ चुनू जे अहाँ अखुनका आ पहिलुका सभटा संशोधन राखऽ चाहै छी, पन्ना इतिहास पाँतीक संग, आकि अखुनका संशोधन पछिला सम्पादनक सूचनाक संग।\n\nबादबला स्थितिमे अहाँ एकटा लागिक प्रयोग कऽ सकै छी, जेना \"[[{{MediaWiki:Mainpage}}]]\" पन्ना लेल [[{{#Special:Export}}/{{MediaWiki:Mainpage}}]]।",
        "exportall": "पन्ना सभकेँ निर्यात करू",
        "exportcuronly": "अखुनका संशोधन मात्र लिअ, पूरा इतिहास नै।",
        "export-download": "संचिका रूपमे संरक्षण करू",
        "export-templates": "सभटा नमूना शामिल करू",
        "export-pagelinks": "लागिबला पन्ना सभकेँ एतेक तह धरि राखू:",
+       "export-manual": "स्वयं सँ पृष्ठ जोडी:",
        "allmessages": "प्रणालीक सन्देश",
        "allmessagesname": "नाम",
        "allmessagesdefault": "पूर्वनिर्धारित सन्देश पाठ",
        "djvu_page_error": "डेजावू पन्ना सकक बाहर अछि",
        "djvu_no_xml": "डेजावू संचिकाक एक्स.एम.एल. नै आनि सकलौं",
        "thumbnail-temp-create": "अस्थायी थम्बनेल फाइल बनाबए में असफल",
+       "thumbnail-dest-create": "थम्बनेलके ई स्थान पर सुरक्षित नै केल जा सकैए।",
        "thumbnail_invalid_params": "अमान्य लघुचित्र परिमिति",
+       "thumbnail_toobigimagearea": "सञ्चिका जेकर आकार $1 सँ बेसी अछि।",
        "thumbnail_dest_directory": "लक्ष्य निर्देशिका नै बना सकल",
        "thumbnail_image-type": "चित्र प्रकार समर्थित नै अछि",
        "thumbnail_gd-library": "अपूर्ण जी.डी.पुस्तकालय विन्यास: प्रकार्य $1 अनुपस्थित",
        "import-interwiki-text": "एकटा विकी आ पन्ना शीर्षक आनैलेल चुनू।\nसंशोधन तिथि आ सम्पादकक नाम सुरक्षित रहत।\nसभटा ट्रान्सविकी आयात क्रिया सम्प्रवेशित [[Special:Log/import|आयात लग]] पर रहत।",
        "import-interwiki-sourcewiki": "मूल विकि:",
        "import-interwiki-sourcepage": "मूल पन्ना:",
-       "import-interwiki-history": "à¤\85à¤\8f à¤ªà¤¨à¥\8dनाà¤\95 à¤¸à¤­à¤\9fा à¤\87तिहास à¤¸à¤\82शà¥\8bधनà¤\95 à¤¦à¥\8dवितà¥\80यà¤\95 à¤¬à¤¨à¤¾à¤\89",
-       "import-interwiki-templates": "सभà¤\9fा à¤¨à¤®à¥\82ना à¤¶à¤¾à¤®à¤¿à¤² à¤\95रà¥\82",
-       "import-interwiki-submit": "à¤\86नà¥\82",
+       "import-interwiki-history": "à¤\88 à¤ªà¤¨à¥\8dनाà¤\95 à¤¸à¤­à¤\9fा à¤\87तिहास à¤¸à¤\82शà¥\8bधनà¤\95 à¤\95पà¥\80 à¤\95रà¥\80",
+       "import-interwiki-templates": "सभà¤\9fा à¤\86à¤\95à¥\83ति à¤¶à¤¾à¤®à¤¿à¤² à¤\95रà¥\80",
+       "import-interwiki-submit": "à¤\86यात",
        "import-mapping-default": "पूर्व निर्धारित स्थान सभ पर आयात करी",
        "import-mapping-namespace": "कोनो नामस्थान पर आयात करी",
        "import-mapping-subpage": "निम्न लिखित पृष्ठ के उपपृष्ठ के रूप में आयात करी:",
        "import-nonewrevisions": "सभटा संशोधन पहिनहियेसँ आयातित अछि।",
        "xml-error-string": "$1 पाँतीपर $2, col $3 (byte $4): $5",
        "import-upload": "एक्स.एम.एल. दत्तांश उपारोपित करू",
-       "import-token-mismatch": "à¤\8fà¤\95 à¤\89à¤\96राहाà¤\95 à¤¦à¤¤à¥\8dताà¤\82श à¤\96तम à¤­à¤½ à¤\97à¥\87ल।\nफà¥\87रसà¤\81 à¤ªà¥\8dरयास à¤\95रà¥\82।",
+       "import-token-mismatch": "सà¥\87शन à¤¡à¤¾à¤\9fा à¤¨à¤·à¥\8dà¤\9f à¤­à¥\87ल।\nà¤\85हाà¤\81 à¤¸à¤¾à¤¯à¤¦ à¤²à¤\97 à¤\86à¤\89à¤\9f à¤\95 à¤\97à¥\87ल à¤\9bà¥\80।<strong>à¤\95à¥\83पया à¤\9cाà¤\81à¤\9a à¤\95रà¥\80 à¤\95à¥\80 à¤\85हाà¤\81 à¤¸à¤®à¥\8dपà¥\8dरवà¥\87शित à¤\9bà¥\80</strong>।\nयदि à¤\8fà¤\95र à¤¬à¤¾à¤¦à¥\8b à¤¸à¤«à¤² à¤¨à¥\88 à¤­à¥\87ल à¤¤à¤\81 à¤\95à¥\83पया [[Special:UserLogout|लà¤\97 à¤\86à¤\89à¤\9f]] à¤\95रि à¤ªà¥\81नà¤\83 à¤¸à¤®à¥\8dपà¥\8dरवà¥\87श à¤\95रà¥\80।",
        "import-invalid-interwiki": "विशिष्ट विकीसँ आयात नै कऽ सकै छी।",
        "import-error-edit": "\"$1\" पन्ना आयातित नै कएल गेल अछि कारण अहाँकेँ एकरा सम्पादित करबाक अधिकार नै अछि।",
        "import-error-create": "\"$1\" पन्ना आयातित नै कएल गेल अछि कारण अहाँकेँ एकरा निर्माण करबाक अधिकार नै अछि।",
        "import-error-interwiki": "पृष्ठ \"$1\" आयात नै केल गेल कियाकि एकर नाम अन्तरविकि जडी बनाबै के लेल आरक्षित अछि।",
        "import-error-special": "पृष्ठ \"$1\" आयात नै केल गेल कियाकि इ एक एहन विशेष नामस्थान के अन्तर्गत आबैत अछि जे में पृष्ठ पृष्ठ नै बनाएल जा सकैत अछि।",
        "import-error-invalid": "पृष्ठ \"$1\" आयात नै केल गेल कियाकि इ आयात पश्चात जे नाम रहत यो इ विकी पर अमान्य अछि।",
+       "import-error-unserialize": "पृष्ठ \"$1\" क संशोधन $2के क्रम सँ हटाएल नै जा सकल। संशोधनक बारेमे बताएल गेल अछि की सामग्री नमूना $3 क क्रम $4 के रूप प्रयोगमे लाबल गेल छल।",
        "import-options-wrong": "गलत {{PLURAL:$2|विकल्प}}: <nowiki>$1</nowiki>",
        "import-rootpage-invalid": "दयाल गेल उपसर्ग पन्ना शीर्षक अमान्य अछि ।",
        "import-rootpage-nosubpage": "दयाल गेल उपसर्ग पन्ना \"$1\" के नामस्थान में उप-पन्ना नै बनाबाल जा सकएत अछि ।",
        "tooltip-pt-preferences": "{{GENDER:|अहाँक}} अभिरुचीसभ",
        "tooltip-pt-watchlist": "पन्नासभ जेकर परिवर्तन पर अहाँक नजरि अछि",
        "tooltip-pt-mycontris": "{{GENDER:|अहाँक}} योगदानक सूची",
+       "tooltip-pt-anoncontribs": "ई आइपी पता सँ सम्पादनक सूची",
        "tooltip-pt-login": "अहाँक खाता खोलक लेल प्रोत्साहित कएल जाइत अछि; मुदा ई अनिवार्य नै अछि",
        "tooltip-pt-logout": "फेर आयब",
        "tooltip-pt-createaccount": "अहाँक खाता खोलक लेल प्रोत्साहित कएल जाइत अछि; मुदा ई अनिवार्य नै अछि",
        "tooltip-t-whatlinkshere": "सभ विकी-पन्नाक सूची जकर एतय लिङ्क अछि",
        "tooltip-t-recentchangeslinked": "ई पृष्ठक लगक पन्नामे भेल नव परिवर्तनसभ",
        "tooltip-feed-rss": "ऐ पन्ना लेल आर.एस.एस. सूचना",
-       "tooltip-feed-atom": "à¤\90 à¤ªà¤¨à¥\8dना à¤²à¥\87ल à¤\85णà¥\81 à¤¸à¤®à¤¦à¤¿à¤¯à¤¾",
+       "tooltip-feed-atom": "à¤\88 à¤ªà¥\83षà¥\8dठà¤\95 à¤\8fà¤\9fम à¤«à¤¿à¤¡",
        "tooltip-t-contributions": "ई {{GENDER:$1|प्रयोक्ताक}} योगदानक सूची देखी",
-       "tooltip-t-emailuser": "ई प्रयोगकर्ताक ई-पत्र पठाबी",
+       "tooltip-t-emailuser": "{{GENDER:$1|ई प्रयोगकर्ता}}के इमेल भेजी",
        "tooltip-t-info": "ई पृष्ठ के सम्बन्धमें आर बैंसी जानकारी",
        "tooltip-t-upload": "चित्र आकि मिडिया फाइल अपलोड करी",
-       "tooltip-t-specialpages": "सभà¤\9fा à¤µà¤¿à¤¶à¥\87ष à¤ªà¤¨à¥\8dनाक सूची",
+       "tooltip-t-specialpages": "समà¥\8dपà¥\82रà¥\8dण à¤µà¤¿à¤¶à¥\87ष à¤ªà¤¨à¥\8dनासभक सूची",
        "tooltip-t-print": "ई पृष्ठक छपैबला रूप",
        "tooltip-t-permalink": "पृष्ठक ई संस्करणक स्थायी लिङ्क",
        "tooltip-ca-nstab-main": "सामग्री वाला पृष्ठ देखी",
        "tooltip-ca-nstab-category": "श्रेणी पन्ना देखी",
        "tooltip-minoredit": "एकरा मामली सम्पादन चिन्हित करू",
        "tooltip-save": "अपन परिवर्तन सुरक्षित करी",
+       "tooltip-publish": "परिवर्तन प्रकाशित करी",
        "tooltip-preview": "परिवर्तनक प्रदर्शन, संरक्षण सँ पहिने एकर प्रयोग करी!",
        "tooltip-diff": "ई पाठमे अहाँद्वारा कएल परिवर्तन देखी।",
        "tooltip-compareselectedversions": "ऐ पन्नाक दू टा चयन कएल संशोधनक बीचक अन्तर देखू",
        "pageinfo-article-id": "पन्ना आई॰डी॰",
        "pageinfo-language": "पन्ना सामग्री भाषा",
        "pageinfo-content-model": "पन्ना सामग्री के नमूना",
+       "pageinfo-content-model-change": "परिवर्तन",
        "pageinfo-robot-policy": "बोटद्वारा अनुक्रमण",
        "pageinfo-robot-index": "मान्य",
        "pageinfo-robot-noindex": "अमान्य",
        "pageinfo-watchers": "जानकारक संख्या",
+       "pageinfo-visiting-watchers": "पृष्ठ देखनिहारक सङ्ख्या जे हालक सम्पादनमे आबए।",
        "pageinfo-few-watchers": "$1 स कम ध्यान दीए {{PLURAL:$1|वाला}}",
+       "pageinfo-few-visiting-watchers": "भ सकैत अछि या नै भी कि कियो ई हाल क सम्पादनद्वारा कोनो प्रयोक्ता आएल होए।",
        "pageinfo-redirects-name": "ई पन्नाक पुनर्निर्देशसभ सङ्ख्या",
        "pageinfo-subpages-name": "इ पन्ना के उप-पन्ना",
        "pageinfo-subpages-value": "$1 ($2 {{PLURAL:$2|पुनर्निर्देश}}; $3 {{PLURAL:$3|ग़ैर-पुनर्निर्देश}})",
        "pageinfo-category-files": "फाइल सभके संख्या",
        "markaspatrolleddiff": "जाँच सम्पन्न करी",
        "markaspatrolledtext": "देखि लेल गेल, एहन चिन्ह लगाऊ",
+       "markaspatrolledtext-file": "ई फाइल संस्करणके जांचल चिन्हित करी",
        "markedaspatrolled": "जाँच सम्पन्न करी",
        "markedaspatrolledtext": "[[:$1]]क चयनित अवतरणक जाँच सम्पन्न भेल।",
        "rcpatroldisabled": "हालमे भेल परिवर्तनक परीक्षण अक्षम अछि",
        "svg-long-error": "अमान्य एस॰वी॰जी फ़ाइल: $1",
        "show-big-image": "पूर्ण आनन्तर्य",
        "show-big-image-preview": "ऐ पूर्वदृश्यक आकार: $1.",
+       "show-big-image-preview-differ": "पूर्वावलोकन $3 क आकार $2 फाइल: $1",
        "show-big-image-other": "दोसर {{PLURAL:$2|resolution|resolutions}}: $1।",
        "show-big-image-size": "$1 × $2 चित्राणु",
        "file-info-gif-looped": "घुरियाएल",
        "variantname-zh-sg": "sg",
        "variantname-zh-my": "my",
        "variantname-zh": "zh",
-       "metadata": "पà¥\8dरदतà¥\8dताà¤\82श",
+       "metadata": "मà¥\87à¤\9fाडà¥\87à¤\9fा",
        "metadata-help": "ई फाइल अतिरिक्त सूचना दैत अछि, सम्भवतः ई अंकीय कैमरा वा स्कैनर द्वारा बनाएल वा अंकण कए जोड़ल गेल अछि।\nजौं फाइलकेँ मूल रूपसँ परिवर्धित कएल गेल हएत तँ किछु विवरण पूर्ण रूपसँ परिवर्धित फाइलमे नै देखाएल गेल हएत।",
        "metadata-expand": "बढ़ाओल विवरण देखाउ।",
        "metadata-collapse": "विस्तृत विवरण नुकाउ",
        "confirm-watch-top": "ऐ पन्नाकेँ अपन साकांक्ष सूचीमे जोड़ू",
        "confirm-unwatch-button": "ठीक अछि",
        "confirm-unwatch-top": "ऐ पन्नाकेँ हमर साकांक्ष सूचीसँ हटाउ",
+       "confirm-rollback-button": "ठीक अछि",
+       "confirm-rollback-top": "ई पृष्ठ सम्पादन पूर्ववत करी?",
        "quotation-marks": "\"$1\"",
        "imgmultipageprev": "← पहिलुका पृष्ठ",
        "imgmultipagenext": "अगुलका पृष्ठ →",
        "watchlistedit-raw-done": "अहाँक साकांक्ष-सूची अद्यतन कएल गेल।",
        "watchlistedit-raw-added": "{{PLURAL:$1|1 शीर्षक छल|$1शीर्षक सभ रहए}} जोड़ल गेल:",
        "watchlistedit-raw-removed": "{{PLURAL:$1|1 शीर्षक छल|$1शीर्षक सभ रहए}} हटाएल गेल:",
-       "watchlistedit-clear-title": "साà¤\95ाà¤\82à¤\95à¥\8dष-सà¥\82à¤\9aà¥\80 à¤®à¥\87à¤\9fाà¤\93ल à¤\97à¥\87ल",
+       "watchlistedit-clear-title": "धà¥\8dयानसà¥\82à¤\9aà¥\80 à¤\96ालà¥\80 à¤\95रà¥\80",
        "watchlistedit-clear-legend": "साकांक्ष-सूची मेटाउ",
        "watchlistedit-clear-explain": "एही ठाम रहल सभ शिर्षक अहाँक साकांक्ष-सूची से मेटा जाएत",
        "watchlistedit-clear-titles": "शीर्षक",
        "watchlisttools-edit": "साकांक्षसूची देखी आ सम्पादित करी",
        "watchlisttools-raw": "काँच साकांक्षसूची सम्पादित करी",
        "signature": "[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1|वार्ता]])",
+       "timezone-local": "स्थानीय",
        "duplicate-defaultsort": "'''चेतौनी:''' पूर्वनिर्धारित विन्यास चाभी \"$2\" पहिलुका पूर्वनिर्धारित विन्यास चाभी \"$1\" केँ खतम करैए।",
        "duplicate-displaytitle": "<strong>चेतना:</strong> शीर्षक दिखाबु \"$2\" पूर्व दिखाएल गेल शीर्षक \"$1\" पे हाबी भऽ रहल अछि।",
+       "restricted-displaytitle": "<strong>चेतावनी :</strong> प्रदर्शित शीर्षक \"$1\" नजरअन्दाज केल गेल अछि, कियाकि ई वास्तविक शीर्षक सँ नै मिलैत अछि।",
        "invalid-indicator-name": "<strong>त्रुटि:</strong> पन्ना स्थिति सुचीत <code>नाम</code> गुण खाली नै रहना चाही।",
        "version": "संस्करण",
        "version-extensions": "संस्करणक आगाँ",
        "version-ext-colheader-description": "विवरण",
        "version-ext-colheader-credits": "लेखक",
        "version-license-title": "$1 के लेल अधिकार",
+       "version-license-not-found": "ई एक्सटेन्सनक लेल कोनो विस्तृत लाइसेन्स जानकारी नै भेट सकल।",
        "version-credits-title": "$1 के लेल श्रेय",
+       "version-credits-not-found": "ई एक्सटेन्सनक लेल कोनो विस्तृत श्रेय जानकारी नै भेट सकल।",
        "version-poweredby-credits": "ई विकी चालित अछि '''[https://www.mediawiki.org/ MediaWiki]''', copyright © 2001-$1 $2",
        "version-poweredby-others": "आन",
        "version-poweredby-translators": "translatewiki.net अनुवादक",
        "version-libraries": "स्थापित लाइब्रेरी",
        "version-libraries-library": "लाइब्रेरी",
        "version-libraries-version": "संस्करण",
-       "redirect": "अनुप्रेषित करु फ़ाइल, प्रयोगकर्ता, वा संशोधन पहीचान के आधार में",
-       "redirect-summary": "ई विशेष पन्ना फ़ाइलनाम प्रदान करै पे फ़ाइल नाम के, पन्न आइ॰दी अथवा अवतरण आइ॰दी दुनु पे पन्ना के,आर साथी सदस्य आइ॰दी दुनु पे सदस्य पन्ना के पुनर्प्रेषित करएत अछि । उदाहरण: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/page/64308]], [[{{#Special:Redirect}}/revision/328429]], या [[{{#Special:Redirect}}/user/101]]।",
+       "version-libraries-license": "अनुज्ञापत्र",
+       "version-libraries-description": "विवरण",
+       "version-libraries-authors": "लेखक",
+       "redirect": "फाइल, सदस्य, पृष्ठ, अवतरण या लग आइडीद्वारा अनुप्रेषित",
+       "redirect-summary": "ई विशेष पन्ना फाइलनाम प्रदान करै पर फाइल नामके, पन्न आइडी अथवा अवतरण आइडी दुनु पर पन्नाके, आर साथी सदस्य आइडी दुनु पर सदस्य पन्नाके पुनर्प्रेषित करैत अछि । उदाहरण: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/page/64308]], [[{{#Special:Redirect}}/revision/328429]], या [[{{#Special:Redirect}}/user/101]]।",
        "redirect-submit": "जाए",
        "redirect-lookup": "ताकू:",
        "redirect-value": "मूल्य:",
        "redirect-page": "पन्ना आई॰डी॰",
        "redirect-revision": "पन्ना अवतरण संख्या",
        "redirect-file": "फाइल नाम",
+       "redirect-logid": "प्रवेश आइडी",
        "redirect-not-exists": "बैनर नैं मिल्ल",
        "fileduplicatesearch": "द्वितीयक संचिका ताकू",
        "fileduplicatesearch-summary": "हैश मानक आधारपर द्वितीयक संचिका ताकू।",
        "intentionallyblankpage": "ई पन्ना पलानि कऽ खाली छोड़ल गेल।",
        "external_image_whitelist": "# ऐ पाँतीकेँ एकदम ओहिना छोड़ि दियौ जेना ई अछि<pre>\n# सामान्य वैचारिक खण्ड नीचाँ राखू (// क बीचक खण्ड मात्र)।\n# ई सभ बाहरी (ताजाताजी लागि) चित्रक सार्वत्रिक विभव संकेतसँ मेल खुआएल जाएत\n# ओ सभ जे मेल खाएत से चित्रक रूपमे प्रदर्शित हएत, नै तँ खाली एकटा चित्रक लागि देखाएल जाएत\n# # सँ शुरू भेल पाँती टिप्पणीक रूपमे देखल जाएत।\n# ई ब्रह्मक्षर-लघ्वक्षरक फेरासँ स्वतंत्र अछि।\n\n# सभटा सामान्य कथन ऐ पाँतीसँ ऊपर राखू। ऐ पाँतीकेँ एकदम ओहिना छोड़ू जेना ई अछि </pre>",
        "tags": "मान्य परिवर्तन चेन्ह सभ",
-       "tag-filter": "[[Special:Tags|Tag]] छन्ना:",
+       "tag-filter": "[[Special:Tags|ट्याग]] छन्ना:",
        "tag-filter-submit": "चलनी",
        "tag-list-wrapper": "([[Special:Tags|{{PLURAL:$1|ट्याग|ट्यागसभ}}]]: $2)",
+       "tag-mw-contentmodelchange": "सामग्री परिवर्तन लग",
        "tags-title": "चेन्ह सभ",
        "tags-intro": "ई पन्ना चेन्ह सभकेँ सूचित करैए जे तंत्रांश सम्पादनसँ चिन्हित करए, आ ओकर अर्थ सेहो।",
        "tags-tag": "चेन्हक नाम",
        "tags-actions-header": "क्रिया सभ",
        "tags-active-yes": "हँ",
        "tags-active-no": "नै",
-       "tags-source-extension": "à¤\8fà¤\95à¥\8dसà¤\9fà¥\87नà¥\8dसनद्वारा परिभाषित",
+       "tags-source-extension": "सफà¥\8dà¤\9fवà¥\87यरद्वारा परिभाषित",
        "tags-source-manual": "प्रयोक्तासभ आर बोटद्वारा नियमानुसार लागू",
        "tags-source-none": "आब प्रयोग में नै",
        "tags-edit": "सम्पादन करी",
        "tags-deactivate": "निष्क्रिय करी",
        "tags-hitcount": "$1 {{PLURAL:$1|परिवर्तन|परिवर्तनसभ}}",
        "tags-manage-no-permission": "अहाँकेँ पन्ना घसकेबाक अधिकार नै अछि।",
+       "tags-manage-blocked": "अहाँ प्रतिबन्धित रहैत समय ट्यागमे कोनो जोडए या हटाबैक कार्य नै करि सकैत छी।",
        "tags-create-heading": "एकटा नयाँ विकि-समूह बनाबु",
        "tags-create-explanation": "पुनः निर्धारित रूप से, नवनिर्मित टैग प्रयोगकर्तासभ आर बॉट के लेल हाजीर राहत।",
        "tags-create-tag-name": "चेन्हक नाम:",
        "tags-edit-manage-link": "ट्याग व्यवस्थापन",
        "tags-edit-revision-selected": "[[:$2]] {{PLURAL:$1|क|के}} चयनित अवतरण:",
        "tags-edit-logentry-selected": "{{PLURAL:$1|चुनल वृत्तलेख घटना|चुनल वृत्तलेख घटना सभ}}:",
-       "tags-edit-existing-tags-none": "''कोनो नै''",
+       "tags-edit-existing-tags-none": "<em>कोनो नै</em>",
        "tags-edit-new-tags": "नव ट्याग:",
        "tags-edit-add": "इ ट्यागसभ जोडी:",
        "tags-edit-remove": "इ ट्यागसभ हटाबी:",
        "tags-edit-chosen-placeholder": "किछु ट्याग चुनी",
        "tags-edit-chosen-no-results": "ए नामक ट्याग नै भेटल",
        "tags-edit-reason": "कारण:",
+       "tags-edit-revision-submit": "बदलाव जोडी {{PLURAL:$1|ई अवतरण|$1 अवतरण}}मे",
+       "tags-edit-logentry-submit": "बदलाव जोडी {{PLURAL:$1|ई लग प्रवक्ति|$1 लग प्रवक्तिसभ}}मे",
+       "tags-edit-success": "बदलाव सफलता लागू भेल।",
+       "tags-edit-failure": "परिवर्तन नै जोडल जा सकैत अछि: $1",
+       "tags-edit-nooldid-title": "अमान्य लक्ष्य संशोधन",
        "comparepages": "पन्ना सभक तुलना करू",
        "compare-page1": "पन्ना १",
        "compare-page2": "पन्ना २",
        "compare-title-not-exists": "जे शीर्षक अहाँ कहलौं से अछिये नै।",
        "compare-revision-not-exists": "जे संशोधन अहाँ कहलौं से अछिये नै।",
        "dberr-problems": "दुखी छी! ई जालस्थल तकनीकी समस्या अनुभव कऽ अछि।",
-       "dberr-again": "à¤\95िà¤\9bà¥\81 à¤\95ाल à¤¬à¤¾à¤\9f à¤¤à¤¾à¤\95à¥\82 à¤\86 à¤«à¥\87रसà¤\81 à¤­à¤¾à¤°à¤¿à¤¤ à¤\95रà¥\82।",
+       "dberr-again": "à¤\95िà¤\9bà¥\81 à¤\95ाल à¤°à¥\81à¤\95à¥\80 à¤\86 à¤«à¥\87रसà¤\81 à¤\9cानà¤\95ारà¥\80 à¤­à¤°à¥\80।",
        "dberr-info": "(दत्तनिधि वितरकके सम्पर्क नै कऽ सकल: $1)",
        "dberr-info-hidden": "(दत्तनिधि वितरकके सम्पर्क नै कऽ सकल: $1)",
        "dberr-usegoogle": "ऐ बीचमे अहाँ गूगलसँ खोज कऽ सकै छी।",
        "logentry-newusers-byemail": "$1 द्वारा प्रयोक्ता खाता $3 {{GENDER:$2|बनाओल}} गेल आ कूटशब्द ई-पत्र द्वारा भेजल गेल",
        "logentry-newusers-autocreate": "खाता $1 छल {{GENDER:$2|बनाएल}} स्वतः",
        "logentry-upload-upload": "$1 {{GENDER:$2|ए}} $3 अपलोड केलक",
-       "log-name-tag": "ट्याग लग",
+       "log-name-tag": "à¤\9fà¥\8dयाà¤\97 à¤²à¥\8cà¤\97",
        "rightsnone": "(कोनो नै)",
        "revdelete-summary": "सम्पादन सारांश",
        "feedback-adding": "पन्ना उपर प्रतिक्रिया जोडु ...",
        "expand_templates_remove_comments": "टिप्पणी हटाउ",
        "expand_templates_remove_nowiki": "परिणाम में <nowiki> ट्याग हटाउ",
        "expand_templates_generate_xml": "XML के पार्स (parse) वृक्ष देखाउ",
+       "pagelanguage": "पृष्ठ भाषा परिवर्तन करी",
        "pagelang-name": "पन्ना",
        "pagelang-language": "भाषा",
+       "pagelang-use-default": "डिफल्ट भाषा प्रयोग करी",
        "pagelang-select-lang": "भाषा चुनु",
+       "pagelang-submit": "भेजी",
        "right-pagelang": "पृष्ठ के भाषा परिवर्तन करू",
        "action-pagelang": "पृष्ठ के भाषा परिवर्तन करू",
+       "log-name-pagelang": "भाषा परिवर्तन लग",
+       "log-description-pagelang": "ई पृष्ठ भाषासभमे परिवर्तनक लग छी।",
+       "logentry-pagelang-pagelang": "$1 {{GENDER:$2|बदलि देल गेल}} पृष्ठ भाषा $3 क लेल $4 सँ $5।",
+       "mediastatistics": "मिडिया तथ्याङ्क",
        "special-characters-group-latin": "ल्याटिन",
        "special-characters-group-latinextended": "ल्याटिन विस्तारित",
        "special-characters-group-ipa": "आइपीए",
        "special-characters-group-khmer": "खमेर",
        "special-characters-title-endash": "एन डैश",
        "special-characters-title-emdash": "एम डैश",
-       "special-characters-title-minus": "ऋण चिह्न"
+       "special-characters-title-minus": "ऋण चिह्न",
+       "randomrootpage": "अविशिष्ट मूल पृष्ठ",
+       "log-action-filter-block": "प्रतिबन्धक प्रकार:",
+       "log-action-filter-delete": "मेटबैक प्रकार:",
+       "log-action-filter-import": "आयातक प्रकार:",
+       "log-action-filter-move": "स्थानान्तरणक प्रकार:",
+       "log-action-filter-newusers": "खाता निर्माणक प्रकार:",
+       "log-action-filter-patrol": "परीक्षणक प्रकार:",
+       "log-action-filter-protect": "सुरक्षाक प्रकार:",
+       "log-action-filter-rights": "अधिकार परिवर्तनक प्रकार:",
+       "log-action-filter-all": "सभटा",
+       "log-action-filter-block-block": "अवरोध",
+       "log-action-filter-block-reblock": "अवरोध परिवर्तन",
+       "log-action-filter-block-unblock": "अवरोधरहित",
+       "log-action-filter-contentmodel-change": "सामग्रीक नमूना परिवर्तन"
 }
index f29b73e..bce08c3 100644 (file)
        "eauthentsent": "На назначената адреса е испратена потврдна порака.\nПред да се испрати друга порака на корисничката сметка, ќе морате да ги проследите напатствијата во пораката, за да потврдите дека таа корисничка сметка е навистина ваша.",
        "throttled-mailpassword": "Веќе е испратена порака за измена на лозинката во {{PLURAL:$1|изминатиов час|изминативе $1 часа}}.\nЗа да се спречи злоупотреба, само едно потсетување може да се праќа на {{PLURAL:$1|секој час|секои $1 часа}}.",
        "mailerror": "Грешка при испраќање на е-поштата: $1",
-       "acct_creation_throttle_hit": "Ð\9aоÑ\80иÑ\81ниÑ\86и Ð½Ð° Ð¾Ð²Ð° Ð²Ð¸ÐºÐ¸ ÐºÐ¾Ñ\80иÑ\81Ñ\82еÑ\98Ñ\9cи Ñ\98а Ð²Ð°Ñ\88аÑ\82а IP-адÑ\80еÑ\81а Ñ\81оздале {{PLURAL:$1|1 ÐºÐ¾Ñ\80иÑ\81ниÑ\87ка Ñ\81меÑ\82ка|$1 ÐºÐ¾Ñ\80иÑ\81ниÑ\87ки Ñ\81меÑ\82ки}} Ð²Ð¾ Ð¿Ð¾Ñ\81ледниве Ð´ÐµÐ½Ð¾Ð²Ð¸, при што е достигнат максималниот број на кориснички сметки предвиден и овозможен за овој период.\nКако резултат на ова, посетителите кои ја користат оваа IP-адреса во моментов нема да можат да создаваат нови сметки.",
+       "acct_creation_throttle_hit": "Ð\9fоÑ\81еÑ\82иÑ\82ели Ð½Ð° Ð¾Ð²Ð° Ð²Ð¸ÐºÐ¸ ÐºÐ¾Ñ\80иÑ\81Ñ\82еÑ\98Ñ\9cи Ñ\98а Ð²Ð°Ñ\88аÑ\82а IP-адÑ\80еÑ\81а Ñ\81оздале {{PLURAL:$1|1 Ñ\81меÑ\82ка|$1 Ñ\81меÑ\82ки}} Ð²Ð¾ Ð¿Ð¾Ñ\81ледниве $2, при што е достигнат максималниот број на кориснички сметки предвиден и овозможен за овој период.\nКако резултат на ова, посетителите кои ја користат оваа IP-адреса во моментов нема да можат да создаваат нови сметки.",
        "emailauthenticated": "Вашата е-пошта адреса е потврдена на $2 во $3 ч.",
        "emailnotauthenticated": "Вашата е-поштенска адреса сè уште не е потврдена.\nНема да биде испратена е-пошта во ниту еден од следниве случаи.",
        "noemailprefs": "Наведете е-поштенска адреса за да функционираат следниве својства.",
        "passwordreset-emailelement": "Корисничко име: \n$1\n\nПривремена лозинка: \n$2",
        "passwordreset-emailsentemail": "Ако ова е регистрираната е-пошта поврзана со вашата сметка, тогаш ќе ви биде испратено писмо за задавање на нова лозинка.",
        "passwordreset-emailsentusername": "Ако има соодветна регистрирана е-пошта поврзана со ова корисничко име, тогаш ќе ви биде испратена порака за промена на лозинката.",
-       "passwordreset-emailsent-capture2": "{{PLURAL:$1|Ð\95-поÑ\88Ñ\82аÑ\82а Ð·Ð° Ð·Ð°Ð´Ð°Ð²Ð°Ñ\9aе Ð½Ð° Ð½Ð¾Ð²Ð° Ð»Ð¾Ð·Ð¸Ð½ÐºÐ°|Ð\95-поÑ\88Ñ\82аÑ\82а Ð·Ð° Ð·Ð°Ð´Ð°Ð²Ð°Ñ\9aе Ð½Ð° Ð½Ð¾Ð²Ð¸ Ð»Ð¾Ð·Ð¸Ð½ÐºÐ¸}} Ðµ Ð¸Ñ\81пÑ\80аÑ\82ена. Ð\9fодолÑ\83 е {{PLURAL:$1|е прикажано корисничкото име и лозинката|прикажан список на кориснички имиња и лозинки}}.",
-       "passwordreset-emailerror-capture2": "Ð\98Ñ\81пÑ\80аÑ\9cаÑ\9aеÑ\82о Ðµ-поÑ\88Ñ\82а Ð½Ð° {{GENDER:$2|коÑ\80иÑ\81никоÑ\82}} Ð½Ðµ Ñ\83Ñ\81пеа: $1 Ð\9fодолÑ\83 е {{PLURAL:$3|прикажано корисничкото име и лозинката|прикажан список на кориснички имиња и лозинки}}.",
+       "passwordreset-emailsent-capture2": "{{PLURAL:$1|Ð\95-поÑ\88Ñ\82аÑ\82а Ð·Ð° Ð·Ð°Ð´Ð°Ð²Ð°Ñ\9aе Ð½Ð° Ð½Ð¾Ð²Ð° Ð»Ð¾Ð·Ð¸Ð½ÐºÐ°|Ð\95-поÑ\88Ñ\82аÑ\82а Ð·Ð° Ð·Ð°Ð´Ð°Ð²Ð°Ñ\9aе Ð½Ð° Ð½Ð¾Ð²Ð¸ Ð»Ð¾Ð·Ð¸Ð½ÐºÐ¸}} Ðµ Ð¸Ñ\81пÑ\80аÑ\82ена. Ð¢Ñ\83ка е {{PLURAL:$1|е прикажано корисничкото име и лозинката|прикажан список на кориснички имиња и лозинки}}.",
+       "passwordreset-emailerror-capture2": "Ð\98Ñ\81пÑ\80аÑ\9cаÑ\9aеÑ\82о Ðµ-поÑ\88Ñ\82а Ð½Ð° {{GENDER:$2|коÑ\80иÑ\81никоÑ\82}} Ð½Ðµ Ñ\83Ñ\81пеа: $1 Ð¢Ñ\83ка е {{PLURAL:$3|прикажано корисничкото име и лозинката|прикажан список на кориснички имиња и лозинки}}.",
        "passwordreset-nocaller": "Мора да се укаже повикувач",
        "passwordreset-nosuchcaller": "Повикувачот не постои: $1",
        "passwordreset-ignored": "Менувањето на лозинката не успеа. Можеби не е поставен услужник?",
        "upload-dialog-disabled": "Подигањето на податотеки со помош на овој дијалог е оневозможено на ова вики.",
        "upload-dialog-title": "Подигни податотека",
        "upload-dialog-button-cancel": "Откажи",
+       "upload-dialog-button-back": "Назад",
        "upload-dialog-button-done": "Готово",
        "upload-dialog-button-save": "Зачувај",
        "upload-dialog-button-upload": "Подигни",
        "htmlform-cloner-create": "Додај уште",
        "htmlform-cloner-delete": "Отстрани",
        "htmlform-cloner-required": "Се бара барем една вредност.",
+       "htmlform-date-placeholder": "ГГГГ-ММ-ДД",
+       "htmlform-time-placeholder": "ЧЧ:ММ:СС",
+       "htmlform-datetime-placeholder": "ГГГГ-ММ-ДД ЧЧ:ММ:СС",
+       "htmlform-date-invalid": "Не можам да ја препознаам внесената вредност. Користете го форматот ГГГГ-ММ-ДД.",
+       "htmlform-time-invalid": "Не можам да ја препознаам внесената вредност за време. Користете го форматот ЧЧ:ММ:СС.",
+       "htmlform-datetime-invalid": "Не можам да ја препознаам внесената вредност за датум и време. Користете го форматот ГГГГ-ММ-ДД ММ:СС.",
+       "htmlform-date-toolow": "Укажаната вредност е пред најраниот допуштен датум — $1.",
+       "htmlform-date-toohigh": "Укажаната вредност е по најдоцниот допуштен датум — $1.",
+       "htmlform-time-toolow": "Укажаната вредност е пред најраното допуштено време — $1.",
+       "htmlform-time-toohigh": "Укажаната вредност е по најдоцното допуштено време — $1.",
+       "htmlform-datetime-toolow": "Укажаната вредност е пред најраниот допуштен датум и време — $1.",
+       "htmlform-datetime-toohigh": "Укажаната вредност е по најдоцниот допуштен датум и време — $1.",
        "htmlform-title-badnamespace": "[[:$1]] не се наоѓа во именскиот простор „{{ns:$2}}“.",
        "htmlform-title-not-creatable": "Насловот „$1“ не може да се создава",
        "htmlform-title-not-exists": "$1 не постои.",
        "unlinkaccounts-success": "Сметката е одврзана.",
        "authenticationdatachange-ignored": "Промената на податоците во заверката не е обработена. Можеби не е поставен услужник?",
        "userjsispublic": "Напомена: потстраниците со JavaScript не треба да содржат дсоверливи податоци бидејќи истите се видливи и за други корисници.",
-       "usercssispublic": "Напомена: потстраниците со CSS не треба да содржат дсоверливи податоци бидејќи истите се видливи и за други корисници."
+       "usercssispublic": "Напомена: потстраниците со CSS не треба да содржат дсоверливи податоци бидејќи истите се видливи и за други корисници.",
+       "restrictionsfield-badip": "Неважечки IP-дијапазон на адреси: $1",
+       "restrictionsfield-label": "Допуштени IP-опсези:",
+       "restrictionsfield-help": "Една IP-адреса или CIDR-опсег по ред. За да овозможите сè, користете<br><code>0.0.0.0/0</code><br><code>::/0</code>"
 }
index 533ebef..11c42a1 100644 (file)
@@ -77,7 +77,7 @@
        "tog-enotifminoredits": "मला पानांच्या आणि संचिकांच्या छोट्या बदलांकरीता सुद्धा विरोप पाठवा",
        "tog-enotifrevealaddr": "सूचना विरोपात माझा विरोपाचा (ई-मेल ) पत्ता दाखवा",
        "tog-shownumberswatching": "पहारा देणाऱ्या सदस्यांचा आकडा दाखवा",
-       "tog-oldsig": "सध्याची सही:",
+       "tog-oldsig": "à¤\86पलà¥\80 à¤¸à¤§à¥\8dयाà¤\9aà¥\80 à¤¸à¤¹à¥\80:",
        "tog-fancysig": "सही विकिसंज्ञा म्हणून वापरा (आपोआप दुव्याशिवाय)",
        "tog-uselivepreview": "सजीव झलक दाखवा",
        "tog-forceeditsummary": "जर ’बदलांचा आढावा’ दिला नसेल तर मला सूचित करा",
@@ -94,7 +94,7 @@
        "tog-showhiddencats": "लपविलेले वर्ग दाखवा",
        "tog-norollbackdiff": "द्रुतमाघार घेतल्यास बदल वगळा",
        "tog-useeditwarning": "जर मी संपादित करीत असलेल्या पानावरील माझे संपादिलेले बदल जतन न केल्यास मला इशारा द्या",
-       "tog-prefershttps": "सनोंद प्रवेशतांना प्रत्येक वेळी  सुरक्षित अनुबंध वापरा",
+       "tog-prefershttps": "सनà¥\8bà¤\82द à¤ªà¥\8dरवà¥\87शित à¤\85सताà¤\82ना à¤ªà¥\8dरतà¥\8dयà¥\87à¤\95 à¤µà¥\87ळà¥\80  à¤¸à¥\81रà¤\95à¥\8dषित à¤\85नà¥\81बà¤\82ध à¤µà¤¾à¤ªà¤°à¤¾",
        "underline-always": "नेहमी",
        "underline-never": "कधीच नाही",
        "underline-default": "त्वचा अथवा न्याहाळक अविचल (स्कीन अथवा ब्राऊजर डिफॉल्ट)",
        "category-file-count-limited": "खालील {{PLURAL:$1|संचिका|$1 संचिका}} या वर्गात आहेत.",
        "listingcontinuesabbrev": "पुढे चला",
        "index-category": "अनुक्रमित पाने",
-       "noindex-category": "à¤\85नà¥\81à¤\95à¥\8dरम à¤¨à¤¸à¤²à¥\87लà¥\80 पाने",
+       "noindex-category": "विना-à¤\85नà¥\81à¤\95à¥\8dरमित पाने",
        "broken-file-category": "तुटलेल्या संचिका दुव्यांसह असलेली पाने",
        "about": "च्या विषयी",
        "article": "आशयाचे पान",
        "newwindow": "(नवीन खिडकीत उघडते.)",
        "cancel": "रद्द करा",
        "moredotdotdot": "अजून...",
-       "morenotlisted": "हà¥\80 à¤¯à¤¾à¤¦à¥\80 à¤ªà¥\82रà¥\8dण à¤¨à¤¾à¤¹à¥\80.",
+       "morenotlisted": "हà¥\80 à¤¯à¤¾à¤¦à¥\80 à¤\85पà¥\82रà¥\8dण à¤\85सà¥\82 à¤¶à¤\95तà¥\87.",
        "mypage": "पान",
        "mytalk": "चर्चा",
        "anontalk": "चर्चा पान",
        "talk": "चर्चा",
        "views": "दृष्ये",
        "toolbox": "साधने",
+       "tool-link-emailuser": "{{GENDER:$1|सदस्याला}} विपत्र पाठवा",
        "userpage": "सदस्य पृष्ठ",
        "projectpage": "प्रकल्प पान पहा",
        "imagepage": "संचिका पृष्ठ पहा",
        "createacct-yourpasswordagain-ph": "पुन्हा परवलीचा शब्द टाका",
        "userlogin-remembermypassword": "मला नोंदीकृतच(लॉग्ड-ईन) ठेवा",
        "userlogin-signwithsecure": "सुरक्षित अनुबंध(सेक्युअर कनेक्शन) वापरा",
+       "cannotlogin-title": "सनोंद प्रवेश करु शकत नाही",
        "cannotloginnow-title": "आता सनोंद प्रवेश घेऊ शकत नाही",
        "cannotloginnow-text": "$1 वापरत असतांना सनोंद प्रवेश करणे शक्य नाही.",
        "yourdomainname": "तुमचे क्षेत्र (डोमेन) :",
        "eauthentsent": "नमूद केलेल्या ई-मेल पत्त्यावर एक निश्चितता स्वीकारक ई-मेल पाठविला गेला आहे.\nखात्यावर कोणताही इतर ई-मेल पाठविण्यापूर्वी - तो ई-मेल पत्ता तुमचाच आहे, हे सुनिश्चित करण्यासाठी - तुम्हाला त्या ई-मेल मधील सूचनांचे पालन करावे लागेल.",
        "throttled-mailpassword": "मागील {{PLURAL:$1|तासात|$1 तासांत}} परवलीचा शब्द बदलण्यासाठीची सूचना विपत्राद्वारे पाठविलेली आहे. दुरुपयोग टाळण्यासाठी, {{PLURAL:$1|एका तासामध्ये|$1 तासांमध्ये}} फक्त एकदाच सूचना दिली जाईल.",
        "mailerror": "विपत्र पाठवण्यात त्रुटी: $1",
-       "acct_creation_throttle_hit": "à¤\86पला à¤\85à¤\82à¤\95पतà¥\8dता à¤µà¤¾à¤ªà¤°à¥\81न à¤¯à¤¾ à¤µà¤¿à¤\95िस à¤­à¥\87à¤\9f à¤¦à¥\87णाऱà¥\8dयाà¤\82नà¥\80 à¤\95ाल {{PLURAL:$1|१ à¤\96ातà¥\87|$1 à¤\96ातà¥\80}} à¤\89à¤\98डलà¥\80 à¤\86हà¥\87त à¤¤à¥\80 à¤¯à¤¾ à¤\95ालावधà¥\80तà¥\80ल à¤®à¤¹à¤¤à¥\8dतम à¤\86हà¥\87त.\n\nतà¥\8dयाà¤\9aा à¤ªà¤°à¤¿à¤ªà¤¾à¤\95 à¤®à¥\8dहणà¥\82न à¤¸à¤§à¥\8dया à¤¹à¤¾ à¤\85à¤\82à¤\95पतà¥\8dता à¤µà¤¾à¤ªà¤°à¥\81न à¤­à¥\87à¤\9f à¤¦à¥\87णाऱà¥\8dयास अधिक खाते उघडता येणार नाहीत.",
+       "acct_creation_throttle_hit": "à¤\86पला à¤\85à¤\82à¤\95पतà¥\8dता à¤µà¤¾à¤ªà¤°à¥\81न à¤¯à¤¾ à¤µà¤¿à¤\95िस à¤­à¥\87à¤\9f à¤¦à¥\87णाऱà¥\8dयाà¤\82नà¥\80 à¤®à¤¾à¤\97à¥\80ल $2 à¤®à¤§à¥\8dयà¥\87 {{PLURAL:$1|१ à¤\96ातà¥\87|$1 à¤\96ातà¥\80}} à¤\89à¤\98डलà¥\80 à¤\86हà¥\87त à¤¤à¥\80 à¤¯à¤¾ à¤\95ालावधà¥\80तà¥\80ल à¤®à¤¹à¤¤à¥\8dतम à¤\86हà¥\87त.\n\nतà¥\8dयाà¤\9aा à¤ªà¤°à¤¿à¤ªà¤¾à¤\95 à¤®à¥\8dहणà¥\82न à¤¸à¤§à¥\8dया à¤¹à¤¾ à¤\85à¤\82à¤\95पतà¥\8dता à¤µà¤¾à¤ªà¤°à¥\81न à¤­à¥\87à¤\9f à¤¦à¥\87णाऱà¥\8dयाला अधिक खाते उघडता येणार नाहीत.",
        "emailauthenticated": "तुमचा विपत्रपत्ता $2 ला $3 यावेळी तपासण्यात आला आहे.",
        "emailnotauthenticated": "तुमच्या ई-मेल पत्त्याची अद्याप निश्चिती झालेली नाही. खालील कोणत्याही फिचर्ससाठी ई-मेल पाठविला जाणार नाही.",
        "noemailprefs": "खालील सुविधा कार्यान्वित करण्यासाठी,पसंतीक्रमात ई-मेल पत्ता नमूद करा.",
        "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\" हे सांगकाम्याचे नाव जोडण्यात अयशस्वी. ते पूर्वीच जोडले होते काय?",
        "upload-dialog-disabled": "हा डायलॉग वापरून  या विकिवर संचिका अपभारण अक्षम केले आहे.",
        "upload-dialog-title": "संचिकेचे अपभारण करा",
        "upload-dialog-button-cancel": "रद्द करा",
+       "upload-dialog-button-back": "परत जा",
        "upload-dialog-button-done": "झाले",
        "upload-dialog-button-save": "जतन करा",
        "upload-dialog-button-upload": "अपभारण करा",
        "pageinfo-article-id": "पृष्ठ-परिचय",
        "pageinfo-language": "पानाच्या मजकूराची भाषा",
        "pageinfo-content-model": "पान आशय नमूना",
+       "pageinfo-content-model-change": "बदला",
        "pageinfo-robot-policy": "यंत्रमानवाद्वारे अनुक्रमन",
        "pageinfo-robot-index": "अनुमती दिली",
        "pageinfo-robot-noindex": "अनुमती दिल्या जात नाही",
        "htmlform-cloner-create": "अधिक जोडा",
        "htmlform-cloner-delete": "हटवा",
        "htmlform-cloner-required": "किमान एक किंमत हवी",
+       "htmlform-date-placeholder": "वववव-मम-दिदि",
+       "htmlform-time-placeholder": "ताता:मिमि:सेसे",
+       "htmlform-datetime-placeholder": "वववव-मम-दिदि ताता:मिमि:सेसे",
+       "htmlform-date-invalid": "आपण नमूद केलेली किंमत ही अनोळखी दिनांक आहे. वववव-मम-दिदि प्रारुपणाचा वापर करण्याबाबत विचार करा.",
+       "htmlform-time-invalid": "आपण नमूद केलेली किंमत ही अनोळखी आहे. ताता:मिमि:सेसे प्रारुपणाचा वापर करण्याबाबत विचार करा.",
+       "htmlform-datetime-invalid": "आपण नमूद केलेली किंमत ही अनोळखी दिनांक व वेळ आहे. वववव-मम-दिदि ताता:मिमि:सेसे प्रारुपणाचा वापर करण्याबाबत विचार करा.",
+       "htmlform-time-toohigh": "आपण नमूद केलेली किंमत ही $1च्या परवानगी असलेल्या वेळ मर्यादेबाहेर आहे.",
+       "htmlform-datetime-toohigh": "आपण नमूद केलेली किंमत ही $1च्या परवानगी असलेल्या दिनांक व वेळ मर्यादेबाहेर आहे.",
        "htmlform-title-badnamespace": "[[:$1]] हे \"{{ns:$2}}\" नामविश्वात नाही.",
        "htmlform-title-not-creatable": "\"$1\" हे पान तयार करण्यासाठीचे शीर्षक नाही",
        "htmlform-title-not-exists": "$1 अस्तीत्वात नाही.",
        "htmlform-user-not-exists": "<strong>$1</strong> अस्तीत्वात नाही.",
        "htmlform-user-not-valid": "<strong>$1</strong> हे वैध सदस्यनाम नाही.",
-       "sqlite-has-fts": "पूर्ण-मजकूर शोध समर्थनासहित $1",
-       "sqlite-no-fts": "पूर्ण-मजकूर शोध समर्थनाविरहित $1",
        "logentry-delete-delete": "$1 {{GENDER:$2|वगळलेले पान}} $3",
        "logentry-delete-restore": "$1 {{GENDER:$2|पुनर्स्थापित पृष्ठ}} $3",
        "logentry-delete-event": "$1 ने $3 वर{{PLURAL:$5|नोंद-प्रसंग|$5 नोंद प्रसंगांची}} दृष्यता{{GENDER:$2|बदलली}}:$4",
index d60887a..6e71765 100644 (file)
@@ -11,7 +11,8 @@
                        "아라",
                        "Fitoschido",
                        "Taresi",
-                       "Macofe"
+                       "Macofe",
+                       "Akapochtli"
                ]
        },
        "tog-underline": "Mokìnxòîkuilòtzàswis tzòwilistìn:",
        "returnto": "Ximocuepa īhuīc $1.",
        "tagline": "Īhuīcpa {{SITENAME}}",
        "help": "Tēpalēhuiliztli",
-       "search": "Mà motèmo",
+       "search": "Nican tictemoz",
        "searchbutton": "Tictēmōz",
        "go": "Xiyauh",
        "searcharticle": "Xiyauh",
        "unprotectthispage": "Xicpatla inīn tlaīxtli ītlapiyaliz",
        "newpage": "Yancuic tlaīxtli",
        "talkpage": "Xictlahto inīn tlaīxtli ītechcopa",
-       "talkpagelinktext": "Nenônòtzalistli",
+       "talkpagelinktext": "Nenonotzaliztli",
        "specialpage": "Nònkuâkìskàtlaìxtlapalli",
        "personaltools": "In tlein nitēquitiltilia",
        "articlepage": "Xiquitta in tlamantlaīxtli",
        "userlogin-yourname": "Tequihuihcātōcāitl",
        "yourpassword": "Motlahtōlichtacāyo",
        "yourpasswordagain": "Motlahtōlichtacāyo occeppa",
-       "remembermypassword": "Ticpiyāz motlacalaquiliz inīn chīuhpōhualhuazco (īxquich {{PLURAL:$1|tōnalli}})",
        "yourdomainname": "Moāxcāyō",
        "login": "Xicalaqui",
        "nav-login-createaccount": "Ximocalaqui / ximomachiyōmaca",
index 7f12e86..151f629 100644 (file)
        "talk": "Diskusjon",
        "views": "Visninger",
        "toolbox": "Verktøy",
+       "tool-link-userrights": "Endre {{GENDER:$1|brukergrupper}}",
+       "tool-link-emailuser": "Send {{GENDER:$1|brukeren}} en e-post",
        "userpage": "Vis brukerside",
        "projectpage": "Vis prosjektside",
        "imagepage": "Vis filside",
        "eauthentsent": "En bekreftelsesmelding ble sendt til oppgitt e-postadresse. Før andre e-poster kan sendes til kontoen må du følge instruksjonene i e-posten for å bekrefte at kontoen faktisk er din.",
        "throttled-mailpassword": "En passordtilbakestillingsepost har allerede blitt sendt for mindre enn {{PLURAL:$1|en time|$1 timer}} siden.\nFor å forhindre misbruk kan kun én passordtilbakestillingsepost sendes per {{PLURAL:$1|time|$1 timer}}.",
        "mailerror": "Feil under sending av e-post: $1",
-       "acct_creation_throttle_hit": "Gjester med samme IP-adresse som deg har opprettet {{PLURAL:$1|én konto|$1 kontoer}} det siste døgnet, og det er ikke tillatt å opprette flere.\nSom et resultat kan det ikke opprettes flere kontoer fra denne IP-adressen.",
+       "acct_creation_throttle_hit": "Gjester med samme IP-adresse som deg har opprettet {{PLURAL:$1|én konto|$1 kontoer}} i løpet av $2, og det er ikke tillatt å opprette flere.\nSom et resultat kan det for tiden ikke opprettes flere kontoer fra denne IP-adressen.",
        "emailauthenticated": "Din e-postadresse ble bekreftet den $2 kl. $3.",
        "emailnotauthenticated": "Din e-postadresse er ikke bekreftet. Du vil ikke kunne motta e-post for noen av følgende egenskaper.",
        "noemailprefs": "Oppgi en e-postadresse for at disse funksjonene skal fungere.",
        "passwordreset-emailelement": "Brukernavn: \n$1\n\nMidlertidig passord: \n$2",
        "passwordreset-emailsentemail": "Hvis denne epostadressen er koblet til din konto, så vil det bli sendt en epost om tilbakestilling av passord.",
        "passwordreset-emailsentusername": "Hvis det finnes en epostadresse knyttet til dette brukernavnet, vil en epost med informasjon om tilbakestilling av passord bli sendt.",
-       "passwordreset-emailsent-capture2": "{{PLURAL:$1|E-post}} om passordtilbakestilling har blitt sendt. {{PLURAL:$1|Brukernavnet og passordet|Listen over brukernavn og passord}} vises under.",
-       "passwordreset-emailerror-capture2": "Kunne ikke sende e-post til {{GENDER:$2|brukeren}}: $1 {{PLURAL:$3|Brukernavnet og passordet|Listen over brukernavn og passord}} vises under.",
+       "passwordreset-emailsent-capture2": "{{PLURALS:$1|E-posten|E-postene}} om passordtilbakestilling har blitt sendt. {{PLURAL:$1|Brukernavnet og passordet|Listen over brukernavn og passord}} vises under.",
+       "passwordreset-emailerror-capture2": "Kunne ikke sende e-post til {{GENDER:$2|brukeren}}: $1 {{PLURAL:$3|Brukernavnet og passordet|Listen over brukernavn og passord}} vises her.",
        "passwordreset-nocaller": "En bruker må angis",
        "passwordreset-nosuchcaller": "Brukeren finnes ikke: $1",
        "passwordreset-ignored": "Passordtilbakestillingen ble ikke håndtert. Har ingen leverandør blitt konfigurert?",
        "listusers": "Brukerliste",
        "listusers-editsonly": "Vis bare brukere med redigeringer",
        "listusers-creationsort": "Sorter etter opprettelsesdato",
-       "listusers-desc": "Sorter i avtakende rekkefølge",
+       "listusers-desc": "Sorter i synkende rekkefølge",
        "usereditcount": "{{PLURAL:$1|én redigering|$1 redigeringer}}",
        "usercreated": "{{GENDER:$3|Opprettet}} $2 $1",
        "newpages": "Nye sider",
        "nopagetext": "Siden du ville flytte finnes ikke.",
        "pager-newer-n": "{{PLURAL:$1|1 nyere|$1 nyere}}",
        "pager-older-n": "{{PLURAL:$1|1 eldre|$1 eldre}}",
-       "suppress": "Historikkrydding",
+       "suppress": "Undertrykk",
        "querypage-disabled": "Denne spesialsiden er deaktivert av ytelsesårsaker.",
        "apihelp": "API hjelp",
        "apihelp-no-such-module": "Modulen «$1» ikke funnet.",
        "sp-contributions-newbies-sub": "For nybegynnere",
        "sp-contributions-newbies-title": "Bidrag av nye kontoer",
        "sp-contributions-blocklog": "blokkeringslogg",
-       "sp-contributions-suppresslog": "undertrykte brukerbidrag",
+       "sp-contributions-suppresslog": "undertrykte {{GENDER:$1|brukerbidrag}}",
        "sp-contributions-deleted": "slettede {{GENDER:$1|brukerbidrag}}",
        "sp-contributions-uploads": "opplastinger",
        "sp-contributions-logs": "logger",
        "tags-deactivate-not-allowed": "Det er ikke mulig å deaktivere taggen «$1».",
        "tags-deactivate-submit": "Deaktiver",
        "tags-apply-no-permission": "Du har ikke tilgang til å legge til merker sammen med dine endringer.",
+       "tags-apply-blocked": "Du kan ikke bruke endringstagger med endringene dine mens du er blokkert.",
        "tags-apply-not-allowed-one": "Merket «$1» kan ikke legges til manuelt.",
        "tags-apply-not-allowed-multi": "{{PLURAL:$2|Det følgende merket|De følgende merkene}} kan ikke legges til manuelt: $1",
        "tags-update-no-permission": "Du har ikke tilgang til å legge til eller fjerne merker fra individuelle revisjoner eller loggposter.",
        "log-action-filter-patrol": "Type patruljering:",
        "log-action-filter-protect": "Type beskyttelse:",
        "log-action-filter-rights": "Type rettighetsendring:",
+       "log-action-filter-suppress": "Type undertrykking:",
        "log-action-filter-upload": "Type opplasting:",
        "log-action-filter-all": "Alle",
        "log-action-filter-block-block": "Blokkering",
        "log-action-filter-protect-move_prot": "Flyttingsbeskyttelse",
        "log-action-filter-rights-rights": "Manuell endring",
        "log-action-filter-rights-autopromote": "Automatisk endring",
+       "log-action-filter-suppress-event": "Loggundertrykking",
+       "log-action-filter-suppress-revision": "Revisjonsundertrykking",
+       "log-action-filter-suppress-delete": "Sideundertrykking",
+       "log-action-filter-suppress-block": "Brukerundertrykking ved blokkering",
+       "log-action-filter-suppress-reblock": "Brukerundertrykking ved gjenblokkering",
        "log-action-filter-upload-upload": "Ny opplasting",
        "log-action-filter-upload-overwrite": "Gjenopplasting",
        "authmanager-authn-not-in-progress": "Autentisering foregår ikke eller sesjonsdata er tapt. Start igjen fra begynnelsen.",
        "linkaccounts-submit": "Lenk kontoer",
        "unlinkaccounts": "Fjern lenking av kontoer",
        "unlinkaccounts-success": "Kontoens lenking ble fjernet.",
+       "authenticationdatachange-ignored": "Autentiseringsdataendringen ble ikke håndtert. Muligens ble ingen tilbyder konfigurert?",
        "userjsispublic": "Merk: JavaScript-undersidene bør ikke inneholde konfidensielle data, siden de kan ses av andre brukere.",
-       "usercssispublic": "Merk: CSS-undersidene bør ikke inneholde konfidensielle data siden de kan ses av andre brukere."
+       "usercssispublic": "Merk: CSS-undersidene bør ikke inneholde konfidensielle data siden de kan ses av andre brukere.",
+       "restrictionsfield-badip": "Ugyldig IP-adresse eller intervall: $1",
+       "restrictionsfield-label": "Tillatte IP-intervaller:",
+       "restrictionsfield-help": "Én IP-adresse eller CIDR-intervall per linje. For å slå på alt, bruk <br /><code>0.0.0.0/0</code><br /><code>::/0</code>"
 }
index b1cc3eb..9839755 100644 (file)
        "recentchangeslinked-page": "Paginanaam:",
        "recentchangeslinked-to": "Wijzigingen aan pagina's met koppelingen naar deze pagina bekijken",
        "recentchanges-page-added-to-category": "[[:$1]] aan categorie toegevoegd",
-       "recentchanges-page-added-to-category-bundled": "[[:$1]] en [[Special:WhatLinksHere/$1|{{PLURAL:$2|één pagina|$2 pagina's}}]] zijn toegevoegd aan categorie",
+       "recentchanges-page-added-to-category-bundled": "[[:$1]] is toegevoegd aan de categorie, [[Special:WhatLinksHere/$1|deze pagina is opgenomen in andere pagina's]]",
        "recentchanges-page-removed-from-category": "[[:$1]] is verwijderd uit categorie",
-       "recentchanges-page-removed-from-category-bundled": "[[:$1]] en {{PLURAL:$2|één pagina|$2 pagina's}} zijn verwijderd uit categorie",
+       "recentchanges-page-removed-from-category-bundled": "[[:$1]] is verwijderd uit de categorie, [[Special:WhatLinksHere/$1|deze pagina is opgenomen in andere pagina's]]",
        "autochange-username": "Automatische wijziging van MediaWiki",
        "upload": "Bestand uploaden",
        "uploadbtn": "Bestand uploaden",
index 750bc46..fb13702 100644 (file)
        "content-model-text": "perustekstu",
        "content-model-javascript": "JavaScript",
        "content-json-empty-object": "Tyhjy objektu",
-       "cantcreateaccounttitle": "Ei voi luadie tunnustu",
        "cantcreateaccount-text": "Tunnuksien luadimine täs IP-adressaspäi ('''$1''') on estetty. Estäjänny on [[User:$3|$3]].\n\nKäyttäjän $3 annettu syy on ''$2''",
        "cantcreateaccount-range-text": "Tunnuksien luadimine IP-adressilois adressualovehel <strong>$1</strong>, kuduah kuuluu sinungi käytetty IP-adressu(<strong>$4</strong>), on estetty. Eston on azetannuh [[User:$3|$3]].\n\nKäyttäjän $3 annettu syy estole on \"$2\".",
        "viewpagelogs": "Ozuta tämän sivun lougat",
index 52740a6..34ac95f 100644 (file)
@@ -32,6 +32,7 @@
        "tog-watchdefault": "ମୁଁ ବଦଳେଇଥିବା ପୃଷ୍ଠା ଏବଂ ଫାଇଲଗୁଡ଼ିକୁ ମୋର ଦେଖଣାତାଲିକାରେ ଯୋଡ଼ନ୍ତୁ",
        "tog-watchmoves": "ମୁଁ ଘୁଞ୍ଚାଇଥିବା ପୃଷ୍ଠା ଏବଂ ଫାଇଲଗୁଡ଼ିକୁ ମୋର ଦେଖଣାତାଲିକାରେ ଯୋଡ଼ନ୍ତୁ",
        "tog-watchdeletion": "ମୁଁ ଲିଭାଇଥିବା ପୃଷ୍ଠା ଏବଂ ଫାଇଲଗୁଡ଼ିକୁ ମୋର ଦେଖଣାତାଲିକାରେ ଯୋଡ଼ନ୍ତୁ",
+       "tog-watchuploads": "ମୋ ଦେଖଣାତାଲିକାରେ ମୁଁ ଅପଲୋଡ଼ କରୁଥିବା ନୂଆ ଫାଇଲ ଯୋଡ଼ନ୍ତୁ",
        "tog-watchrollback": "ମୁଁ ପଛକୁ ଫେରାଇଦେଇଥିବା ମୋ ଦେଖଣାତାଲିକାର ପୃଷ୍ଠାସବୁକୁ ଯୋଡ଼ନ୍ତୁ",
        "tog-minordefault": "ସବୁଯାକ ସମ୍ପାଦନାକୁ ଆପେ ଛୋଟ ବଦଳ ଭାବରେ ସୂଚିତ କରିବେ",
        "tog-previewontop": "ଏଡ଼ିଟ ବାକ୍ସ ଆଗରୁ ଦେଖଣା ଦେଖାଇବେ",
@@ -41,7 +42,7 @@
        "tog-enotifminoredits": "ପୃଷ୍ଠାରେ ଏବଂ ଫାଇଲଗୁଡିକରେ ଛୋଟ ଛୋଟ ବଦଳ ହେଲେ ବି ମୋତେ ଇ-ମେଲ କରିବେ",
        "tog-enotifrevealaddr": "ନୋଟିଫିକେସନ ଇମେଲରେ ମୋ ଇ-ମେଲ ଦେଖାଇବେ",
        "tog-shownumberswatching": "ଦେଖୁଥିବା ବ୍ୟବହାରକାରୀଙ୍କ ସଂଖ୍ୟା ଦେଖାନ୍ତୁ",
-       "tog-oldsig": "à¬\8fବà­\87à¬\95ାର ଦସ୍ତଖତ:",
+       "tog-oldsig": "à¬\86ପଣà¬\99à­\8dà¬\95ର à¬\8fବà­\87ର ଦସ୍ତଖତ:",
        "tog-fancysig": "ଦସ୍ତଖତକୁ ଉଇକିଟେକ୍ସଟ ଭାବରେ ଗଣିବେ (ଆପେଆପେ ଥିବା ଲିଙ୍କ ବିନା)",
        "tog-uselivepreview": "ସାଥେ ସାଥେ ଚାଲିଥିବା ଦେଖଣା ବ୍ୟବହାର କରିବେ",
        "tog-forceeditsummary": "ଖାଲି ସମ୍ପାଦନା ସାରକଥାକୁ ଯିବା ବେଳେ ମୋତେ ଜଣାଇବେ",
index ce00a81..ad9848b 100644 (file)
        "upload-dialog-disabled": "Przesyłanie plików przy pomocy tego okna jest wyłączone na tej wiki.",
        "upload-dialog-title": "Prześlij plik",
        "upload-dialog-button-cancel": "Anuluj",
+       "upload-dialog-button-back": "Wstecz",
        "upload-dialog-button-done": "Gotowe",
        "upload-dialog-button-save": "Zapisz",
        "upload-dialog-button-upload": "Prześlij",
        "htmlform-cloner-create": "Dodaj więcej",
        "htmlform-cloner-delete": "Usuń",
        "htmlform-cloner-required": "Wymagana jest co najmniej jedna wartość.",
+       "htmlform-date-placeholder": "RRRR-MM-DD",
        "htmlform-title-badnamespace": "[[:$1]] nie znajduje się w przestrzeni nazw „{{ns:$2}}”.",
        "htmlform-title-not-creatable": "Nie można użyć „$1” do utworzenia tytułu strony",
        "htmlform-title-not-exists": "$1 nie istnieje.",
index 21272c1..15b5bee 100644 (file)
@@ -12,7 +12,8 @@
                        "Obaid Raza",
                        "Macofe",
                        "Matma Rex",
-                       "Saanvel"
+                       "Saanvel",
+                       "Satdeep gill"
                ]
        },
        "tog-underline": "حوڑ تھلے لین:",
        "yourpasswordagain": "کنجی فیر لکھو:",
        "createacct-yourpasswordagain": "کنجی پکی کرو",
        "createacct-yourpasswordagain-ph": "کنجی فیر پاؤ",
-       "remembermypassword": "اس براؤزر تے میرا ورتن ناں یاد رکھو ($1 {{PLURAL:$1|دن|دناں}} واسطے)",
        "userlogin-remembermypassword": "مینوں لاگ ان رکھو",
        "yourdomainname": "تواڈا علاقہ:",
        "externaldberror": "ڈیٹابیس چ توانوں پہچاننے چ کوئی مسئلہ ہویا اے یا فیر تسی اپنا بارلا کھاتا نئیں بدل سکدے۔",
        "passwordreset-emailtext-user": "ورتنوالے $1 نے {{سائیٹناں}} تے تواڈے کھاتے بارے پچھیا اے {{SITENAME}} لئی ($4)۔ تھلے دتا گیا ورتن {{PLURAL:$3|کھاتہ|کھاتے}} ایس ای-میل نال جڑدا اے۔\n\n$2\n\n{{PLURAL:$3|ایہ عارضی کنجی|اے عارضی کنجیاں}} مک جائیگا {{PLURAL:$5|اک دن|$5 دن}}۔ تسیں ہن لاکان ہوو تے نویں کنجی چنو۔ اگر کسے ہور نے اے چٹھی پیجی یا توانوں اپنی پہلی کنجی یاد آگئی اے تے تسیں اونوں بدلنا نئیں چاندے تے تسیں ایس سنیعے نوں پھل جاؤ تے پرانی کنجی نال ای کم چلاؤ۔",
        "passwordreset-emailelement": "ورتن ناں: \n$1\n\nعارضی کنجی: \n$2",
        "passwordreset-emailsentemail": "یاد کران واسطے اک ای-میل پیج دتی گئی اے۔",
-       "passwordreset-emailsent-capture": "اک یاد کران والی ای-میل پیج دتی گئی اے، جیہڑی تھلے دسی گئی اے۔",
-       "passwordreset-emailerror-capture": "اک یادکراؤ ای-میل بنائی گئی اے، جیہڑی کہ تھلے دسی گئی اے، پر ورتن والے تک پیجنا نئیں ہوسکیا:$1",
        "changeemail": "ای-میل پتہ بدلو",
        "changeemail-header": "کھاتے دا ای-میل پتہ بدلو",
        "changeemail-no-info": "تسی لاگ ان ہوکے ای اس صفحے نوں ویکھ سکدے او۔",
        "minoredit": "اے نکا جیا کم اے",
        "watchthis": "اس صفے تے اکھ رکھو",
        "savearticle": "کم بچاؤ",
+       "savechanges": "کم بچاؤ",
        "preview": "وکھاؤ",
        "showpreview": "کچا کم ویکھو",
        "showdiff": "تبدیلیاں وکھاؤ",
        "undo-failure": "تبدیلی واپس نئیں ہوسکدی وشکار ہویاں تبدیلیاں ہون دی وجہ توں۔",
        "undo-norev": "تبدیلی واپس نئیں ہوسکدی کیوں جے ایہ ہے ای نئیں یا مٹا دتی گئی اے۔",
        "undo-summary": "$1 دی کیتی ہوئی ریوین [[Special:Contributions/$2|$2]] ([[User talk:$2|گل]]) واپس کرو",
-       "cantcreateaccounttitle": "کھاتہ نئیں کھول سکدے",
        "cantcreateaccount-text": "کھاتہ بنانا ایس آئی پی پتے  ('''$1''')  لئی  [[User:$3|$3]] نے روک دتی اے۔\n$3 نے ''$2'' وجہ دسی اے۔",
        "viewpagelogs": "صفحے دے لاگ ویکھو",
        "nohistory": "اس صفحے دی پرانی لکھائی دی کوئی تاریخ نئیں۔",
        "htmlform-submit": "رکھو",
        "htmlform-reset": "تبدیلیاں واپس",
        "htmlform-selectorother-other": "ہور",
-       "sqlite-has-fts": "$1 پوری لکھت کھوج مدد نال",
-       "sqlite-no-fts": "$1 بنا کسے لکھت مدد دے",
        "logentry-delete-delete": "$1 {{GENDER:$2|مٹایا}} صفہ $3",
        "logentry-delete-restore": "$1 {{GENDER:$2|بچایا}} صفہ $3",
        "logentry-delete-event": "$1 پلٹے وکھالہ {{PLURAL:$5|اک لاگ ایونٹ|$5 لاگ ایونٹس}} تے $3: $4",
        "special-characters-group-gujarati": "گجراتی",
        "special-characters-group-thai": "تھائی",
        "special-characters-group-lao": "لاؤ",
-       "special-characters-group-khmer": "کھیمر",
-       "api-error-blacklisted": "مہربانی کرکے وکھری سرخی چنو۔"
+       "special-characters-group-khmer": "کھیمر"
 }
index 2b48012..668515e 100644 (file)
                        "LucyDiniz",
                        "Tusca",
                        "Cristofer Alves",
-                       "Tark"
+                       "Tark",
+                       "O Andarilho"
                ]
        },
        "tog-underline": "Sublinhar links:",
        "tog-enotifminoredits": "Notificar-me por email também sobre edições menores de páginas ou arquivos",
        "tog-enotifrevealaddr": "Revelar meu endereço de email nas mensagens de notificação",
        "tog-shownumberswatching": "Mostrar o número de usuários que estão vigiando",
-       "tog-oldsig": "Assinatura existente:",
+       "tog-oldsig": "Sua Assinatura Existente:",
        "tog-fancysig": "Tratar assinatura como wikitexto (sem link automático)",
        "tog-uselivepreview": "Utilizar pré-visualização em tempo real",
        "tog-forceeditsummary": "Avisar-me ao introduzir um sumário de edição vazio",
        "tog-showhiddencats": "Exibir categorias ocultas",
        "tog-norollbackdiff": "Omitir diferenças após desfazer edições em bloco",
        "tog-useeditwarning": "Avisar-me quando eu deixar uma janela de edição sem ter salvo as alterações",
-       "tog-prefershttps": "Usar sempre uma conexão segura quando estiver conectado",
+       "tog-prefershttps": "Usar sempre uma conexão segura enquanto estiver conectado",
        "underline-always": "Sempre",
        "underline-never": "Nunca",
        "underline-default": "Padrão do navegador/skin",
        "newwindow": "(abre numa nova janela)",
        "cancel": "Cancelar",
        "moredotdotdot": "Mais...",
-       "morenotlisted": "Esta lista não está completa.",
+       "morenotlisted": "Esta lista está incompleta.",
        "mypage": "Página",
        "mytalk": "Discussão",
        "anontalk": "Discussão",
index 160f738..e2b8292 100644 (file)
        "upload-dialog-disabled": "Message shown when the upload dialog functionality is disabled. (This doesn't mean that uploads in general are disabled, only this specific method of uploading.)",
        "upload-dialog-title": "Title of the upload dialog box\n{{Identical|Upload file}}",
        "upload-dialog-button-cancel": "Button to cancel the dialog\n{{Identical|Cancel}}",
+       "upload-dialog-button-back": "Button to go back the dialog\n{{Identical|Back}}",
        "upload-dialog-button-done": "Button to close the dialog once upload is complete\n{{Identical|Done}}",
        "upload-dialog-button-save": "Button to save the file after upload finishes and metadata is filled out, part 2 of a multi-step upload form\n{{Identical|Save}}",
        "upload-dialog-button-upload": "Button to initiate upload, part 1 of a multi-step upload form\n{{Identical|Upload}}",
        "htmlform-cloner-create": "Used as the text for the button that adds a row to a multi-input HTML form element.\n\nSee also:\n* {{msg-mw|htmlform-cloner-delete}}\n* {{msg-mw|htmlform-cloner-required}}",
        "htmlform-cloner-delete": "Used as the text for the button that removes a row from a multi-input HTML form element\n\nSee also:\n* {{msg-mw|htmlform-cloner-create}}\n* {{msg-mw|htmlform-cloner-required}}\n{{Identical|Remove}}",
        "htmlform-cloner-required": "Used as an error message in HTML forms.\n\nSee also:\n* {{msg-mw|htmlform-required}}\n* {{msg-mw|htmlform-cloner-create}}\n* {{msg-mw|htmlform-cloner-delete}}",
+       "htmlform-date-placeholder": "Used as initial placeholder text in \"date\" input boxes. This date MUST be formatted as a 4-digit year, 2-digit month, and 2-digit day, in the Gregorian calendar, separated with ASCII hyphen ('-') characters. You can localise the letters to your language or script, but you should not change the format.",
+       "htmlform-time-placeholder": "Used as initial placeholder text in \"time\" input boxes. This time MUST be formatted as a 2-digit hour 00 to 23, a 2-digit minute, and an optional 2-digit second, all separated by ASCII colons. You can localise the letters to your language or script, but you should not change the format.",
+       "htmlform-datetime-placeholder": "Used as initial placeholder text in \"datetime\" input boxes. This date and time MUST be formatted as a 4-digit year, 2-digit month, and 2-digit day, in the Gregorian calendar, separated with ASCII hyphen ('-') characters, followed by a space (or the letter 'T'), followed by a time formatted as a 2-digit hour 00 to 23, a 2-digit minute, and an optional 2-digit second, all separated by ASCII colons. You can localise the letters to your language or script, but you should not change the format.",
+       "htmlform-date-invalid": "Used as error message in HTML forms. This date MUST be formatted as a 4-digit year, 2-digit month, and 2-digit day, in the Gregorian calendar, separated with ASCII hyphen ('-') characters. You can localise the letters to your language or script, but you should not change the format.\n\n* {{msg-mw|Htmlform-invalid-input}}\n* {{msg-mw|Apifeatureusage-htmlform-date-placeholder}}\n* {{msg-mw|Apifeatureusage-htmlform-date-toolow}}\n* {{msg-mw|Apifeatureusage-htmlform-date-toohigh}}\n* {{msg-mw|Htmlform-required}}",
+       "htmlform-time-invalid": "Used as error message in HTML forms. This time MUST be formatted as a 2-digit hour 00 to 23, a 2-digit minute, and an optional 2-digit second, all separated by ASCII colons. You can localise the letters to your language or script, but you should not change the format.\n\n* {{msg-mw|Htmlform-invalid-input}}\n* {{msg-mw|Apifeatureusage-htmlform-time-placeholder}}\n* {{msg-mw|Apifeatureusage-htmlform-time-toolow}}\n* {{msg-mw|Apifeatureusage-htmlform-time-toohigh}}\n* {{msg-mw|Htmlform-required}}",
+       "htmlform-datetime-invalid": "Used as error message in HTML forms. This date and time MUST be formatted as a 4-digit year, 2-digit month, and 2-digit day, in the Gregorian calendar, separated with ASCII hyphen ('-') characters, followed by a space (or the letter 'T'), followed by a time formatted as a 2-digit hour 00 to 23, a 2-digit minute, and an optional 2-digit second, all separated by ASCII colons. You can localise the letters to your language or script, but you should not change the format.\n\n* {{msg-mw|Htmlform-invalid-input}}\n* {{msg-mw|Apifeatureusage-htmlform-datetime-placeholder}}\n* {{msg-mw|Apifeatureusage-htmlform-datetime-toolow}}\n* {{msg-mw|Apifeatureusage-htmlform-datetime-toohigh}}\n* {{msg-mw|Htmlform-required}}",
+       "htmlform-date-toolow": "Used as error message in HTML forms. Parameters:\n* $1 - minimum date\nSee also:\n* {{msg-mw|Htmlform-invalid-input}}\n* {{msg-mw|Htmlform-required}}\n* {{msg-mw|Apifeatureusage-htmlform-date-invalid}}\n* {{msg-mw|Apifeatureusage-htmlform-date-toohigh}}",
+       "htmlform-date-toohigh": "Used as error message in HTML forms. Parameters:\n* $1 - maximum date\nSee also:\n* {{msg-mw|Htmlform-invalid-input}}\n* {{msg-mw|Htmlform-required}}\n* {{msg-mw|Apifeatureusage-htmlform-date-invalid}}\n* {{msg-mw|Apifeatureusage-htmlform-date-toolow}}",
+       "htmlform-time-toolow": "Used as error message in HTML forms. Parameters:\n* $1 - minimum date\nSee also:\n* {{msg-mw|Htmlform-invalid-input}}\n* {{msg-mw|Htmlform-required}}\n* {{msg-mw|Apifeatureusage-htmlform-time-invalid}}\n* {{msg-mw|Apifeatureusage-htmlform-time-toohigh}}",
+       "htmlform-time-toohigh": "Used as error message in HTML forms. Parameters:\n* $1 - maximum date\nSee also:\n* {{msg-mw|Htmlform-invalid-input}}\n* {{msg-mw|Htmlform-required}}\n* {{msg-mw|Apifeatureusage-htmlform-time-invalid}}\n* {{msg-mw|Apifeatureusage-htmlform-time-toolow}}",
+       "htmlform-datetime-toolow": "Used as error message in HTML forms. Parameters:\n* $1 - minimum date\nSee also:\n* {{msg-mw|Htmlform-invalid-input}}\n* {{msg-mw|Htmlform-required}}\n* {{msg-mw|Apifeatureusage-htmlform-datetime-invalid}}\n* {{msg-mw|Apifeatureusage-htmlform-datetime-toohigh}}",
+       "htmlform-datetime-toohigh": "Used as error message in HTML forms. Parameters:\n* $1 - maximum date\nSee also:\n* {{msg-mw|Htmlform-invalid-input}}\n* {{msg-mw|Htmlform-required}}\n* {{msg-mw|Apifeatureusage-htmlform-datetime-invalid}}\n* {{msg-mw|Apifeatureusage-htmlform-datetime-toolow}}",
        "htmlform-title-badnamespace": "Error message shown if the page title provided by the user is not in the required namespace. $1 is the page, $2 is the numerical namespace index.",
        "htmlform-title-not-creatable": "Error message shown if the page title provided by the user is not creatable (a special page). $1 is the page title.",
        "htmlform-title-not-exists": "Error message shown if the page title provided by the user does not exist. $1 is the page title.",
index c2c42c2..dadd322 100644 (file)
        "expensive-parserfunction-warning": "Atenție: Această pagină conține prea multe apelări costisitoare ale funcțiilor parser.\n\nAr trebui să existe mai puțin de $2 {{PLURAL:$2|apelare|apelări}}, acolo există {{PLURAL:$1|$1 apelare|$1 apelări}}.",
        "expensive-parserfunction-category": "Pagini cu prea multe apelări costisitoare de funcții parser",
        "post-expand-template-inclusion-warning": "Atenție: Formatele incluse sunt prea mari.\nUnele formate nu vor fi incluse.",
-       "post-expand-template-inclusion-category": "Paginile în care este inclus formatul are o dimensiune prea mare",
+       "post-expand-template-inclusion-category": "Pagini în care formatele incluse au o dimensiune prea mare",
        "post-expand-template-argument-warning": "Atenție: Această pagină conține cel puțin un argument al unui format care are o mărime prea mare atunci când este expandat.\nAcsete argumente au fost omise.",
        "post-expand-template-argument-category": "Pagini care conțin formate cu argumente omise",
        "parser-template-loop-warning": "Buclă de formate detectată: [[$1]]",
index 57a83d6..1fc53df 100644 (file)
        "eauthentsent": "На указанный адрес электронной почты отправлено письмо. \nЧтобы получать письма в дальнейшем, следуйте изложенным там инструкциям для подтверждения, что этот адрес действительно принадлежит вам.",
        "throttled-mailpassword": "Функция напоминания пароля уже использовалась в течение {{PLURAL:$1|1=последнего часа|последних $1 часов}}.\nДля предотвращения злоупотреблений, разрешено запрашивать не более одного напоминания {{PLURAL:$1|за $1 час|за $1 часов|за $1 часа|1=в час}}.",
        "mailerror": "Ошибка при отправке почты: $1",
-       "acct_creation_throttle_hit": "Ð\97а Ñ\81Ñ\83Ñ\82ки Ñ\81 Ð²Ð°Ñ\88его IP-адÑ\80еÑ\81а {{PLURAL:$1|бÑ\8bла Ñ\81оздана $1 Ñ\83Ñ\87Ñ\91Ñ\82наÑ\8f Ð·Ð°Ð¿Ð¸Ñ\81Ñ\8c|бÑ\8bло Ñ\81оздано $1 Ñ\83Ñ\87Ñ\91Ñ\82нÑ\8bÑ\85 Ð·Ð°Ð¿Ð¸Ñ\81ей|бÑ\8bли Ñ\81озданÑ\8b $1 Ñ\83Ñ\87Ñ\91Ñ\82нÑ\8bÑ\85 Ð·Ð°Ð¿Ð¸Ñ\81и|1=Ñ\83же Ð±Ñ\8bла Ñ\81оздана Ñ\83Ñ\87Ñ\91Ñ\82наÑ\8f Ð·Ð°Ð¿Ð¸Ñ\81Ñ\8c}} — это предельное количество для данного отрезка времени.\nВ результате, пользователи с этим IP-адресом в данный момент больше не могут создавать новых учётных записей.",
+       "acct_creation_throttle_hit": "Ð\9fоÑ\81еÑ\82иÑ\82ели Ñ\81 Ð²Ð°Ñ\88его IP-адÑ\80еÑ\81а {{PLURAL:$1|бÑ\8bла Ñ\81оздана $1 Ñ\83Ñ\87Ñ\91Ñ\82наÑ\8f Ð·Ð°Ð¿Ð¸Ñ\81Ñ\8c|бÑ\8bло Ñ\81оздано $1 Ñ\83Ñ\87Ñ\91Ñ\82нÑ\8bÑ\85 Ð·Ð°Ð¿Ð¸Ñ\81ей|бÑ\8bли Ñ\81озданÑ\8b $1 Ñ\83Ñ\87Ñ\91Ñ\82нÑ\8bÑ\85 Ð·Ð°Ð¿Ð¸Ñ\81и}} Ð·Ð° Ð¿Ð¾Ñ\81ледние $2 — это предельное количество для данного отрезка времени.\nВ результате, пользователи с этим IP-адресом в данный момент больше не могут создавать новых учётных записей.",
        "emailauthenticated": "Ваш адрес электронной почты подтверждён $2 в $3.",
        "emailnotauthenticated": "Ваш адрес электронной почты ещё не был подтверждён.\nПисьма не будут отправляться ни для одной из следующий функций.",
        "noemailprefs": "Адрес электронной почты не был указан, функции вики-движка по работе с эл. почтой отключены.",
        "passwordreset-emailelement": "Имя участника: \n$1\n\nВременный пароль: \n$2",
        "passwordreset-emailsentemail": "Если это адрес электронной почты связан с вашей учётной записью, вам будет отправлено письмо для сброса пароля.",
        "passwordreset-emailsentusername": "Если есть адрес электронной почты, связанный с этим именем участника, то будет отправлено письмо для восстановления пароля.",
-       "passwordreset-emailsent-capture2": "{{PLURAL:$1|Ð\9fиÑ\81Ñ\8cмо|Ð\9fиÑ\81Ñ\8cма}} Ð´Ð»Ñ\8f Ñ\81бÑ\80оÑ\81а Ð¿Ð°Ñ\80олÑ\8f {{PLURAL:$1|бÑ\8bло Ð¾Ñ\82пÑ\80авлено|бÑ\8bли Ð¾Ñ\82пÑ\80авленÑ\8b}}. {{PLURAL:$1|Ð\9bогин Ð¸ Ð¿Ð°Ñ\80олÑ\8c Ð¿Ð¾ÐºÐ°Ð·Ð°Ð½Ñ\8b|СпиÑ\81ок Ð»Ð¾Ð³Ð¸Ð½Ð¾Ð² Ð¸ Ð¿Ð°Ñ\80олей Ð¿Ð¾ÐºÐ°Ð·Ð°Ð½}} Ð½Ð¸Ð¶Ðµ.",
-       "passwordreset-emailerror-capture2": "Отправка {{GENDER:$2|участнику}} письма по электронной почте не удалась: $1 В {{PLURAL:$3|логин и пароль показаны|список логинов и паролей показан}} ниже.",
+       "passwordreset-emailsent-capture2": "{{PLURAL:$1|Ð\9fиÑ\81Ñ\8cмо|Ð\9fиÑ\81Ñ\8cма}} Ð´Ð»Ñ\8f Ñ\81бÑ\80оÑ\81а Ð¿Ð°Ñ\80олÑ\8f {{PLURAL:$1|бÑ\8bло Ð¾Ñ\82пÑ\80авлено|бÑ\8bли Ð¾Ñ\82пÑ\80авленÑ\8b}}. {{PLURAL:$1|Ð\9bогин Ð¸ Ð¿Ð°Ñ\80олÑ\8c Ð¿Ð¾ÐºÐ°Ð·Ð°Ð½Ñ\8b|СпиÑ\81ок Ð»Ð¾Ð³Ð¸Ð½Ð¾Ð² Ð¸ Ð¿Ð°Ñ\80олей Ð¿Ð¾ÐºÐ°Ð·Ð°Ð½}} Ð·Ð´ÐµÑ\81Ñ\8c.",
+       "passwordreset-emailerror-capture2": "Отправка {{GENDER:$2|участнику|участнице}} письма по электронной почте не удалась: $1\n{{PLURAL:$3|Логин и пароль показаны|Список логинов и паролей показан}} здесь.",
        "passwordreset-nocaller": "Должен быть предоставлен источник вызова",
        "passwordreset-nosuchcaller": "Источник вызова не существует: $1",
        "passwordreset-ignored": "Сброс пароля не был обработан. Может быть, не был настроен ни один провайдер?",
        "upload-dialog-disabled": "На этом вики-сайте отключена возможность загрузки файлов с помощью этого диалогового окна.",
        "upload-dialog-title": "Загрузить файл",
        "upload-dialog-button-cancel": "Отменить",
+       "upload-dialog-button-back": "Назад",
        "upload-dialog-button-done": "Готово",
        "upload-dialog-button-save": "Сохранить",
        "upload-dialog-button-upload": "Загрузить",
        "htmlform-cloner-create": "Добавить ещё",
        "htmlform-cloner-delete": "Удалить",
        "htmlform-cloner-required": "Требуется по крайней мере одно значение.",
+       "htmlform-date-placeholder": "ГГГГ-ММ-ДД",
+       "htmlform-time-placeholder": "ЧЧ:ММ:СС",
+       "htmlform-datetime-placeholder": "ГГГГ-ММ-ДД ЧЧ:ММ:СС",
+       "htmlform-date-invalid": "Указанное вами значение не похоже на дату. Попробуйте использовать формат ГГГГ-ММ-ДД.",
+       "htmlform-time-invalid": "Указанное вами значение не похоже на время. Попробуйте использовать формат ЧЧ-ММ-СС.",
+       "htmlform-datetime-invalid": "Указанное вами значение не похоже на дату и время. Попробуйте использовать формат ГГГГ-ММ-ДД ЧЧ-ММ-СС.",
+       "htmlform-date-toolow": "Указанное вами значение меньше самой ранней разрешённой даты — $1.",
+       "htmlform-date-toohigh": "Указанное вами значение больше самой поздней разрешённой даты — $1.",
+       "htmlform-time-toolow": "Указанное вами значение меньше самого раннего разрешённого времени — $1.",
+       "htmlform-time-toohigh": "Указанное вами значение больше самого позднего разрешённого времени — $1.",
+       "htmlform-datetime-toolow": "Указанное вами значение меньше самым ранних разрешённых даты и времени — $1.",
+       "htmlform-datetime-toohigh": "Указанное вами значение больше самых поздних разрешённых даты и времени — $1.",
        "htmlform-title-badnamespace": "[[:$1]] находится не в пространстве имён «{{ns:$2}}».",
        "htmlform-title-not-creatable": "«$1» — заголовок страницы, которая не может быть создана",
        "htmlform-title-not-exists": "$1 не существует.",
        "unlinkaccounts-success": "Учетная запись была отвязан.",
        "authenticationdatachange-ignored": "Изменение данных для проверки подлинности не было обработано. Может быть, не был настроен ни один провайдер?",
        "userjsispublic": "Обратите внимание: подстраницы JavaScript не должны содержать конфиденциальные сведения, поскольку они доступны для просмотра другим участникам.",
-       "usercssispublic": "Обратите внимание: подстраницы CSS не должны содержать конфиденциальные сведения, поскольку они доступны для просмотра другим участникам."
+       "usercssispublic": "Обратите внимание: подстраницы CSS не должны содержать конфиденциальные сведения, поскольку они доступны для просмотра другим участникам.",
+       "restrictionsfield-badip": "Недопустимый IP-адрес или диапазон адресов: $1",
+       "restrictionsfield-label": "Разрешённые диапазоны IP-адресов:",
+       "restrictionsfield-help": "По одному IP-адресу или CIDR-диапазону в строке. Чтобы разрешить всё, используйте <br /><code>0.0.0.0/0</code><br /><code>::/0</code>"
 }
index 15d45cf..65f90a8 100644 (file)
@@ -31,7 +31,7 @@
        "tog-enotifminoredits": "صفحن ۾ معمولي ترميمن جي صورت ۾ بہ مون کي برق ٽپال ڪريو",
        "tog-enotifrevealaddr": "پڌراين ۾ منهنجو برق ٽپال پتو ظاهر ڪريو.",
        "tog-shownumberswatching": "ڏسندڙ يوزرس جو انگ ڏيکاريو",
-       "tog-oldsig": "موجوده دستخط",
+       "tog-oldsig": "توھان جو موجوده دستخط:",
        "tog-uselivepreview": "سڌي سنئين پيش نگاھہ استعمال ڪريو",
        "tog-watchlisthideown": "زير نظر فهرست مان منهنجون ڪيل ترميمون لڪايو",
        "tog-watchlisthidebots": "ٽيٽ فهرست تان بوٽ جون ترميمون لڪايو",
@@ -43,7 +43,7 @@
        "tog-diffonly": "تفاوت هيٺان صفحي جو مواد نہ ڏيکاريو",
        "tog-showhiddencats": "لڪل زمرا ڏيکاريو",
        "tog-useeditwarning": "مونکي خبردار ڪريو جڏهن مان هڪ ترميم وارو صفحو بغير تبديلين سانڍڻ جي ڇڏيان",
-       "tog-prefershttps": "هميشه محفوظ ڪنيڪشن استعمال ڪريو جڏهن لاگ اِن ٿيل هجو",
+       "tog-prefershttps": "هميشہ محفوظ ڪنيڪشن استعمال ڪريو جڏهن داخل ٿيل هجو",
        "underline-always": "هميشہ",
        "underline-never": "ڪڏهن بہ نہ",
        "editfont-style": "ايراضي جو فونٽ اسٽائيل سنواريو:",
        "newwindow": "(نئين دريءَ ۾ کلندو)",
        "cancel": "رد",
        "moredotdotdot": "اڃا...",
-       "morenotlisted": "فهرست مڪمل ڪانهي.",
+       "morenotlisted": "ھي فھرست نامڪمل بہ ٿي سگھي ٿي.",
        "mypage": "منهنجو صفحو",
        "mytalk": "ڳالهہ ٻول",
        "anontalk": "ڳالھ ٻولھ",
        "yourpasswordagain": "يُوزرنان ٻيهر ٽائيپ ڪريو:",
        "createacct-yourpasswordagain": "ڳجھي لفظ جي خاطري ڪريو",
        "createacct-yourpasswordagain-ph": "ٻيهر ڳجھو لفظ داخل ڪريو",
-       "remembermypassword": "هن برائوزر تي منهنجي لاگ ان کي (وڌ ۾ وڌ $1 {{PLURAL:$1|ڏينهن}} لاءِ) ياد رکو",
        "userlogin-remembermypassword": "مون کي لاگ اِن رکو",
        "userlogin-signwithsecure": "محفوظ ڳانڍاپو استعمال ڪريو",
        "cannotloginnow-title": "ھاڻي لاگ ان نٿو ڪري سگھجي",
        "passwordreset-emailtitle": "{{SITENAME}} واري کاتي جا تفصيل",
        "passwordreset-emailelement": "يُوزر نانءُ: \n$1\n\nعارضي ڳجھو لفظ:\n$2",
        "changeemail": "برق ٽپال پتو مِٽايو يا بدلايو",
-       "changeemail-passwordrequired": "توهانکي هن تبديلي جي تصديق ڪرڻ جي لاءِ پنهنجو ڳجھو لفظ داخل ڪرڻ جي ضرورت پوندي.",
        "changeemail-oldemail": "هاڻوڪو برق ٽپال پتو:",
        "changeemail-newemail": "نئون برق ٽپال پتو:",
        "changeemail-none": "(ڪو بہ نہ)",
        "content-json-empty-array": "خالي اري",
        "duplicate-args-warning": "چتاءُ: [[:$2]] کي [[:$1]] ڪال ڪري رهيو آهي، جنهن منجھہ ’$3‘ نيم‌پيما لاءِ هڪ کان وڌيڪ قدر ڄاڻايل آهن. فقط آخري ڄاڻايل قدر استعمال ڪيو ويندو.",
        "parser-template-loop-warning": "سانچو چڪر لڌو ويو: [[$1]]",
-       "cantcreateaccounttitle": "کاتو کولي نہ ٿو سگھجي",
        "cantcreateaccount-text": "هن آءِ پي پتي تان کاتي جي تخليق تي يُوز (<strong>$1</strong>)  [[User:$3|$3]] روڪ لڳائي آهي.\n\n$3 جو ڄاڻايل سبب آهي <em>$2</em> آهي.",
        "cantcreateaccount-range-text": "آءِپي پتن جي حد <strong>$1</strong> ۾ [[User:$3|$3]] کاتو کولڻ تي روڪ لڳائي وئي آهي،$4 جنهن ۾ توهان جو آءِپي پتو بہ (<strong>$4</strong>)،  پڻ شامل آهي. \n\n$3 ان روڪَ جو سبب \"$2\" ڄاڻايو آهي.",
        "viewpagelogs": "هن صفحي جا لاگس ڏسو",
index c541349..a2e0dac 100644 (file)
        "talk": "Diskusia",
        "views": "Zobrazenia",
        "toolbox": "Nástroje",
+       "tool-link-userrights": "Zmeniť používateľské skupiny {{GENDER:$1|tohoto použivateľa|tejto používateľky}}",
+       "tool-link-emailuser": "Poslať e-mail {{GENDER:$1|tomuto používateľovi|tejto používateľke}}",
        "userpage": "Zobraziť stránku používateľa",
        "projectpage": "Zobraziť projektovú stránku",
        "imagepage": "Zobraziť stránku súboru",
        "content-model-css": "CSS",
        "content-json-empty-object": "Prázdny objekt",
        "content-json-empty-array": "Prázdne pole",
+       "deprecated-self-close-category": "Stránky s neplatnými samouzavrenými HTML značkami",
+       "deprecated-self-close-category-desc": "Stránka obsahuje neplatné samouzatvárajúce HTML značky, napr. <code>&lt;b/></code> alebo <code>&lt;span/></code>. Ich správanie sa v záujme konzistencie so špecifikáciou HTML5 čoskoro zmení a použitie je preto vo wikitexte zastarané.",
        "duplicate-args-warning": "<strong>Upozornenie:</strong> Stránka [[:$1]] volá [[:$2]] s viacerými hodnotami parametra „$3“. Použitá bude len posledná odovzdaná hodnota.",
        "duplicate-args-category": "Stránky s duplicitnými parametrami pri volaniach šablón",
        "duplicate-args-category-desc": "Stránka obsahuje volania šablóny používajúce duplicitné parametere, ako napríklad <code><nowiki>{{foo|bar=1|bar=2}}</nowiki></code> alebo <code><nowiki>{{foo|bar|1=baz}}</nowiki></code>.",
        "search-redirect": "(presmerovanie $1)",
        "search-section": "(sekcia $1)",
        "search-category": "($1 kategória)",
+       "search-file-match": "(výskyt v obsahu súboru)",
        "search-suggest": "Mali ste na mysli „$1“?",
        "search-rewritten": "Zobrazujú sa výsledky pre $1. Vyhľadať namiesto toho $2.",
        "search-interwiki-caption": "Sesterské projekty",
        "prefs-files": "Súbory",
        "prefs-custom-css": "Vlastný CSS",
        "prefs-custom-js": "Vlastný JS",
-       "prefs-common-css-js": "Spoločné CSS/JS pre všetky témy vzhľadu:",
+       "prefs-common-css-js": "Spoločné CSS/JS pre všetky témy:",
        "prefs-reset-intro": "Túto stránku môžete použiť na vrátenie predvolených hodnôt vašich nastavení.\nTúto operáciu nemožno vrátiť.",
        "prefs-emailconfirm-label": "Overenie e-emailu:",
        "youremail": "Váš e-mail²",
        "right-edit": "Upravovať stránky (ktoré nie sú diskusné stránky)",
        "right-createpage": "Vytvárať stránky (ktoré nie sú diskusné stránky)",
        "right-createtalk": "Vytvárať diskusné stránky",
-       "right-createaccount": "Vytvárať nové používateľské účty",
+       "right-createaccount": "Vytvárať nové používateľské kontá",
+       "right-autocreateaccount": "Automatické prihlásenie s externým používateľským kontom",
        "right-minoredit": "Označovať úpravy ako drobné",
        "right-move": "Presúvať stránky",
        "right-move-subpages": "Presunúť stránky aj s podstránkami",
        "rcshowhidebots": "$1 botov",
        "rcshowhidebots-show": "Zobraziť",
        "rcshowhidebots-hide": "Skryť",
-       "rcshowhideliu": "$1 registrovaných používateľov",
+       "rcshowhideliu": "$1 registrovaných",
        "rcshowhideliu-show": "Zobraziť",
        "rcshowhideliu-hide": "Skryť",
-       "rcshowhideanons": "$1 anonymných používateľov",
+       "rcshowhideanons": "$1 anonymov",
        "rcshowhideanons-show": "Zobraziť",
        "rcshowhideanons-hide": "Skryť",
        "rcshowhidepatr": "$1 úpravy strážených stránok",
        "rcshowhidemine": "$1 moje úpravy",
        "rcshowhidemine-show": "Zobraziť",
        "rcshowhidemine-hide": "Skryť",
-       "rcshowhidecategorization": "$1 kategorizáciu stránok",
+       "rcshowhidecategorization": "$1 kategorizáciu",
        "rcshowhidecategorization-show": "Zobraziť",
        "rcshowhidecategorization-hide": "Skryť",
        "rclinks": "Zobraziť posledných $1 úprav za posledných $2 dní<br />$3",
        "upload-copy-upload-invalid-domain": "Kopírovanie nahraných súborov nie je dostupné z tejto domény.",
        "upload-dialog-title": "Nahrať súbor",
        "upload-dialog-button-cancel": "Zrušiť",
+       "upload-dialog-button-back": "Späť",
        "upload-dialog-button-done": "Hotovo",
        "upload-dialog-button-save": "Uložiť",
        "upload-dialog-button-upload": "Nahrať",
        "watchnologin": "Nie ste prihlásený/á",
        "addwatch": "Pridať do zoznamu sledovaných stránok",
        "addedwatchtext": "Stránka „[[:$1]]“ a jej diskusná stránka boli pridané do vášho zoznamu [[Special:Watchlist|sledovaných stránok]].",
+       "addedwatchtext-talk": "„[[:$1]]“ a súvisiaca stránka boli pridané do vášho zoznamu [[Special:Watchlist|sledovaných stránok]].",
        "addedwatchtext-short": "Stránka „$1“ bola pridaná do vášho zoznamu sledovaných.",
        "removewatch": "Odstrániť zo zoznamu sledovaných",
        "removedwatchtext": "Stránka „[[:$1]]“ a jej diskusná stránka boli odstránené z vášho [[Special:Watchlist|zoznamu sledovaných stránok]].",
+       "removedwatchtext-talk": "„[[:$1]]“ a súvisiaca stránka boli odstránené z vášho [[Special:Watchlist|zoznamu sledovaných stránok]].",
        "removedwatchtext-short": "Stránka „$1“ bola odstránená z vášho zoznamu sledovaných.",
        "watch": "Sledovať",
        "watchthispage": "Sledovať túto stránku",
        "revertpage": "Posledné úpravy používateľa [[Special:Contributions/$2|$2]] ([[User talk:$2|diskusia]]) vrátené; bola obnovená posledná úprava $1",
        "revertpage-nouser": "Vrátené úpravy od skrytého používateľa na poslednú revíziu od {{GENDER:$1|[[User:$1|$1]]}}",
        "rollback-success": "Úpravy $1 vrátené; obnovená posledná verzia od $2.",
+       "rollback-success-notify": "Úpravy používateľa $1 boli vrátené;\nobnovená posledná revízia od používateľa $2. [$3 Zobraziť zmeny]",
        "sessionfailure-title": "Chyba relácie",
        "sessionfailure": "Zdá sa, že je problém s vašou prihlasovacou reláciou;\ntáto akcia bola zrušená ako prevencia proti zneužitiu relácie (session).\nProsím, stlačte \"naspäť\", obnovte stránku, z ktorej ste sa sem dostali, a skúste to znova.",
        "changecontentmodel": "Zmeniť model obsahu stránky",
        "tags-active-yes": "Áno",
        "tags-active-no": "Nie",
        "tags-source-extension": "Definované softvérom",
+       "tags-source-manual": "Pridané manuálne používateľmi a botmi",
        "tags-source-none": "Už sa nepoužíva",
        "tags-edit": "upraviť",
        "tags-delete": "zmazať",
        "feedback-bugornote": "Ak ste pripravený podrobne popísať technický problém, prosím pošlite [$1 hlásenie o chybe]. \nV opačnom prípade môžete použiť zjednodušený formulár nižšie. Váš komentár sa pridá na stránku „[$3 $2]“ spolu s vašim používateľským meno a prehliadačom, ktorý používate.",
        "feedback-cancel": "Zrušiť",
        "feedback-close": "Hotovo",
+       "feedback-external-bug-report-button": "Založiť technickú úlohu",
        "feedback-dialog-title": "Odoslať názor",
+       "feedback-dialog-intro": "Pomocou formulára nižšie môžete odoslať svoj názor. Váš komentár sa spolu s vašim použivateľským menom pridá na stránku „$1“.",
        "feedback-error-title": "Chyba",
        "feedback-error1": "Chyba: Nerozpoznaný výsledok z API",
        "feedback-error2": "Chyba: Úprava sa nepodarila",
        "feedback-message": "Správa:",
        "feedback-subject": "Predmet:",
        "feedback-submit": "Odoslať",
+       "feedback-terms": "Beriem na vedomie, že informácie o mojom prehliadači zahŕňajú jeho presnú verziu spolu s verziou operačného systému a budú zverejnené pri mojom komentári.",
+       "feedback-termsofuse": "Súhlasím s tým, že budem poskytovať spätnú väzbu v súlade s Podmienkami použitia.",
        "feedback-thanks": "Ďakujeme. Váš komentár bol odoslaný na stránku „[$2 $1]“.",
        "feedback-thanks-title": "Ďakujeme",
        "feedback-useragent": "Prehliadač:",
        "searchsuggest-search": "Hľadať",
        "searchsuggest-containing": "obsahuje...",
+       "api-error-autoblocked": "Vaše IP adresa bola automaticky zablokovaná, pretože ju používal zablokovaný používateľ.",
        "api-error-badaccess-groups": "Nemáte oprávnenie nahrávať súbory na tejto wiki.",
        "api-error-badtoken": "Vnútorná chyba: Zlý token.",
+       "api-error-blocked": "Možnosť editovať vám bola zablokovaná.",
        "api-error-copyuploaddisabled": "Nahrávanie z URL je na tomto serveri zakázané.",
        "api-error-duplicate": "{{PLURAL:$1|ďalší súbor|ďalšie súbory}} s rovnakým obsahom už na tejto wiki existujú",
        "api-error-duplicate-archive": "{{PLURAL:$1|ďalší súbor|ďalšie súbory}} s rovnakým obsahom už na tejto wiki existoval, ale {{PLURAL:$1|bol zmazaný|boli zmazané}}.",
        "pagelang-language": "Jazyk",
        "pagelang-use-default": "Použiť predvolený jazyk",
        "pagelang-select-lang": "Vybrať jazyk",
+       "pagelang-submit": "Odoslať",
        "right-pagelang": "Zmeniť jazyk stránky",
        "action-pagelang": "meniť jazyk stránky",
        "default-skin-not-found": "Uups! Základná tapeta pre Vašu wiki, popísanú v <code dir=\"ltr\">$wgDefaultSkin</code> ako <code>$1</code>, nie je dostupná. \n\nVaša inštalácia pravdepodobne obsahuje nasledovné tapety. Pozri [https://www.mediawiki.org/wiki/Manual:Skin_configuration Manual: Skin configuration] pre viac informácii o ich aktivácii a zvoľte základnú.\n\n$2\n\n; Ak ste MediaWiki len teraz nainštalovali\n; Zrejme ste to nainštalovali z gitu alebo priamo zo zdrojového kódu inou metódou. Je to očakávané. Skúste nainštalovať nejaké tapety z [https://www.mediawiki.org/wiki/Category:All_skins mediawiki.org's skin directory];\n:*Stiahnutím [https://www.mediawiki.org/wiki/Download tarball installer], ktorý ponúka viacero tapiet a rozšírení. Skopírovať a nalepiť možno priamo z <code>skins/</code>.\n:*Klonovanie jednej zo <code>mediawiki/skins/*</code> schránok cez git do <code dir=\"ltr\">skins/</code> priečinku Vašej Media Wiki inštalácie.\n: S existujúcou git schránkou, ak ste vývojár MediaWiki, by nemal byť konflikt.\n\n: Ak ste upgradeovali MediaWiki\n: MediaWiki 1.24 a novšie už tapety automaticky neaktivujú. (see [https://www.mediawiki.org/wiki/Manual:Skin_autodiscovery Manual: Skin autodiscovery]). Nasledovný kód môžete skopírovať do <code>LocalSettings.php</code> pre aktivovanie všetkých dostupných tapiet.\n\n<pre dir=\"ltr\">$3</pre>\n\n; Ak ste upravili <code>LocalSettings.php</code>:\n: Skontrolujte chyby.",
        "mediastatistics-header-text": "Text",
        "mediastatistics-header-executable": "Spustiteľné súbory",
        "mediastatistics-header-archive": "Komprimované formáty",
+       "mediastatistics-header-total": "Všetky súbory",
        "json-warn-trailing-comma": "Z JSONu {{PLURAL:$1|bola odstránená 1 koncová čiarka|boli odstránené $1 koncové čiarky|bolo odstránených $1 koncových čiarok}}",
        "json-error-unknown": "Došlo k problému s JSONom. Chyba: $1",
        "json-error-depth": "Maximálna hĺbka zásobníka bola prekročená",
        "special-characters-group-ipa": "IPA",
        "special-characters-group-symbols": "Symboly",
        "special-characters-group-greek": "Grécke",
+       "special-characters-group-greekextended": "Grécke rozšírené",
        "special-characters-group-cyrillic": "Azbuka",
        "special-characters-group-arabic": "Arabské",
        "special-characters-group-arabicextended": "Arabské rozšírené",
        "mw-widgets-dateinput-placeholder-month": "RRRR-MM",
        "mw-widgets-titleinput-description-new-page": "stránka zatiaľ neexistuje",
        "mw-widgets-titleinput-description-redirect": "presmerovanie na $1",
-       "randomrootpage": "Náhodná koreňová stránka"
+       "randomrootpage": "Náhodná koreňová stránka",
+       "changecredentials": "Zmena prihlasovacích údajov",
+       "removecredentials": "Odstránenie prihlasovacích údajov"
 }
index 4e51d08..bc4f06a 100644 (file)
        "editold": "spremeni",
        "viewsourceold": "izvorno besedilo",
        "editlink": "uredi",
-       "viewsourcelink": "izvorna koda",
+       "viewsourcelink": "izvorno besedilo",
        "editsectionhint": "Spremeni razdelek: $1",
        "toc": "Vsebina",
        "showtoc": "prikaži",
        "upload-dialog-disabled": "Nalaganj datotek z uporabo tega obrazca je na wikiju onemogočeno.",
        "upload-dialog-title": "Naloži datoteko",
        "upload-dialog-button-cancel": "Prekliči",
+       "upload-dialog-button-back": "Nazaj",
        "upload-dialog-button-done": "Končano",
        "upload-dialog-button-save": "Shrani",
        "upload-dialog-button-upload": "Naloži",
        "htmlform-cloner-create": "Dodaj več",
        "htmlform-cloner-delete": "Odstrani",
        "htmlform-cloner-required": "Zahtevana je vsaj ena vrednost.",
+       "htmlform-date-placeholder": "LLLL-MM-DD",
+       "htmlform-time-placeholder": "UU:MM:SS",
+       "htmlform-datetime-placeholder": "LLLL-MM-DD UU:MM:SS",
+       "htmlform-date-invalid": "Navedena vrednost ni prepoznan datum. Poskusite uporabiti obliko LLLL-MM-DD.",
+       "htmlform-time-invalid": "Navedena vrednost ni prepoznan čas. Poskusite uporabiti obliko UU:MM:SS.",
+       "htmlform-datetime-invalid": "Navedena vrednost ni prepoznan datum in čas. Poskusite uporabiti obliko LLLL-MM-DD UU:MM:SS.",
+       "htmlform-date-toolow": "Navedena vrednost je časovno pred najzgodnejšim dovoljenim datumom $1.",
+       "htmlform-date-toohigh": "Navedena vrednost je časovno po najpoznejšim dovoljenim datumom $1.",
+       "htmlform-time-toolow": "Navedena vrednost je časovno pred najzgodnejšim dovoljenim časom $1.",
+       "htmlform-time-toohigh": "Navedena vrednost je časovno po najpoznejšim dovoljenim časom $1.",
+       "htmlform-datetime-toolow": "Navedena vrednost je časovno pred najzgodnejšim dovoljenim datumom in časom $1.",
+       "htmlform-datetime-toohigh": "Navedena vrednost je časovno po najpoznejšim dovoljenim datumom in časom $1.",
        "htmlform-title-badnamespace": "[[:$1]] ni v imenskem prostoru »{{ns:$2}}«.",
        "htmlform-title-not-creatable": "»$1« je naslov strani, ki ga ni mogoče ustvariti",
        "htmlform-title-not-exists": "$1 ne obstaja.",
        "unlinkaccounts-success": "Račun smo razvezali.",
        "authenticationdatachange-ignored": "Sprememba overitvenih podatkov ni bila obdelana. Morda ni bil konfiguriran noben ponudnik?",
        "userjsispublic": "Pomnite: Podstrani JavaScript naj ne vsebujejo zaupnih podatkov, saj so vidne tudi drugim uporabnikom.",
-       "usercssispublic": "Pomnite: Podstrani CSS naj ne vsebujejo zaupnih podatkov, saj so vidne tudi drugim uporabnikom."
+       "usercssispublic": "Pomnite: Podstrani CSS naj ne vsebujejo zaupnih podatkov, saj so vidne tudi drugim uporabnikom.",
+       "restrictionsfield-badip": "Neveljaven IP-naslov ali obseg: $1",
+       "restrictionsfield-label": "Dovoljeni IP-obsegi:",
+       "restrictionsfield-help": "En IP-naslov ali CIDR-območje na vrstico. Da omogočite vse, uporabite<br><code>0.0.0.0/0</code><br><code>::/0</code>"
 }
index 8f0057f..0dd4408 100644 (file)
        "eauthentsent": "На вказану адресу електронної пошти відправлено лист підтвердження.\nЩоб отримувати надалі будь-які повідомлення, необхідно підтвердити, що обліковий запис належить справді Вам, за процедурою, описаною в листі.",
        "throttled-mailpassword": "Листа для оновлення пароля вже було надіслано електронною поштою протягом {{PLURAL:$1|1=останньої години|останніх $1 годин}}.\nДля попередження зловживань дозволено надсилати тільки одного листа оновлення пароля за {{PLURAL:$1|годину|$1 години|$1 годин}}.",
        "mailerror": "Помилка надсилання пошти: $1",
-       "acct_creation_throttle_hit": "Відвідувачі з вашої IP-адреси вже створили $1 {{PLURAL:$1|обліковий запис|облікових записи|облікових записів}} за останню добу, що є максимумом для цього відрізка часу.\nТаким чином, користувачі з цієї IP-адреси не можуть на цей момент створювати нових облікових записів.",
+       "acct_creation_throttle_hit": "Відвідувачі з вашої IP-адреси вже створили $1 {{PLURAL:$1|обліковий запис|облікові записи|облікових записів}} за останню $2, що є максимумом для цього відрізка часу.\nТаким чином, користувачі з цієї IP-адреси не можуть на цей момент створювати нових облікових записів.",
        "emailauthenticated": "Вашу адресу електронної пошти було підтверджено $2  о  $3.",
        "emailnotauthenticated": "Адресу вашої електронної пошти ще не підтверджено. Надсилання листів неможливе у жодній з наступних опцій.",
        "noemailprefs": "Вкажіть адресу електронної пошти, щоб уможливити наступні поштові функції вікі.",
        "passwordreset-emailelement": "Ім'я користувача: \n$1\n\nТимчасовий пароль: \n$2",
        "passwordreset-emailsentemail": "Якщо ця електронна адреса асоційована з вашим обліковим записом, то лист для відновлення пароля буде відправлено на неї.",
        "passwordreset-emailsentusername": "Якщо існує електронна адреса, яка асоційована з цим обліковим записом, на неї буде надіслано лист для відновлення пароля.",
-       "passwordreset-emailsent-capture2": "{{PLURAL:$1|Електронний лист|Електронні листи}} скидання паролю було надіслано. {{PLURAL:$1|Ім'я користувача і пароль|Список імен користувачів і паролів}} показано нижче.",
-       "passwordreset-emailerror-capture2": "Не вдалося надіслати листа {{GENDER:$2|користувачу|користувачці}}: $1 {{PLURAL:$3|Ім'я користувача і пароль|список імен користувачів і паролів}} показано нижче.",
+       "passwordreset-emailsent-capture2": "{{PLURAL:$1|Електронний лист|Електронні листи}} скидання паролю було надіслано. {{PLURAL:$1|Ім'я користувача і пароль|Список імен користувачів і паролів}} показано тут.",
+       "passwordreset-emailerror-capture2": "Не вдалося надіслати листа {{GENDER:$2|користувачу|користувачці}}: $1 {{PLURAL:$3|Ім'я користувача і пароль|список імен користувачів і паролів}} показано тут.",
        "passwordreset-nocaller": "Має бути надане джерело виклику",
        "passwordreset-nosuchcaller": "Джерело виклику не існує: $1",
        "passwordreset-ignored": "Скидання пароля не відбулося. Можливо, не було налашатовано надавача?",
        "unlinkaccounts-success": "Обліковий запис було відв'язано.",
        "authenticationdatachange-ignored": "Неопрацьована зміна облікових даних. Можливо, жоден з провайдерів не був налаштований?",
        "userjsispublic": "Будь ласка, зверніть увагу: підсторінки JavaScript не повинні містити конфіденційних даних, бо їх можуть бачити інші користувачі.",
-       "usercssispublic": "Будь ласка, зверніть увагу: підсторінки CSS не повинні містити конфіденційних даних, бо їх можуть бачити інші користувачі."
+       "usercssispublic": "Будь ласка, зверніть увагу: підсторінки CSS не повинні містити конфіденційних даних, бо їх можуть бачити інші користувачі.",
+       "restrictionsfield-badip": "Недійсна IP-адреса або діапазон: $1",
+       "restrictionsfield-label": "Дозволені діапазони IP-адрес:",
+       "restrictionsfield-help": "Одна IP-адреса або CIDR-діапазон на рядок. Щоб увімкнути все, використайте<br><code>0.0.0.0/0</code><br><code>::/0</code>"
 }
index bf2e212..210bfa8 100644 (file)
        "viewtalkpage": "تبادلۂ خیال دیکھیں",
        "otherlanguages": "دیگر زبانوں میں",
        "redirectedfrom": "($1 سے رجوع مکرر)",
-       "redirectpagesub": "لوٹایا گیا صفحہ",
+       "redirectpagesub": "رجوع مکرر",
        "redirectto": "رجوعِ مکرر از:",
        "lastmodifiedat": "اس صفحہ میں آخری بار مورخہ $1ء کو $2 بجے ترمیم کی گئی۔",
        "viewcount": "اِس صفحہ تک {{PLURAL:$1|ایک‌بار|$1 مرتبہ}} رسائی کی گئی",
        "createacct-yourpassword-ph": "پاس ورڈ درج کریں",
        "yourpasswordagain": "کلمۂ شناخت دوبارہ لکھیں",
        "createacct-yourpasswordagain": "پاس ورڈ کی تصدیق کریں",
-       "createacct-yourpasswordagain-ph": "پاس ورڈ پھر داخل کریں",
-       "userlogin-remembermypassword": "Ù\85جھÛ\92 Ø¯Ø§Ø®Ù\84 Ø±Ú©Ú¾Û\92",
+       "createacct-yourpasswordagain-ph": "پاس ورڈ دوبارہ درج کریں",
+       "userlogin-remembermypassword": "Ù\84اگ Ø§Ù\86 Ø¨Ø±Ù\82رار Ø±Ú©Ú¾Û\8cÚº",
        "userlogin-signwithsecure": "محفوظ رابطہ (کنکشن) استعمال کریں",
        "cannotlogin-title": "داخل نہیں ہو سکتے",
        "cannotlogin-text": "داخل ہونا ممکن نہیں۔",
        "createacct-emailrequired": "ای میل پتہ",
        "createacct-emailoptional": "برقی ڈاک پتا (اختیاری)",
        "createacct-email-ph": "اپنا برقی پتہ لکھیں",
-       "createacct-another-email-ph": "برقی پتہ لکھیں",
+       "createacct-another-email-ph": "برقی ڈاک پتا لکھیں",
        "createaccountmail": "عارضی پاسورڈ استعمال کریں اور اسے متعینہ برقی ڈاک پتہ پر ارسال کریں",
        "createaccountmail-help": "پاس ورڈ معلوم کیے بغیر کسی دوسرے شخص کا کھاتہ بنانے کے لیے اسے استعمال کیا جا سکتا ہے۔",
        "createacct-realname": "اصلی نام (اختیاری)",
        "createacct-another-submit": "کھاتہ بنائیں",
        "createacct-continue-submit": "کھاتہ سازی جاری رکھیں",
        "createacct-another-continue-submit": "کھاتہ سازی جاری رکھیں",
-       "createacct-benefit-heading": "{{SITENAME}} آپ جیسے لوگوں کی طرف سے بنایا گیا ہے ۔",
+       "createacct-benefit-heading": "{{SITENAME}} آپ جیسے علم دوست افراد کا مرہون منت ہے۔",
        "createacct-benefit-body1": "{{PLURAL:$1|ترمیم|ترامیم}}",
-       "createacct-benefit-body2": "$1 {{PLURAL:$1|صفحہ|صفحات}}",
-       "createacct-benefit-body3": "حالیہ {{PLURAL:$1|شرکت کرنے والا|شرکت کرنے والے}}",
+       "createacct-benefit-body2": "$1 {{PLURAL:$1|مضمون|مضامین}}",
+       "createacct-benefit-body3": "حالیہ {{PLURAL:$1|مشارکت کنندہ|مشارکت کنندگان}}",
        "badretype": "درج شدہ کلمۂ شناخت اصل سے مطابقت نہیں رکھتا۔",
        "usernameinprogress": "انتظار فرمائیے!<br />\nاس صارف نام سے کھاتہ بننے کا عمل ابھی جاری ہے۔",
        "userexists": "داخل کردہ اسم صارف پہلے سے مستعمل ہے۔\nبراہِ کرم! کوئی دوسرا اسم منتخب کیجئے۔",
        "summary": "خلاصہ:",
        "subject": "عنوان:",
        "minoredit": "معمولی ترمیم",
-       "watchthis": "اس صفحہ کو زیر نظر کیحیے",
+       "watchthis": "اس صفحہ کو زیر نظر کریں",
        "savearticle": "محفوظ",
        "savechanges": "تبدیلیاں محفوظ کریں",
        "publishpage": "شائع کریں",
        "revdelete-confirm": "برائے مہربانی! یقین دِہانی کرلیجئے کہ آپ واقعی ایسا کرنا چاہتے ہیں، آپ اِس کے نتائج سے باخبر ہیں، اور آپ یہ [[{{MediaWiki:Policy-url}}|پالیسی]] کے مطابق کررہے ہیں.",
        "revdelete-legend": "رویتی پابندیاں لگائیں",
        "revdelete-hide-text": "نظرثانی متن چھپاؤ",
-       "revdelete-hide-image": "Ù\85Ø´Ù\85Ù\88Ù\84اتÙ\90 Ù\85Ù\84Ù\81 Ú\86ھپاؤ",
+       "revdelete-hide-image": "Ù\81ائÙ\84 Ú©Û\92 Ù\85Ø´Ù\85Ù\88Ù\84ات Ú\86ھپائÛ\8cÚº",
        "revdelete-hide-name": "ہدف اور پیرامیٹرز کو چھپائیں",
        "revdelete-hide-comment": "ترمیمی تبصرہ چھپاؤ",
        "revdelete-hide-user": "ترمیم کار کا اسمِ صارف / آئی.پی پتہ چُھپاؤ",
        "searchprofile-everything-tooltip": "تمام مندرجات (بشمول تبادلۂ خیال صفحات) میں تلاش کریں",
        "searchprofile-advanced-tooltip": "حسب مرضی نام فضا میں تلاش کریں",
        "search-result-size": "$1 ({{PLURAL:$2|1 لفظ|$2 الفاظ}})",
-       "search-result-category-size": "{{PLURAL:$1|1 رُکن|$1 اراکین}} ({{PLURAL:$2|1 ذیلی زمرہ|$2 ذیلی زمرہ جات}}, {{PLURAL:$3|1 ملف|$3 ملفات}})",
+       "search-result-category-size": "{{PLURAL:$1|1 رُکن|$1 اراکین}} ({{PLURAL:$2|1 ذیلی زمرہ|$2 ذیلی زمرہ جات}}، {{PLURAL:$3|1 فائل|$3 فائلیں}})",
        "search-redirect": "(رجوع مکرر $1)",
        "search-section": "(قطعہ $1)",
        "search-category": "(زمرہ $1)",
        "prefs-watchlist-token": "زیر نظر فہرست کی کلید:",
        "prefs-misc": "دیگر",
        "prefs-resetpass": "پاس ورڈ تبدیل کریں",
-       "prefs-changeemail": "برقی ڈاک پتہ (e-mail address) تبدیل کریں",
+       "prefs-changeemail": "برقی ڈاک پتا تبدیل یا حذف کریں",
        "prefs-setemail": "برقی پتہ دیں",
        "prefs-email": "برقی خط کے اختیارات",
        "prefs-rendering": "ظاہریت",
        "prefs-help-realname": "حقیقی نام اختیاری ہے۔\nاگر آپ درج کریں تو اسے آپ کے کاموں کو آپ سے منسوب کرنے کے لیے استعمال کیا جائے گا۔",
        "prefs-help-email": "برقی ڈاک پتے کا اندراج اختیاری ہے، عموماً اس کی ضرورت اس وقت پڑتی ہے جب آپ اپنا پاس ورڈ بھول چکے ہوں اور نیا پاس ورڈ رکھنا چاہتے ہوں۔",
        "prefs-help-email-others": "یہ ممکن ہے کہ آپ دیگر صارفین کو اس بات کی اجازت دیں کہ وہ آپ کے صارف یا تبادلۂ خیال صفحہ پر موجود ربط کے ذریعہ آپ کو برقی خط بھیج سکیں۔\nجب صارفین اس طرح آپ سے رابطہ کریں گے تو انہیں آپ کا برقی ڈاک پتہ نظر نہیں آئے گا۔",
-       "prefs-help-email-required": "برقی ڈاک پتہ چاہئے.",
+       "prefs-help-email-required": "برقی ڈاک پتا درکار ہے۔",
        "prefs-info": "بنیادی معلومات",
        "prefs-i18n": "بین الاقوامیت",
        "prefs-signature": "دستخط",
        "autochange-username": "میڈیاویکی خودکار تبدیلیاں",
        "upload": "فائل اپلوڈ کریں",
        "uploadbtn": "فائل اپلوڈ کریں",
-       "reuploaddesc": "زبراثÙ\82اÙ\84 Ù\88رÙ\82Û\81 (Ù\81ارÙ\85) Ú©Û\8cجاÙ\86ب Ù\88اپسÛ\94",
+       "reuploaddesc": "اپÙ\84Ù\88Ú\88 Ù\85Ù\86سÙ\88Ø® Ú©Ø±Ú©Û\92 Ø§Ù¾Ù\84Ù\88Ú\88 Ù\81ارÙ\85 Ú©Û\8c Ø¬Ø§Ù\86ب Ù\88اپس Ø¬Ø§Ø¦Û\8cÚº",
        "upload-tryagain": "فائل کی تبدیل شدہ وضاحت روانہ کریں",
        "uploadnologin": "آپ داخل شدہ حالت میں نہیں",
        "uploadnologintext": "فائلیں اپلوڈ کرنے کے لیے براہ کرم $1 ہوں",
        "upload-permitted": "اجازت یافتہ فائلوں کی {{PLURAL:$2|قسم|قسمیں}}: $1",
        "upload-preferred": "ترجیحی فائلوں کی {{PLURAL:$2|قسم|قسمیں}}: $1",
        "upload-prohibited": "ممنوع فائلوں کی {{PLURAL:$2|قسم|قسمیں}}: $1",
-       "uploadlogpage": "Ù\86Ù\88شتÛ\82 Ø²Ø¨Ø±Ø§Ø«Ù\82اÙ\84 (اپ Ù\84Ù\88Ú\88 Ù\84اگ)",
-       "uploadlogpagetext": "درج Ø°Û\8cÙ\84 Ù\85Û\8cÚº Ø­Ø§Ù\84Û\8cÛ\81 Ø²Ø¨Ø±Ø§Ø«Ù\82اÙ\84 (اپ Ù\84Ù\88Ú\88) Ú©Û\8c Ú¯Ø¦Û\8c Ø§Ù\85Ù\84اÙ\81 (Ù\81ائÙ\84Ù\88Úº) Ú©Û\8c Ù\81Û\81رست Ø¯Û\8c Ú¯Ø¦Û\8c Û\81Û\92۔",
+       "uploadlogpage": "Ù\86Ù\88شتÛ\81 Ø§Ù¾Ù\84Ù\88Ú\88",
+       "uploadlogpagetext": "Ø°Û\8cÙ\84 Ù\85Û\8cÚº Ø­Ø§Ù\84Û\8cÛ\81 Ø§Ù¾Ù\84Ù\88Ú\88 Ú©Ø±Ø¯Û\81 Ù\81ائÙ\84Ù\88Úº Ú©Û\8c Ù\81Û\81رست Ù\85Ù\88جÙ\88د Û\81Û\92Û\94\nÙ\85زÛ\8cد Ø¨ØµØ±Û\8c Ø¬Ø§Ø¦Ø²Û\92 Ú©Û\92 Ù\84Û\8cÛ\92 [[Special:NewFiles|Ù\86ئÛ\8c Ù\81ائÙ\84Ù\88Úº Ú©Ø§ Ù\86گارخاÙ\86Û\81]] Ù\85Ù\84احظÛ\81 Ù\81رÙ\85ائÛ\8cÚº۔",
        "filename": "فائل کا نام",
        "filedesc": "خلاصہ",
        "fileuploadsummary": "خلاصہ :",
        "filereuploadsummary": "فائل کی تبدیلیاں:",
        "filestatus": "کاپی رائٹ کی صورت حال:",
        "filesource": "ذرائع",
-       "ignorewarning": "انتباہ نظرانداز کرتے ہوۓ بہرصورت ملف (فائل) کو محفوظ کرلیا جاۓ۔",
+       "ignorewarning": "انتباہ نظر انداز کرتے ہوئے فائل کو بہرصورت محفوظ کر لیا جائے",
        "ignorewarnings": "ہر انتباہ نظرانداز کردیا جاۓ۔",
        "minlength1": "فائل کے ناموں میں کم از کم ایک حرف ہونا ضروری ہے۔",
        "illegalfilename": "اس فائل کے نام \"$1\" میں ایسے حروف موجود ہیں جو صفحہ کے عنوانات میں ممنوع ہیں۔\nبراہ کرم فائل کا نام تبدیل کرکے دوبارہ اپلوڈ کرنے کی کوشش کریں۔",
        "filename-toolong": "فائل کے نام 240 بائٹ سے زیادہ طویل نہ ہوں۔",
-       "badfilename": "Ù\85Ù\84Ù\81 (Ù\81ائÙ\84) Ú©Ø§ Ù\86اÙ\85 \"$1\" Ø\8c ØªØ¨Ø¯Û\8cÙ\84 Ú©Ø±Ø¯Û\8cا Ú¯Û\8cا۔",
+       "badfilename": "Ù\81ائÙ\84 Ú©Ø§ Ù\86اÙ\85 Â«$1» Ú©Ø± Ø¯Û\8cا Ú¯Û\8cا Û\81Û\92۔",
        "filetype-mime-mismatch": "فائل کی توسیع «$1.‎» فائل کی MIME قسم ($2) کے مطابق نہیں۔",
        "filetype-badmime": "MIME قسم \"$1\" کی فائلوں کو اپلوڈ کرنے کی اجازت نہیں ہے۔",
        "filetype-bad-ie-mime": "اس فائل کو اپلوڈ نہیں کیا جا سکتا کیونکہ انٹرنیٹ ایکسپلورر اسے «$1» سمجھے گا جس کی اجازت نہیں اور اس نوع کی فائل کے خطرناک ہونے کا احتمال ہے۔",
        "file-exists-duplicate": "پیش نظر فائل درج ذیل {{PLURAL:$1|فائل|فائلوں}} کی نقل ہے:",
        "file-deleted-duplicate": "اس فائل ([[:$1]]) سے ملتی جلتی دوسری فائل کو پہلے حذف کیا جا چکا ہے۔\nچنانچہ اسے دوبارہ اپلوڈ کرنے سے قبل اُس پرانی فائل کے حذف کا تاریخچہ جانچ لیں۔",
        "file-deleted-duplicate-notitle": "اس فائل سے ملتی جلتی دوسری فائل کو پہلے حذف کیا اور اس عنوان کو ممنوع قرار دیا جا چکا ہے۔\nاسے دوبارہ اپلوڈ کرنے سے قبل کسی ایسے شخص سے اس صورت حال کا جائزہ لینے کی درخواست کریں جسے ممنوع فائلوں کی معلومات تک رسائی حاصل ہو۔",
-       "uploadwarning": "اÙ\86تباÛ\81 Ø¨Û\81 Ø³Ù\84سÙ\84Û\82 Ø²Ø¨Ø±Ø§Ø«Ù\82اÙ\84",
+       "uploadwarning": "اپÙ\84Ù\88Ú\88 Ø§Ù\86تباÛ\81",
        "uploadwarning-text": "ذیل میں موجود فائل کی وضاحت میں تبدیلی کریں اور دوبارہ کوشش کریں۔",
        "savefile": "فائل محفوظ کریں",
        "uploaddisabled": "اپلوڈ غیر فعال ہے۔",
        "uploadinvalidxml": "اپلوڈ کردہ فائل میں موجود ایکس ایم ایل کا تجزیہ نہیں کیا جا سکا۔",
        "uploadvirus": "اس فائل میں وائرس موجود ہے!\nتفصیلات: $1",
        "upload-source": "اصل فائل",
-       "sourcefilename": "اسÙ\85 Ù\85Ù\84Ù\81 (Ù\81ائÙ\84) Ú©Ø§ Ù\85Ù\86بع:",
+       "sourcefilename": "اصÙ\84 Ù\81ائÙ\84 Ú©Ø§ Ù\86اÙ\85:",
        "sourceurl": "اصل یوآرایل",
-       "destfilename": "تعین شدہ اسم ملف:",
+       "destfilename": "ہدف فائل کا نام:",
        "upload-maxfilesize": "فائل کا زیادہ سے زیادہ حجم: $1",
        "upload-description": "فائل کی وضاحت",
        "upload-options": "اپلوڈ کے اختیارات",
        "upload-dialog-disabled": "اس ویکی پر اس ڈائیلاگ سے فائل اپ لوڈز غیر فعال ہیںَ",
        "upload-dialog-title": "فائل اپلوڈ کریں",
        "upload-dialog-button-cancel": "منسوخ",
+       "upload-dialog-button-back": "پیچھے جائیں",
        "upload-dialog-button-done": "مکمل",
        "upload-dialog-button-save": "محفوظ",
        "upload-dialog-button-upload": "اپلوڈ",
        "upload-form-label-infoform-name": "نام",
        "upload-form-label-infoform-description": "تفصیل",
        "upload-form-label-usage-title": "استعمال",
-       "upload-form-label-usage-filename": "Ù\85Ù\84Ù\81 نام",
+       "upload-form-label-usage-filename": "Ù\81ائÙ\84 Ú©Ø§ نام",
        "upload-form-label-own-work": "یہ میرا ذاتی کام ہے",
        "upload-form-label-infoform-categories": "زمرہ جات",
        "upload-form-label-infoform-date": "تاریخ",
        "listfiles-summary": "اس خصوصی صفحہ میں تمام اپلوڈ کردہ فائلیں نظر آئیں گی۔",
        "listfiles_search_for": "میڈیا کے نام کو تلاش کریں:",
        "listfiles-userdoesnotexist": "«$1» کے نام سے کھاتہ موجود نہیں۔",
-       "imgfile": "Ù\85Ù\84Ù\81",
-       "listfiles": "فہرست فائل",
+       "imgfile": "Ù\81ائÙ\84",
+       "listfiles": "فائلوں کی فہرست",
        "listfiles_thumb": "تھمب نیل",
        "listfiles_date": "تاریخ",
        "listfiles_name": "نام",
        "listfiles_user": "صارف",
        "listfiles_size": "حجم",
-       "listfiles_description": "تفصیل",
-       "listfiles_count": "Ù\88رÚ\98Ù\86",
+       "listfiles_description": "وضاحت",
+       "listfiles_count": "Ù\86سخÛ\92",
        "listfiles-show-all": "تصویروں کے پرانے نسخے شامل کریں",
        "listfiles-latestversion": "موجودہ ورژن",
        "listfiles-latestversion-yes": "ہاں",
        "duplicatesoffile": "ذیل میں موجود {{PLURAL:$1|فائل|فائلیں}} اس فائل کی نقل {{PLURAL:$1|ہے|ہیں}}\n([[Special:FileDuplicateSearch/$2|مزید تفصیلات]]):",
        "sharedupload": "یہ فائل $1 میں موجود ہے، نیز ممکن ہے دیگر منصوبوں میں بھی مستعمل ہو۔",
        "sharedupload-desc-there": "یہ فائل $1 میں موجود ہے، نیز ممکن ہے دیگر منصوبوں میں بھی مستعمل ہو۔\nمزید معلومات کے لیے براہ کرم [$2 فائل کا صفحۂ وضاحت] ملاحظہ فرمائیں۔",
-       "sharedupload-desc-here": "Û\8cÛ\81 Ù\85Ù\84Ù\81 $1 Ø³Û\92 Û\81Û\92 Ø§Ù\88ر Ø¯Ù\88سرÛ\92 Ù\85Ù\86صÙ\88بÙ\88Úº Ù\85Û\8cÚº Ø§Ø³ØªØ¹Ù\85اÙ\84 Û\81Ù\88سکتا Û\81Û\92Û\94\nاÙ\90س Ú©Û\92 [$2 Ù\85Ù\84Ù\81اتÛ\8c ØµÙ\81Ø­Û\82 Ù\88ضاحت] Ø³Û\92 ØªÙ\81صÛ\8cÙ\84 Ø¯Ø±Ø¬ Ø°Û\8cÙ\84 ہے۔",
+       "sharedupload-desc-here": "Û\8cÛ\81 Ù\81ائÙ\84 $1 Ú©Û\8c Û\81Û\92 Ù\86Û\8cز Ù\85Ù\85Ú©Ù\86 Û\81Û\92 Ø¯Ù\88سرÛ\92 Ù\85Ù\86صÙ\88بÙ\88Úº Ù\85Û\8cÚº Ø¨Ú¾Û\8c Ø²Û\8cر Ø§Ø³ØªØ¹Ù\85اÙ\84 Û\81Ù\88Û\94\nاÙ\90س Ú©Û\92 [$2 ØµÙ\81Ø­Û\82 Ù\88ضاحت] Ù\85Û\8cÚº Ø¯Ø±Ø¬ Ù\88ضاحت Ø°Û\8cÙ\84 Ù\85Û\8cÚº Ù\85Ù\88جÙ\88د ہے۔",
        "sharedupload-desc-edit": "یہ فائل $1 میں موجود ہے، نیز ممکن ہے دیگر منصوبوں میں بھی مستعمل ہو۔\nاگر آپ [$2 فائل کے صفحۂ وضاحت] میں موجود معلومات میں ترمیم کرنا چاہیں تو وہاں کر سکتے ہیں۔",
        "sharedupload-desc-create": "یہ فائل $1 میں موجود ہے، نیز ممکن ہے دیگر منصوبوں میں بھی مستعمل ہو۔\nاگر آپ [$2 فائل کے صفحۂ وضاحت] میں موجود معلومات میں ترمیم کرنا چاہیں تو وہاں کر سکتے ہیں۔",
        "filepage-nofile": "اس نام سے کوئی فائل موجود نہیں ہے۔",
        "confirmdeletetext": "آپ اس صفحے کو اس سے ملحقہ تاریخچہ سمیت حذف کر رہے ہیں۔ براہ مہربانی اس بات کی تصدیق کر لیں کہ آپ اس عمل کے نتائج سے بخوبی آگاہ ہیں، اور یہ بھی جانچ لیں کہ آیا آپ کا یہ اقدام [[{{MediaWiki:Policy-url}}|حکمت عملی]] کے دائرے میں ہے یا نہیں۔",
        "actioncomplete": "اقدام تکمیل کو پہنچا",
        "actionfailed": "عمل ناکام",
-       "deletedtext": "\"$1\" کو حذف کر دیا گیا ہے ۔\nحالیہ حذف شدگی کے تاریخ نامہ کیلیۓ  $2  دیکھیۓ",
+       "deletedtext": "\"$1\" کو حذف کر دیا گیا ہے۔\nحالیہ حذف شدگیوں کی فہرست دیکھنے کے لیے $2 ملاحظہ فرمائیں۔",
        "dellogpage": "نوشتۂ حذف شدگی",
        "dellogpagetext": "حالیہ حذف شدگی کی فہرست درج ذیل ہے۔",
        "deletionlog": "نوشتۂ حذف شدگی",
        "undeleteinvert": "انتخاب بالعکس",
        "undeletecomment": "وجہ:",
        "undeletedrevisions": "{{PLURAL:$1|1 نظر ثانی|$1 نظر ثانیاں}} بحال",
-       "undeletedrevisions-files": "{{PLURAL:$1|1 Ù\86ظر Ø«Ø§Ù\86Û\8c|$1 Ù\86ظر Ø«Ø§Ù\86Û\8cاں}} Ø§Ù\88ر {{PLURAL:$2|1 Ù\85Ù\84Ù\81|$2 Ø§Ù\85Ù\84اÙ\81}} بحال",
-       "undeletedfiles": "{{PLURAL:$1|1 Ù\85Ù\84Ù\81|$1 Ø§Ù\85Ù\84اÙ\81}} Ø¨Ø­Ø§Ù\84",
+       "undeletedrevisions-files": "{{PLURAL:$1|1 Ù\86سخÛ\81|$1 Ù\86سخÛ\92}} Ø§Ù\88ر {{PLURAL:$2|1 Ù\81ائÙ\84|$2 Ù\81ائÙ\84Û\8cÚº}} بحال",
+       "undeletedfiles": "{{PLURAL:$1|1 Ù\81ائÙ\84|$1 Ù\81ائÙ\84}} Ø¨Ø­Ø§Ù\84 Ú©Û\8c {{PLURAL:$1|گئÛ\8c|گئÛ\8cÚº}}",
        "cannotundelete": "کلی یا جزوی طور پر بحالی کا اقدام ناکام رہا:\n$1",
        "undeletedpage": "<strong>$1 کو بحال کر دیا گیا</strong>\n\nحالیہ حذف شدگیوں اور بحالیوں کا نوشتہ دیکھنے کے لیے [[Special:Log/delete|نوشتہ حذف شدگی]] ملاحظہ فرمائیں۔",
        "undelete-header": "حالیہ حذف شدہ صفحات کے لیے [[Special:Log/delete|نوشتۂ حذف شدگی]] دیکھیں۔",
        "sp-contributions-hideminor": "معمولی ترامیم چھپائیں",
        "sp-contributions-submit": "تلاش",
        "whatlinkshere": "مربوط صفحات",
-       "whatlinkshere-title": "\"$1\" سے مربوط صفحات",
+       "whatlinkshere-title": "«$1» سے مربوط صفحات",
        "whatlinkshere-page": "صفحہ:",
        "linkshere": "<strong>[[:$1]]</strong> سے درج ذیل صفحات مربوط ہیں:",
        "nolinkshere": "<strong>[[:$1]]</strong> سے کوئی صفحہ مربوط نہیں ہے۔",
        "whatlinkshere-next": "{{PLURAL:$1|اگلا|اگلے $1}}",
        "whatlinkshere-links": "→ روابط",
        "whatlinkshere-hideredirs": "رجوع مکررات $1",
-       "whatlinkshere-hidetrans": "$1 استعمالات",
+       "whatlinkshere-hidetrans": "استعمالات $1",
        "whatlinkshere-hidelinks": "روابط $1",
        "whatlinkshere-hideimages": "تصویر کے روابط $1",
        "whatlinkshere-filters": "مقطارات",
        "thumbnail_dest_directory": "مقصود ڈائرکٹری کو بنایا نہیں جا سکا",
        "thumbnail_image-type": "تصویر کی نوعیت معاونت یافتہ نہیں ہے",
        "thumbnail_image-missing": "معلوم ہوتا ہے کہ یہ فائل موجود نہیں: $1",
+       "thumbnail_image-failure-limit": "حال میں اس تھمب نیل کو بنانے کی ($1 یا زائد) متعدد ناکام کوششیں کی گئی ہیں۔ براہ کرم کچھ دیر بعد دوبارہ کوشش کریں۔",
        "import": "درآمد صفحات",
        "importinterwiki": "دوسرے ویکی سے درآمد کریں",
        "import-interwiki-text": "درآمد کرنے کے لیے ویکی اور صفحہ کا عنوان منتخب کریں۔\nنسخوں کی تاریخ اور نسخہ نویسوں کے نام محفوظ رکھے جائیں گے۔\nدوسری ویکیوں سے درآمد کردہ ہر چیز کو [[Special:Log/import|نوشتہ درآمد]] میں درج کیا جاتا ہے۔",
        "import-mapping-subpage": "درج ذیل صفحہ کے ذیلی صفحات کے طور پر درآمد کریں:",
        "import-upload-filename": "فائل کا نام:",
        "import-comment": "تبصرہ:",
+       "importtext": "براہ کرم [[Special:Export|برآمد کی سہولت]] کے ذریعہ اصل ویکی سے فائل برآمد کریں۔\nاور اسے اپنے کمپیوٹر میں محفوظ کرکے یہاں اپلوڈ کریں۔",
        "importstart": "صفحات درآمد کیے جا رہے ہیں۔۔۔",
        "import-revision-count": "$1 {{PLURAL:$1|نسخہ|نسخے}}",
        "importnopages": "درآمد کرنے کے لیے کوئی صفحہ نہیں ہے۔",
        "importcantopen": "درآمد فائل کھل نہیں سکی",
        "importbadinterwiki": "غلط بین الویکی ربط",
        "importsuccess": "درآمد مکمل!",
+       "importnosources": "کسی ایسی ویکی کا اندراج نہیں کیا گیا جہاں سے درآمد کرنا ہے اور تاریخچے کے براہ راست اپلوڈ غیر فعال ہیں۔",
        "importnofile": "کسی درآمد فائل کو اپلوڈ نہیں کیا گیا۔",
+       "importuploaderrorsize": "درآمد فائل کی اپلوڈ ناکام ہوئی۔\nفائل اپلوڈ کے اجازت یافتہ حجم سے بڑی ہے۔",
+       "importuploaderrorpartial": "درآمد فائل کی اپلوڈ ناکام ہوئی۔\nاس فائل کا محض ایک حصہ اپلوڈ ہوا۔",
+       "importuploaderrortemp": "درآمد فائل کی اپلوڈ ناکام ہوئی۔\nعارضی فولڈر موجود نہیں۔",
+       "import-parse-failure": "درآمد شدہ ایکس ایم ایل کا تجزیہ ناکام",
        "import-noarticle": "درآمد کرنے کے لیے کوئی صفحہ موجود نہیں!",
+       "import-nonewrevisions": "کسی نسخے کو درآمد نہیں کیا گیا (شاید وہ سب پہلے سے موجود ہیں یا کسی نقص کی بنا پر چھوڑ دیے گئے ہیں)۔",
+       "xml-error-string": "سطر نمبر $2، ستون نمبر $3 میں $1 ($4 بائٹ): $5",
        "import-upload": "ایکس ایم ایل ڈیٹا اپلوڈ کریں",
+       "import-token-mismatch": "معذرت! نشست کے مواد میں خامی کی وجہ سے آپ کی  ترمیم مکمل نہیں ہو سکی۔\n\nشاید آپ اپنے کھاتے سے خارج ہو گئے ہیں۔ <strong>براہ کرم اس بات کی تصدیق کر لیں کہ آپ داخل ہیں اور دوبارہ کوشش کریں۔</strong> اگر آپ کو پھر بھی مشکل پیش آرہی ہو تو ایک بار [[Special:UserLogout|خارج ہو کر]] واپس داخل ہو جائیں اور اپنے براؤزر کو جانچ لیں کہ آیا وہ اس سائٹ کی کوکیز اخذ کر رہا ہے یا نہیں۔",
        "import-invalid-interwiki": "اس ویکی سے درآمد نہیں کیا جا سکتا۔",
        "import-error-edit": "صفحہ «$1» درآمد نہیں کیا جا سکا کیونکہ آپ کو اس میں ترمیم کرنے کی اجازت نہیں ہے۔",
        "import-error-create": "صفحہ «$1» درآمد نہیں کیا جا سکا کیونکہ آپ کو اسے تخلیق کرنے کی اجازت نہیں ہے۔",
        "import-error-interwiki": "صفحہ «$1» درآمد نہیں کیا جا سکا کیونکہ اس کا نام بیرونی ربط (بین الویکی) کے لیے محفوظ ہے۔",
        "import-error-special": "صفحہ «$1» درآمد نہیں کیا جا سکا کیونکہ یہ اس خصوصی نام فضا سے متعلق ہے جس میں صفحات بنانے کی اجازت نہیں۔",
        "import-error-invalid": "صفحہ «$1» درآمد نہیں کیا جا سکا کیونکہ درآمد کے بعد اس صفحہ کا جو نام ہوگا وہ اس ویکی پر نادرست ہے۔",
+       "import-error-unserialize": "صفحہ «$1» کے نسخہ $2 کے تسلسل کو ختم نہیں کیا جا سکا۔ اس نسخے کے متعلق اطلاع دی گئی ہے کہ اس میں مواد کے ماڈل $3 کو $4 کے تسلسل کے طور پر استعمال کیا گیا تھا۔",
+       "import-error-bad-location": "نسخہ $2 کو جس میں مواد کا ماڈل $3 زیر استعمال ہے اس ویکی کے \"$1\" میں نہیں رکھا جا سکا، کیونکہ اس صفحہ کا ماڈل اس ماڈل سے مختلف ہے۔",
        "import-options-wrong": "غلط {{PLURAL:$2|اختیار|اختیارات}}: <nowiki>$1</nowiki>",
        "import-rootpage-invalid": "درج کردہ ماخذی صفحہ کا عنوان نادرست ہے۔",
+       "import-rootpage-nosubpage": "اصل صفحہ کی نام فضا \"$1\" میں ذیلی صفحات کی اجازت نہیں۔",
        "importlogpage": "نوشتہ درآمد",
+       "importlogpagetext": "دوسری ویکیوں سے تاریخچہ سمیت صفحوں کی انتظامی درآمد کے اقدامات۔",
        "import-logentry-upload-detail": "$1 {{PLURAL:$1|نسخہ|نسخے}} درآمد {{PLURAL:$1|کیا گیا|کیے گئے}}",
        "import-logentry-interwiki-detail": "$2 سے $1 {{PLURAL:$1|نسخہ|نسخے}} درآمد {{PLURAL:$1|کیا گیا|کیے گئے}}",
        "javascripttest": "جاوا اسکرپٹ کی آزمائش",
        "pageinfo-category-total": "اراکین کی مجموعی تعداد",
        "pageinfo-category-pages": "تعداد صفحات",
        "pageinfo-category-subcats": "تعداد ذیلی زمرہ جات",
-       "pageinfo-category-files": "تعداد املاف",
+       "pageinfo-category-files": "فائلوں کی تعداد",
        "markaspatrolleddiff": "بطور مراجعت شدہ نشان زد کریں",
        "markaspatrolledtext": "اس صفحہ کو بطور مراجعت شدہ نشان زد کریں",
        "markaspatrolledtext-file": "فائل کے اس نسخے کو مراجعت شدہ نشان زد کریں",
        "file-info": "فائل کا حجم: $1، MIME قسم: $2",
        "file-info-size": "\n$1 × $2 پکسل، فائل کا حجم: $3، MIME قسم: $4",
        "file-info-size-pages": "$1 × $2 پکسل، فائل کا حجم: $3، MIME قسم: $4، $5 {{PLURAL:$5|صفحہ|صفحات}}",
-       "file-nohires": "اس Ø³Û\92 Ø¨Ú\91Û\8c ØªØµÙ\85Û\8cÙ\85 دستیاب نہیں۔",
+       "file-nohires": "اس Ø³Û\92 Ø²Û\8cادÛ\81 Ø±Û\8cزÙ\88Ù\84Û\8cÙ\88Ø´Ù\86 دستیاب نہیں۔",
        "svg-long-desc": "ایس وی جی فائل، ابعاد $1 × $2 پکسل، فائل کا حجم: $3",
        "svg-long-desc-animated": "متحرک ایس وی جی فائل، ابعاد $1 × $2 پکسل، فائل کا حجم: $3",
        "svg-long-error": "نادرست ایس وی جی فائل: $1",
        "saturday-at": "سنیچر بوقت $1",
        "sunday-at": "اتوار بوقت $1",
        "yesterday-at": "گزشتہ کل بوقت $1",
-       "bad_image_list": "شکلبند درج ذیل ہے:\n\nصرف فہرستی عناصر (* سے شروع ہونے والی لکیری) شامل کی جاتی ہیں۔\nکسی لکیر میں پہلا ربط کوئی خراب ملف کا ہونا چاہئے۔\nاُسی لکیر میں باقی آنے والے ربط کو مستثنیٰ قرار دیا جاتا ہے، مثلاً صفحات جہاں ملف لکیر کے وسط میں آسکتا ہے۔",
+       "bad_image_list": "فارمیٹ درج ذیل ہے:\n\nمحض فہرست میں موجود مندرجات (* سے شروع ہونے والی سطریں) شامل سمجھے جائیں گے۔\nسطر میں پہلا ربط کسی خراب فائل کا ہونا لازمی ہے۔\nاُسی سطر کے بقیہ روابط کو مستثنیٰ سمجھا جائے گا، مثلاً وہ صفحات جن میں فائل سطر میں موجود ہوں۔",
        "metadata": "میٹا ڈیٹا",
-       "metadata-help": "اِس فائل میں اِضافی معلومات شامل ہیں، جو کہ شاید اُس رقمی کیمرے یا سکینر سے آئے ہیں جس کے ذریعے یہ فائل بنائی گئی تھی۔\nاگر فائل اپنی اصل حالت میں نہیں رہی ہے تو کچھ تفصیلات ترمیم شدہ فائل کی مکمل طور پر عکاسی نہیں کر پائیں گی۔",
+       "metadata-help": "اِس فائل میں اِضافی معلومات شامل ہیں، جو شاید اُس ڈیجیٹل کیمرے یا سکینر سے آئی ہیں جس کے ذریعے یہ فائل بنائی گئی تھی۔\nاگر فائل اپنی اصل حالت میں نہ ہو تو کچھ معلومات ترمیم شدہ فائل کی مکمل طور پر عکاسی نہیں کر پائیں گی۔",
        "metadata-expand": "تفصیلی معلومات دکھائیں",
        "metadata-collapse": "طویل تفاصیل چھپاؤ",
        "metadata-fields": "تصویر کے میٹاڈیٹا کے وہ خانے جو اس پیغام میں درج ہیں وہ تصویر کے صفحے پر شامل ہوتے ہیں نیز یہ اس وقت ظاہر ہوتے ہیں جب میٹاڈیٹا کو وسیع کیا جائے۔\nالبتہ دیگر خانے ابتدائی طور پر پوشیدہ ہوتے ہیں۔\n* make\n* model\n* datetimeoriginal\n* exposuretime\n* fnumber\n* isospeedratings\n* focallength\n* artist\n* copyright\n* imagedescription\n* gpslatitude\n* gpslongitude\n* gpsaltitude",
        "exif-jpeginterchangeformatlength": "JPEG ڈیٹا کے بائٹ",
        "exif-whitepoint": "سفید نقطہ کے رنگ",
        "exif-primarychromaticities": "اساسیات کے رنگ",
-       "exif-ycbcrcoefficients": "Ù\81ضائÛ\92 Ø±Ù\86Ú¯ Ú©Û\8c Ù\85Û\8cٹرکس ØªØ¨Ø¯Û\8cÙ\84Û\8c Ú©Û\92 Ø´Ø±Ø­ Ù\82در",
+       "exif-ycbcrcoefficients": "Ù\81ضائÛ\92 Ø±Ù\86Ú¯ Ú©Û\8c Ù\85Û\8cٹرکس ØªØ¨Ø¯Û\8cÙ\84Û\8c Ú©Û\8c Ù\85Ù\82دارÛ\8cÚº",
        "exif-referenceblackwhite": "سیاہ و سفید جوالے کی قدروں کی جوڑی",
        "exif-datetime": "فائل کی تبدیلی کی تاریخ اور وقت",
        "exif-imagedescription": "تصویر کا عنوان",
        "exif-gpslatitude": "عرض البلد",
        "exif-gpslongituderef": "مشرقی یا مغربی طول البلد",
        "exif-gpslongitude": "طول البلد",
-       "exif-gpsaltituderef": "اتفاع کا حوالہ",
+       "exif-gpsaltituderef": "ارتÙ\81اع Ú©Ø§ Ø­Ù\88اÙ\84Û\81",
        "exif-gpsaltitude": "ارتفاع",
        "exif-gpstimestamp": "جی پی ایس وقت (جوہری گھڑی)",
        "exif-gpssatellites": "پیمائش کے لیے مستعمل مصنوعی سیارے",
        "exif-originalimageheight": "تراشنے سے قبل تصویر کی لمبائی",
        "exif-originalimagewidth": "تراشنے سے قبل تصویر کی چوڑائی",
        "exif-compression-1": "غیر کمپریس شدہ",
+       "exif-compression-2": "CCITT گروپ 3 1 - ہف مین رن کی تبدیل شدہ لمبائی کی ابعادی اینکوڈنگ",
+       "exif-compression-3": "CCITT گروپ 3 کے فیکس کی اینکوڈنگ",
+       "exif-compression-4": "CCITT گروپ 4 کے فیکس کی اینکوڈنگ",
        "exif-copyrighted-true": "کاپی رائٹ شدہ",
        "exif-copyrighted-false": "کاپی رائٹ کی صورت حال متعین نہیں کی گئی",
        "exif-photometricinterpretation-1": "سیاہ اور سفید (سیاہ 0 ہے)",
        "exif-scenecapturetype-2": "عمودی انداز",
        "exif-scenecapturetype-3": "رات کا منظر",
        "exif-gaincontrol-0": "کچھ نہیں",
+       "exif-gaincontrol-1": "لو گین اپ",
+       "exif-gaincontrol-2": "ہائی گین اپ",
+       "exif-gaincontrol-3": "لو گین ڈاؤن",
+       "exif-gaincontrol-4": "ہائی گین ڈاؤن",
        "exif-contrast-0": "عام",
        "exif-contrast-1": "نرم",
        "exif-contrast-2": "سخت",
        "exif-saturation-0": "عام",
+       "exif-saturation-1": "سیال رنگ",
+       "exif-saturation-2": "ٹھوس رنگ",
        "exif-sharpness-0": "عام",
        "exif-sharpness-1": "نرم",
        "exif-sharpness-2": "سخت",
        "exif-gpsaltitude-above-sealevel": "سطح سمندر سے $1 {{PLURAL:$1|میٹر}} بلند",
        "exif-gpsaltitude-below-sealevel": "سطح سمندر سے $1 {{PLURAL:$1|میٹر}} نیچے",
        "exif-gpsstatus-a": "پیمائش جاری ہے",
+       "exif-gpsstatus-v": "پیمائش پذیری",
+       "exif-gpsmeasuremode-2": "دو ابعادی پیمائش",
+       "exif-gpsmeasuremode-3": "سہ ابعادی پیمائش",
        "exif-gpsspeed-k": "کلو میٹر فی گھنٹہ",
        "exif-gpsspeed-m": "میل فی گھنٹہ",
        "exif-gpsspeed-n": "گرہیں",
        "exif-gpsdirection-t": "اصلی سمت",
        "exif-gpsdirection-m": "مقناطیسی سمت",
        "exif-ycbcrpositioning-1": "وسط",
+       "exif-ycbcrpositioning-2": "مشترکہ منظر کشی",
        "exif-dc-contributor": "ترمیم کنندگان",
+       "exif-dc-coverage": "میڈیا کی مکانی یا زمانی وسعت",
        "exif-dc-date": "تاریخ",
        "exif-dc-publisher": "ناشر",
        "exif-dc-relation": "متعلقہ میڈیا",
        "monthsall": "تمام",
        "confirmemail": "اپنے برقی پتہ کی تصدیق کریں",
        "confirmemail_noemail": "آپ نے [[Special:Preferences|اپنی ترجیحات]] میں درست برقی ڈاک پتا نہیں دیا ہے۔",
+       "confirmemail_text": "{{SITENAME}} میں موجود برقی خط کی سہولتوں کو استعمال کرنے کے لیے آپ کے برقی ڈاک پتے کی تصدیق ضروری ہے۔\nاپنے پتے پر تصدیقی ڈاک روانہ کرنے کے لیے ذیل میں موجود بٹن پر کلک کریں۔\nموصولہ برقی خط میں آپ کو کوڈ پر مشتمل ایک ربط نظر آئے گا۔\nچنانچہ اپنے بڑقی ڈاک پتے کی تصدیق کے لیے اس ربط کو اپنے براؤزر میں کھولیں۔",
+       "confirmemail_pending": "آپ کو تصدیقی کوڈ پہلے ہی روانہ کیا جا چکا ہے۔\nاگر آپ نے ابھی اپنا کھاتہ بنایا ہے تو نئے کوڈ کی درخواست دینے سے قبل اس کے موصول ہونے کا کچھ دیر انتظار کر لیں۔",
        "confirmemail_send": "تصدیقی کوڈ بھیجیں",
        "confirmemail_sent": "تصدیقی برقی خط بھیجا گیا ہے۔",
        "confirmemail_oncreate": "آپ کے برقی ڈاک پتے پر تصدیقی کوڈ بھیجا گیا ہے۔\nیہ کوڈ داخل ہونے کے لیے ضروری نہیں، تاہم اس ویکی میں برقی ڈاک پر مبنی کسی سہولت کو فعال کرنے سے قبل آپ کو اس کوڈ کی ضرورت پڑے گی۔",
        "confirmemail_success": "آپ کے برقی ڈاک پتے کی تصدیق ہو چکی ہے۔\nاب آپ اپنے کھاتے میں [[Special:UserLogin|داخل ہو سکتے ہیں]]۔",
        "confirmemail_loggedin": "اب آپ کے برقی ڈاک پتے کی تصدیق ہو چکی ہے۔",
        "confirmemail_subject": "{{SITENAME}} کی جانب سے برقی ڈاک پتے کا تصدیقی پیغام",
+       "confirmemail_body": "کسی نے، غالباً آپ نے، اس آئی پی پتے $1 سے {{SITENAME}} میں «$2» کے نام سے کھاتہ بنایا اور اسی برقی ڈاک پتے کو استعمال کیا ہے۔\n\nاس بات کی تصدیق کے لیے کہ یہ کھاتہ آپ ہی کا ہے نیز {{SITENAME}} میں برقی خط کی سہولتوں کو فعال کرنے کے لیے ذیل میں موجود ربط کو اپنے براؤزر میں کھولیں:\n\n$3\n\nاگر آپ نے یہ کھاتہ *نہیں* کھولا ہے تو اس برقی ڈاک پتے کی تصدیق کو منسوخ کرنے کے لیے اس ربط پر جائیں:\n\n$5\n\nاس تصدیقی کوڈ کی مدت $4 تک ختم ہو جائے گی۔",
+       "confirmemail_body_changed": "کسی نے، غالباً آپ نے، اس آئی پی پتے $1 سے {{SITENAME}} میں «$2» کے نام سے موجود کھاتے کا برقی ڈاک پتہ تبدیل کیا ہے۔\n\nاس بات کی تصدیق کے لیے کہ یہ کھاتہ آپ ہی کا ہے نیز {{SITENAME}} میں برقی خط کی سہولتوں کو دوبارہ فعال کرنے کے لیے ذیل میں موجود ربط کو اپنے براؤزر میں کھولیں:\n\n$3\n\nاگر یہ کھاتہ آپ کا *نہیں* ہے تو اس برقی ڈاک پتے کی تصدیق کو منسوخ کرنے کے لیے اس ربط پر جائیں:\n\n$5\n\nاس تصدیقی کوڈ کی مدت $4 تک ختم ہو جائے گی۔",
+       "confirmemail_body_set": "کسی نے، غالباً آپ نے، اس آئی پی پتے $1 سے {{SITENAME}} میں «$2» کے نام سے موجود کھاتے میں یہ برقی ڈاک پتا دیا ہے۔\n\nاس بات کی تصدیق کے لیے کہ یہ کھاتہ آپ ہی کا ہے نیز {{SITENAME}} میں برقی خط کی سہولتوں کو فعال کرنے کے لیے ذیل میں موجود ربط کو اپنے براؤزر میں کھولیں:\n\n$3\n\nاگر یہ کھاتہ آپ کا *نہیں* ہے تو اس برقی ڈاک پتے کی تصدیق کو منسوخ کرنے کے لیے اس ربط پر جائیں:\n\n$5\n\nاس تصدیقی کوڈ کی مدت $4 تک ختم ہو جائے گی۔",
        "confirmemail_invalidated": "برقی ڈاک پتے کی تصدیق منسوخ ہو گئی",
        "invalidateemail": "برقی ڈاک کی تصدیق منسوخ کریں",
+       "notificationemail_subject_changed": "{{SITENAME}} میں درج کردہ برقی ڈاک پتا تبدیل ہو چکا ہے",
+       "notificationemail_subject_removed": "{{SITENAME}} میں درج کردہ برقی ڈاک پتا حذف ہو چکا ہے",
+       "notificationemail_body_changed": "کسی نے، غالباً آپ نے، اس آئی پی پتے $1 سے {{SITENAME}} میں «$2» کے نام سے موجود کھاتے کے برقی ڈاک پتے کو $3 میں تبدیل کیا ہے۔\n\nاگر وہ شخص آپ نہیں ہے تو سائٹ کے کسی منتظم سے فوراً رابطہ کریں۔",
+       "notificationemail_body_removed": "کسی نے، غالباً آپ نے، اس آئی پی پتے $1 سے {{SITENAME}} میں «$2» کے نام سے موجود کھاتے کے برقی ڈاک پتے کو حذف کیا ہے۔\n\nاگر وہ شخص آپ نہیں ہے تو سائٹ کے کسی منتظم سے فوراً رابطہ کریں۔",
        "scarytranscludedisabled": "[بین الویکی شمولیت غیر فعال ہے]",
        "scarytranscludefailed": "[$1 کے لیے سانچہ اخذ نہیں کیا جا سکا]",
        "scarytranscludefailed-httpstatus": "[$1 کے لیے سانچہ اخذ نہیں کیا جا سکا: HTTP $2]",
        "table_pager_first": "پہلا صفحہ",
        "table_pager_last": "آخری صفحہ",
        "table_pager_limit": "فی صفحہ $1 آئٹم دکھائیں",
-       "table_pager_limit_label": "آئٹم فی صفحہ:",
+       "table_pager_limit_label": "فی صفحہ اندراج:",
        "table_pager_limit_submit": "چلیں",
        "table_pager_empty": "کوئی نتیجہ برآمد نہیں ہوا",
        "autosumm-blank": "تمام مندرجات حذف",
        "autosumm-replace": "\"$1\" سے مواد کی تبدیلی",
        "autoredircomment": "[[$1]] سے رجوع مکرر",
-       "autosumm-new": "«$1» پر مشتمل نیا صفحہ بنایا",
+       "autosumm-new": "«$1» Ù\85Ù\88اد Ù¾Ø± Ù\85شتÙ\85Ù\84 Ù\86Û\8cا ØµÙ\81Ø­Û\81 Ø¨Ù\86اÛ\8cا",
        "autosumm-newblank": "خالی صفحہ بنایا",
        "size-bytes": "$1 بائٹ",
+       "size-kilobytes": "$1 کلوبائٹ",
+       "lag-warn-normal": "گزشتہ $1 {{PLURAL:$1|سیکنڈ|سیکنڈوں}} میں ہونے والی تبدیلیاں شاید اس فہرست میں نظر نہ آئیں۔",
+       "lag-warn-high": "ڈیٹابیس سرور کی جانب سے بے حد تاخیر کی بنا پر گزشتہ $1 {{PLURAL:$1|سیکنڈ|سیکنڈوں}} میں ہونے والی تبدیلیاں شاید اس فہرست میں نظر نہ آئیں۔",
        "watchlistedit-normal-title": "زیر نظر فہرست میں ترمیم کریں",
        "watchlistedit-normal-legend": "زیرنظر فہرست سے عناوین نکالیں",
-       "watchlistedit-normal-submit": "عناوین نکالیں",
+       "watchlistedit-normal-explain": "آپ کی زیرنظر فہرست میں موجود عناوین ذیل میں موجود ہیں۔\nکسی عنوان کو حذف کرنے کے لیے اس کے سامنے موجود خانہ کو نشان زد کریں اور «{{int:Watchlistedit-normal-submit}}» پر کلک کریں۔\nنیز آپ [[Special:EditWatchlist/raw|خام فہرست]] میں بھی ترمیم کر سکتے ہیں۔",
+       "watchlistedit-normal-submit": "عناوین حذف کریں",
+       "watchlistedit-normal-done": "آپ کی زیرنظر فہرست سے {{PLURAL:$1|ایک عنوان حذف کیا گیا|$1 عناوین حذف کیے گئے}}:",
        "watchlistedit-raw-title": "خام زیرِنظرفہرست میں ترمیم کریں",
        "watchlistedit-raw-legend": "خام زیرِنظرفہرست میں ترمیم کریں",
+       "watchlistedit-raw-explain": "آپ کی زیرنظر فہرست میں موجود عناوین ذیل میں موجود ہیں، ان عناوین کو اس فہرست سے حذف کسی مزید عناوین شامل کیے جا سکتے ہیں؛\nفی سطر ایک عنوان درج کریں۔\nترمیم مکمل ہو جانے پر «{{int:Watchlistedit-raw-submit}}» پر کلک کریں۔\nنیز آپ اس میں ترمیم و تبدیلی کے لیے [[Special:EditWatchlist|معیاری خانہ ترمیم]] بھی استعمال کر سکتے ہیں۔",
        "watchlistedit-raw-titles": "عناوین:",
        "watchlistedit-raw-submit": "زیرنظر فہرست کی تجدید کریں",
        "watchlistedit-raw-done": "آپ کی زیرنظر فہرست کی تجدید ہو چکی ہے۔",
        "hijri-calendar-m12": "ذوالحجہ",
        "signature": "[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1|تبادلۂ خیال]])",
        "timezone-local": "مقامی",
+       "duplicate-defaultsort": "<strong>انتباہ:</strong> سابقہ ابتدائی کلید ترتیب «$1» کی بجائے اب «$2» ہی ابتدائی کلید ترتیب ہوگی۔",
+       "duplicate-displaytitle": "<strong>انتباہ:</strong> سابقہ عنوان «$1» کی بجائے اب «$2» عنوان ہوگا۔",
        "restricted-displaytitle": "<strong>انتباہ!:</strong> عنوان \"$1\" کو نظر انداز کر دیا گیا ہے کیونکہ یہ متعلقہ صفحہ کے عنوان کا حقیقی متبادل نہیں ہے۔",
+       "invalid-indicator-name": "<strong>نقص:</strong> صفحہ کی صورت حال کے اشارہ نما کی <code>name</code> خاصیت خالی نہیں ہونی چاہیے۔",
        "version": "نسخہ",
        "version-extensions": "نصب شدہ توسیعات",
        "version-skins": "نصب شدہ پوشاکیں",
        "version-poweredby-others": "دیگر",
        "version-poweredby-translators": "translatewiki.net کے مترجمین",
        "version-credits-summary": "ہم درج ذیل اشخاص کی [[Special:Version|میڈیاویکی]] کی تعمیر میں شرکت کرنے کا اعتراف کرتے ہیں۔",
-       "version-license-info": "میڈیاویکی ایک آزاد سافٹ ویئر ہے؛ آپ اسے آزاد سافٹ ویئر فاؤنڈیش کی جانب سے شائع کردہ گنو عام عوامی اجازت نامہ کی شرائط کے تحت دوبارہ شائع/یا اس میں تبدیلی کر سکتے ہیں؛ خواہ مذکورہ اجازت نامہ کے نسخہ دوم کے تحت شائع کریں یا (حسب منشا) کسی جدید نسخے کے تحت۔\n\nیقیناً میڈیاویکی کو اس امید کے ساتھ شائع کیا گیا ہے کہ یہ مفید ثابت ہوگا، لیکن کوئی ضمانت نہیں ہے؛ نہ قابل تجارت ہونے کی اطلاقی ضمانت ہے اور نہ کسی مخصوص مقصد کے لیے موزوں ہونے کی۔ مزید تفصیلات کے لئے گنو کا عام عوامی اجازت نامہ ملاحظہ فرمائیں۔\n\nآپ کو اس پروگرام کے ساتھ  [{{SERVER}}{{SCRIPTPATH}}/COPYING گنو عام عوامی اجازت نامہ کا ایک نسخہ] بھی موصول ہوگا؛ اگر یہ نسخہ نہ ملے تو Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA پتے پر خط و کتابت کریں یا [//www.gnu.org/licenses/old-licenses/gpl-2.0.html اسے آن لائن پڑھیں]۔",
+       "version-license-info": "میڈیاویکی ایک آزاد سافٹ ویئر ہے؛ آپ اسے آزاد سافٹ ویئر فاؤنڈیشن کے شایع کردہ گنو عام عوامی اجازت نامے کی شرائط کے مطابق دوبارہ شایع یا اس میں تبدیلی کر سکتے ہیں، خواہ اس اجازت نامے کے نسخہ دوم کے مطابق شایع کریں یا حسب منشا کسی نئے نسخے کے مطابق۔\n\nیقیناً میڈیاویکی کی اشاعت سے امید ہے کہ یہ مفید ثابت ہوگا، لیکن اس کی  کوئی قطعی ضمانت نہیں ہے، نہ قابل تجارت ہونے کی اطلاقی ضمانت ہے اور نہ کسی خاص مقصد کے لیے موزوں ہونے کی۔ مزید تفصیل کے لیے گنو کا عام عوامی اجازت نامہ ملاحظہ فرمائیں۔\n\nآپ کو اس پروگرام کے ساتھ  [{{SERVER}}{{SCRIPTPATH}}/COPYING گنو عام عوامی اجازت نامہ کا ایک نسخہ] بھی موصول ہوگا؛ اگر یہ نسخہ نہ ملے تو Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA پتے پر خط و کتابت کریں یا [//www.gnu.org/licenses/old-licenses/gpl-2.0.html اسے آن لائن پڑھیں]۔",
        "version-software": "نصب شدہ سافٹ ویئر",
        "version-software-product": "مصنوعات",
        "version-software-version": "نسخہ",
        "tags-create-warnings-below": "کیا آپ واقعی ٹیگ سازی جاری رکھنا چاہتے ہیں؟",
        "tags-delete-title": "حذف ٹیگ",
        "tags-delete-explanation-initial": "آپ «$1» ٹیگ کو ڈیٹابیس سے حذف کرنے جا رہے ہیں۔",
+       "tags-delete-explanation-in-use": "اس ٹیگ کو {{PLURAL:$2|$2 نسخے یا اندراج نوشتہ|تمام $2 نسخوں اور/یا اندراجات نوشتہ}} سے ہٹا دیا جائے گا جہاں یہ زیر استعمال ہے۔",
+       "tags-delete-explanation-warning": "یہ اقدام <strong>ناقابل تغیر</strong> ہے اور اسے <strong>واپس نہیں پھیرا جا سکتا</strong>، حتی کہ ڈیٹابیس کے منتظمین بھی اس معاملے میں معذور ہیں۔ لہذا اس بات کا یقین کر لیں کہ آیا یہ وہی ٹیگ ہے جسے آپ حذف کرنا چاہتے ہیں۔",
+       "tags-delete-explanation-active": "<strong> ٹیگ \"$1\" فعال ہے اور آئندہ بھی فعال رہے گا۔</strong> اسے روکنے کے لیے اس جگہ/ان جگہوں پر جائیں جہاں یہ ٹیگ زیر استعمال ہے اور وہاں اسے غیر فعال کر دیں۔",
        "tags-delete-reason": "وجہ:",
        "tags-delete-submit": "اس ٹیگ کو اٹل طور پر حذف کریں",
+       "tags-delete-not-allowed": "کسی توسیع کے ذریعہ تخلیق کردہ ٹیگوں کو اس وقت تک حذف نہیں کیا جا سکتا جب تک متعلقہ توسیع خود اس کی سہولت فراہم نہ کرے۔",
        "tags-delete-not-found": "«$1» ٹیگ موجود نہیں ہے۔",
+       "tags-delete-too-many-uses": "ٹیگ \"$1\" کو $2 سے زائد {{PLURAL:$2|نسخے|نسخوں}} میں مستعمل ہے، چنانچہ اسے حذف نہیں کیا جا سکتا۔",
+       "tags-delete-warnings-after-delete": "ٹیگ \"$1\" حذف ہو چکا ہے، لیکن درج ذیل {{PLURAL:$2|انتباہ دیا گیا|انتباہات سامنے آئے}}:",
        "tags-delete-no-permission": "آپ کو تبدیلی کے ٹیگ حذف کرنے کی اجازت نہیں۔",
        "tags-activate-title": "ٹیگ فعال",
        "tags-activate-question": "آپ «$1» ٹیگ کو فعال کرنے جا رہے ہیں۔",
        "tags-edit-success": "تبدیلیاں نافذ کر دی گئیں۔",
        "tags-edit-failure": "تبدیلیاں نافذ نہیں کی جا سکیں:\n$1",
        "tags-edit-nooldid-title": "نادرست ہدف نسخہ",
+       "tags-edit-nooldid-text": "اس کارروائی کو انجام دینے کے لیے یا تو آپ نے کسی ہدف نسخے کا تعین نہیں کیا ہے، یا متعینہ نسخہ موجود نہیں ہے۔",
        "tags-edit-none-selected": "اضافہ کرنے یا ہٹانے کے لیے کم از کم ایک ٹیگ منتخب کریں۔",
        "comparepages": "صفحات کا موازنہ کریں",
        "compare-page1": "صفحہ 1",
        "htmlform-cloner-create": "مزید اضافہ کریں",
        "htmlform-cloner-delete": "حذف",
        "htmlform-cloner-required": "کم ازکم ایک قدر درکار ہے۔",
+       "htmlform-date-placeholder": "YYYY-MM-DD",
+       "htmlform-time-placeholder": "HH:MM:SS",
+       "htmlform-datetime-placeholder": "YYYY-MM-DD HH:MM:SS",
+       "htmlform-date-invalid": "آپ کی درج کردہ قدر تسلیم شدہ تاریخ نہیں ہے۔ براہ کرم YYYY-MM-DD فارمیٹ استعمال کرنے کی کوشش کریں۔",
+       "htmlform-time-invalid": "آپ کی درج کردہ قدر تسلیم شدہ وقت نہیں ہے۔ براہ کرم HH:MM:SS فارمیٹ استعمال کرنے کی کوشش کریں۔",
+       "htmlform-datetime-invalid": "آپ کی درج کردہ قدر تسلیم شدہ تاریخ اور وقت نہیں ہے۔ براہ کرم YYYY-MM-DD HH:MM:SS فارمیٹ استعمال کرنے کی کوشش کریں۔",
        "htmlform-title-badnamespace": "[[:$1]] صفحہ \"{{ns:$2}}\" نام فضا میں موجود نہیں۔",
        "htmlform-title-not-creatable": "«$1» عنوان قابل تخلیق نہیں",
        "htmlform-title-not-exists": "$1 موجود نہیں ہے۔",
        "revdelete-unrestricted": "منتظمین کے لیے کھول دیا گیا",
        "logentry-block-block": "$1 نے {{GENDER:$4|$3}} پر $5 کے وقت اختتام تک {{GENDER:$2|پابندی لگائی}} $6",
        "logentry-block-unblock": "$1 نے {{GENDER:$4|$3}} سے {{GENDER:$2|پابندی اٹھائی}}",
+       "logentry-block-reblock": "$1 نے {{GENDER:$4|$3}} کی ترتیبات پابندی کو {{GENDER:$2|تبدیل کیا}}، اب مدت اختتام $5 $6 ہے۔",
+       "logentry-suppress-block": "$1 نے {{GENDER:$4|$3}} پر $5 کے وقت اختتام تک {{GENDER:$2|پابندی لگائی}} $6",
+       "logentry-suppress-reblock": "$1 نے {{GENDER:$4|$3}} کی ترتیبات پابندی کو {{GENDER:$2|تبدیل کیا}}، اب مدت اختتام $5 $6 ہے۔",
+       "logentry-import-upload": "$1 نے $3 کو فائل اپلوڈ کی مدد سے {{GENDER:$2|درآمد کیا}}",
+       "logentry-import-upload-details": "$1 نے $3 کو فائل اپلوڈ کی مدد سے {{GENDER:$2|درآمد کیا}} ($4 {{PLURAL:$4|نسخہ|نسخے}})",
+       "logentry-import-interwiki": "$1 نے $3 کو دوسری ویکی سے {{GENDER:$2|درآمد کیا}}",
+       "logentry-import-interwiki-details": "$1 نے $3 کو $5 سے {{GENDER:$2|درآمد کیا}} ($4 {{PLURAL:$4|نسخہ|نسخے}})",
+       "logentry-merge-merge": "$1 نے $3 کو $4 میں {{GENDER:$2|ضم کیا}} ($5 تک نسخے)",
        "logentry-move-move": "$1 نے صفحہ $3 کو $4 کی جانب منتقل کیا",
+       "logentry-move-move-noredirect": "$1 نے صفحہ $3 کو $4 کی جانب بدون رجوع مکرر {{GENDER:$2|منتقل کیا}}",
+       "logentry-move-move_redir": "$1 نے رجوع مکرر ہٹا کر صفحہ $3 کو $4 کی جانب {{GENDER:$2|منتقل کیا}}",
        "logentry-move-move_redir-noredirect": "$1 نے صفحہ $3 کو رجوع مکرر چھوڑے بغیر $4 کی جانب جو رجوع مکر تھا {{GENDER:$2|منتقل کیا}}",
+       "logentry-patrol-patrol": "$1 نے صفحہ $3 کے نسخہ $4 کو مراجعت شدہ {{GENDER:$2|نشان زد کیا}}",
+       "logentry-patrol-patrol-auto": "$1 نے صفحہ $3 کے نسخہ $4 کو خودکار طور پر مراجعت شدہ {{GENDER:$2|نشان زد کیا}}",
        "logentry-newusers-newusers": "صارف کھاتہ $1 {{GENDER:$2|تخلیق ہو چکا ہے}}",
        "logentry-newusers-create": "صارف کھاتہ $1 {{GENDER:$2|بنایا گیا}}",
        "logentry-newusers-create2": "$1 نے صارف کھاتہ $3 {{GENDER:$2|تخلیق کیا}}",
        "logentry-upload-overwrite": "$1 نے $3 کا نیا نسخہ {{GENDER:$2|اپلوڈ کیا}}",
        "logentry-upload-revert": "$1 نے $3 کو {{GENDER:$2|اپلوڈ کیا}}",
        "log-name-managetags": "نوشتہ انتظام ٹیگ",
+       "log-description-managetags": "اس صفحہ میں [[Special:Tags|ٹیگوں]] سے متعلق انتظامی کاموں کی فہرست درج ہے۔ اس نوشتہ میں محض ان اقدامات کی فہرست ہے جنہیں کسی منتظم نے از خود انجام دیا ہو؛ تاہم ویکی سافٹویئر کی مدد سے ٹیگوں کو تخلیق یا حذف کیا جا سکتا ہے، جس کا اندراج اس نوشتہ میں ہونا ضروری نہیں۔",
        "logentry-managetags-create": "$1 نے «$4» ٹیگ کو {{GENDER:$2|بنایا}}",
+       "logentry-managetags-delete": "$1 نے ٹیگ \"$4\" کو {{GENDER:$2|حذف کیا}} ($5 {{PLURAL:$5|نسخے یا اندراج نوشتہ|نسخوں یا اندراجات نوشتہ}} سے حذف کیا گیا)",
+       "logentry-managetags-activate": "$1 نے ٹیگ «$4» کو صارفین اور روبہ جات کے استعمال کے لیے {{GENDER:$2|فعال کیا}}",
+       "logentry-managetags-deactivate": "$1 نے ٹیگ «$4» کو صارفین اور روبہ جات کے استعمال کے لیے {{GENDER:$2|غیر فعال کیا}}",
        "log-name-tag": "نوشتہ ٹیگ",
+       "log-description-tag": "ذیل میں صارفین کی جانب سے انفرادی نسخوں یا اندراجات نوشتہ سے [[Special:Tags|ٹیگوں]] کے حذف و اضافہ کا نوشتہ دیکھا جا سکتا ہے۔ تاہم اس نوشتہ میں ٹیگ کاری کے اقدامات -مثلاً کب وہ کسی ترمیم یا حذف شدگی وغیرہ کا جزو بنے- کی فہرست نہیں ہے۔",
+       "logentry-tag-update-add-revision": "$1 نے صفحہ $3 کے نسخہ $4 پر $6 {{PLURAL:$7|ٹیگ|ٹیگوں}} کو {{GENDER:$2|شامل کیا}}",
+       "logentry-tag-update-add-logentry": "$1 نے صفحہ $3 کے اندراج نوشتہ $5 میں $6 {{PLURAL:$7|ٹیگ|ٹیگوں}} کو {{GENDER:$2|شامل کیا}}",
+       "logentry-tag-update-remove-revision": "$1 نے صفحہ $3 کے نسخہ $4 سے $8 {{PLURAL:$9|ٹیگ|ٹیگوں}} کو {{GENDER:$2|حذف کیا}}",
+       "logentry-tag-update-remove-logentry": "$1 نے صفحہ $3 کے اندراج نوشتہ $5 سے $8 {{PLURAL:$9|ٹیگ|ٹیگوں}} کو {{GENDER:$2|حذف کیا}}",
+       "logentry-tag-update-revision": "$1 نے صفحہ $3 کے نسخہ $4 پر موجود ٹیگوں کو {{GENDER:$2|تازہ کیا}} ({{PLURAL:$7|شامل کیا گیا|شامل کیے گئے}} $6؛ {{PLURAL:$9|حذف کیا گیا|حذف کیے گئے}} $8)",
+       "logentry-tag-update-logentry": "$1 نے صفحہ $3 کے اندراج نوشتہ $5 پر موجود ٹیگوں کو {{GENDER:$2|تازہ کیا}} ({{PLURAL:$7|شامل کیا گیا|شامل کیے گئے}} $6؛ {{PLURAL:$9|حذف کیا گیا|حذف کیے گئے}} $8)",
        "rightsnone": "(کچھ نہیں)",
        "revdelete-summary": "خلاصۂ تدوین",
        "feedback-adding": "صفحہ میں تبصرہ درج کیا جا رہا ہے۔۔۔",
        "feedback-back": "واپس",
+       "feedback-bugcheck": "زبردست! جانچ لیں کہ کہیں پہلے ہی [$1 اس کی اطلاع نہ دے دی گئی ہو]۔",
        "feedback-bugnew": "میں نے جانچ لیا ہے۔ نئی خامی کی شکایت کریں",
+       "feedback-bugornote": "اگر آپ کسی تکنیکی مسئلہ کو تفصیل سے بیان کر سکتے ہیں تو براہ کرم [$1 یہاں خامی کی اطلاع دیں]۔\nورنہ ذیل میں موجود فارم کا استعمال کریں۔ آپ کا تبصرہ آپ کے صارف نام کے ساتھ صفحہ «[$3 $2]» میں شائع کر دیا جائے گا۔",
        "feedback-cancel": "منسوخ",
        "feedback-close": "مکمل",
+       "feedback-external-bug-report-button": "تکنیکی خامی کی اطلاع دیں",
        "feedback-dialog-title": "تبصرہ روانہ کریں",
+       "feedback-dialog-intro": "اپنا تبصرہ شائع کرنے کے لیے ذیل میں موجود فارم کو استعمال کر سکتے ہیں۔ آپ کا تبصرہ آپ کے صارف نام کے ساتھ صفحہ «$1» میں شامل کر دیا جائے گا۔",
        "feedback-error-title": "نقص",
        "feedback-error1": "نقص: اے پی آئی کی جانب سے غیر معروف نتیجہ",
        "feedback-error2": "نقص: ترمیم ناکام ہو گئی",
        "feedback-error3": "نقص: اے پی آئی سے کوئی جواب نہیں",
+       "feedback-error4": "نقص: درج کردہ عنوان تبصرہ کے تحت شائع نہیں کیا جا سکا۔",
        "feedback-message": "پیغام:",
        "feedback-subject": "موضوع:",
        "feedback-submit": "روانہ کریں",
+       "feedback-terms": "میں اس امر سے بخوبی واقف ہوں کہ میری یوزر ایجنٹ معلومات کے تحت میرے زیر استعمال براؤزر اور آپریٹنگ سسٹم کے نسخے کی معلومات بھی شامل ہیں اور انہیں میرے تبصرے کے ساتھ عوامی طور پر شائع کیا جائے گا۔",
        "feedback-termsofuse": "میں شرائط استعمال کے مطابق تبصرہ درج کرنے پر متفق ہوں۔",
        "feedback-thanks": "شکریہ! آپ کا تبصرہ صفحہ «[$1 $2]» میں درج کر دیا گیا ہے۔",
        "feedback-thanks-title": "شکریہ!",
+       "feedback-useragent": "یوزر ایجنٹ:",
        "searchsuggest-search": "تلاش",
        "searchsuggest-containing": "نتائج...",
+       "api-error-autoblocked": "آپ کے آئی پی پتے پر خودکار طور پر پابندی لگا دی گئی ہے، کیونکہ اسے کسی ممنوع صارف نے استعمال کیا ہے۔",
+       "api-error-badaccess-groups": "آپ کو اس ویکی میں فائلیں اپلوڈ کرنے کی اجازت نہیں ہے۔",
        "api-error-badtoken": "داخلی نقص: غلط ٹوکن۔",
        "api-error-blocked": "آپ کی ترمیم کاری پر پابندی لگا دی گئی ہے۔",
        "api-error-copyuploaddisabled": "یوآرایل کے ذریعہ اس سرور پر اپلوڈ کو غیر فعال کر دیا گیا ہے۔",
+       "api-error-duplicate": "یکساں مواد کی حامل {{PLURAL:$1|ایک اور فائل|مزید فائلیں}} ویکی پر موجود {{PLURAL:$1|ہے|ہیں}}۔",
+       "api-error-duplicate-archive": "یکساں مواد کی حامل {{PLURAL:$1|ایک اور فائل|مزید فائلیں}} ویکی پر موجود {{PLURAL:$1|تھی|تھیں}}، لیکن {{PLURAL:$1|اسے|انہیں}} حذف کر دیا گیا۔",
        "api-error-empty-file": "آپ کی ارسال کردہ فائل خالی تھی۔",
        "api-error-emptypage": "نئے خالی صفحات بنانے کی اجازت نہیں ہے۔",
        "api-error-fetchfileerror": "داخلی نقص: فائل کو اخذ کرنے کے دوران میں کچھ غلط ہوا ہے۔",
+       "api-error-fileexists-forbidden": "«$1» کے نام سے ایک فائل پہلے سے موجود ہے، اسے تبدیل نہیں کیا جا سکتا۔",
+       "api-error-fileexists-shared-forbidden": "«$1» کے نام سے مشترکہ ذخیرے میں ایک فائل پہلے سے موجود ہے، اسے تبدیل نہیں کیا جا سکتا۔",
        "api-error-file-too-large": "آپ کی ارسال کردہ فائل بہت بڑی تھی۔",
        "api-error-filename-tooshort": "فائل کا نام انتہائی مختصر ہے۔",
        "api-error-filetype-banned": "فائل کی اس قسم پر پابندی عائد ہے۔",
+       "api-error-filetype-banned-type": "$1 نوعیت کی {{PLURAL:$4|فائل|فائلوں}} کی اجازت نہیں۔\nاجازت یافتہ نوعیت کی {{PLURAL:$3|فائل|فائلیں}} $2 {{PLURAL:$3|ہے|ہیں}}۔",
        "api-error-filetype-missing": "فائل کی توسیع موجود نہیں",
+       "api-error-hookaborted": "آپ نے جو تبدیلی کرنے کی کوشش کی اسے کسی توسیع نے منسوخ کر دیا۔",
        "api-error-http": "داخلی نقص: سرور سے رابطہ نہیں ہو سکا",
        "api-error-illegal-filename": "اس نام کی فائل ممنوع ہے۔",
+       "api-error-internal-error": "داخلی نقص: ویکی پر آپ کے اپلوڈ کی انجام دہی کے دوران میں کچھ غلط واقع ہوا۔",
+       "api-error-invalid-file-key": "داخلی نقص: عارضی ذخیرے میں فائل نہیں مل سکی۔",
+       "api-error-missingparam": "داخلی نقص: درخواست میں مفقود متغیرات",
+       "api-error-missingresult": "داخلی نقص: نہیں بتایا جا سکتا کہ نقل و چسپاں کا عمل کامیاب ہوا یا نہیں۔",
+       "api-error-mustbeloggedin": "فائلیں اپلوڈ کرنے کے لیے آپ کا داخل ہونا ضروری ہے۔",
+       "api-error-mustbeposted": "داخلی نقص: یہ درخواست HTTP POST کی متقاضی ہے۔",
+       "api-error-noimageinfo": "اپلوڈ کامیاب رہا لیکن فائل کے متعلق سرور نے ہمیں کسی قسم کی معلومات بہم نہیں پہنچائیں۔",
+       "api-error-nomodule": "داخلی نقص: کسی ماڈیول کو مرتب نہیں کیا گیا۔",
+       "api-error-ok-but-empty": "داخلی نقص: سرور سے کوئی جواب نہیں ملا۔",
+       "api-error-overwrite": "موجودہ فائل کو دوبارہ اپلوڈ کرنے کی اجازت نہیں۔",
+       "api-error-ratelimited": "مختصر وقت میں آپ اس ویکی میں اجازت یافتہ تعداد سے زیادہ فائلوں کو اپلوڈ کرنے کی کوشش کر رہے ہیں۔\nبراہ کرم کچھ منٹ بعد دوبارہ کوشش کریں۔",
+       "api-error-stashfailed": "داخلی نقص: عارضی فائل رکھنے میں سرور کو ناکامی ہوئی۔",
+       "api-error-publishfailed": "داخل نقص: عارضی فائل شائع کرنے میں سرور کو ناکامی ہوئی۔",
+       "api-error-stasherror": "نہاں خانے میں فائل کو اپلوڈ کرتے وقت کوئی نقص واقع ہوا۔",
+       "api-error-stashedfilenotfound": "نہاں خانے میں رکھی گئی فائل وہاں سے اپلوڈ کرنے کے دوران نہیں ملی۔",
+       "api-error-stashpathinvalid": "وہ جگہ غلط ہے جہاں پوشیدہ فائل ملنی چاہیے تھی۔",
+       "api-error-stashfilestorage": "نہاں خانے میں فائل کو رکھتے وقت کوئی نقص واقع ہوا۔",
+       "api-error-stashzerolength": "سرور اس فائل کو پوشیدہ نہ کر سکا کیونکہ اس کی لمبائی صفر ہے۔",
+       "api-error-stashnotloggedin": "اپلوڈ کے نہاں خانے میں فائلوں کو محفوظ کرنے کے لیے آپ کا داخل ہونا ضروری ہے۔",
+       "api-error-stashwrongowner": "فائل کی جس کلید کے ذریعہ آپ نہاں خانے میں رسائی کی کوشش کر رہے ہیں وہ آپ کی نہیں ہے۔",
+       "api-error-stashnosuchfilekey": "فائل کی جس کلید کے ذریعہ آپ نہاں خانے میں رسائی کی کوشش کر رہے ہیں وہ موجود نہیں۔",
+       "api-error-timeout": "متوقع مدت کے دوران میں سرور نے کوئی جواب نہیں دیا۔",
        "api-error-unclassified": "نامعلوم نقص واقع ہوا۔",
        "api-error-unknown-code": "نامعلوم نقص: \"$1\" ۔",
+       "api-error-unknown-error": "داخلی نقص: آپ کی فائل کو اپلوڈ کرنے کے دوران میں کچھ غلط ہو گیا ہے۔",
+       "api-error-unknown-warning": "نامعلوم انتباہ: \"$1\"",
+       "api-error-unknownerror": "نامعلوم نقص: \"$1\"",
        "api-error-uploaddisabled": "اس ویکی پر اپلوڈ کی سہولت غیر فعال ہے۔",
        "api-error-verification-error": "شاید فائل خراب ہے یا غلط توسیع کی حامل ہے۔",
+       "api-error-was-deleted": "اس نام کی فائل پہلے اپلوڈ کی گئی تھی اور معاً بعد حذف کر دی گئی۔",
        "duration-seconds": "$1 {{PLURAL:$1|سیکنڈ}}",
        "duration-minutes": "$1 {{PLURAL:$1|منٹ}}",
        "duration-hours": "$1 {{PLURAL:$1|گھنٹہ|گھنٹے}}",
        "duration-decades": "$1 {{PLURAL:$1|دہائی|دہائیاں}}",
        "duration-centuries": "$1 {{PLURAL:$1|صدی|صدیاں}}",
        "duration-millennia": "$1 {{PLURAL:$1|ہزاریے|ہزاریہ}}",
+       "rotate-comment": "تصویر $1 {{PLURAL:$1|درجہ|درجے}} بائیں سے دائیں گھمائی گئی",
+       "limitreport-title": "تجزیاتی ڈیٹا:",
        "limitreport-cputime": "سی پی یو استعمال کا وقت",
        "limitreport-cputime-value": "$1 {{PLURAL:$1|سیکنڈ}}",
        "limitreport-walltime": "حقیقی استعمال کا وقت",
        "limitreport-walltime-value": "$1 {{PLURAL:$1|سیکنڈ}}",
+       "limitreport-ppvisitednodes": "پراسیسر کی مشاہدہ کردہ گرہوں کی تعداد",
+       "limitreport-ppgeneratednodes": "پراسیسر کی مدد  سے جاری کردہ گرہوں کی تعداد",
+       "limitreport-postexpandincludesize": "بعد از توسیع شمولیت کا حجم",
        "limitreport-postexpandincludesize-value": "$1/$2 {{PLURAL:$2|بائٹ}}",
+       "limitreport-templateargumentsize": "سانچہ آرگومنٹ کا حجم",
        "limitreport-templateargumentsize-value": "$1/$2 {{PLURAL:$2|بائٹ}}",
+       "limitreport-expansiondepth": "توسیع کی بلند ترین گہرائی",
+       "limitreport-expensivefunctioncount": "کثیر الاستعمال پارسر فنکشنوں کی تعداد",
        "expandtemplates": "سانچے کو وسیع کریں",
+       "expand_templates_intro": "اس خصوصی صفحہ میں ویکی کی عبارتوں کو اخذ کرکے ان میں موجود تمام مستعمل سانچوں کو کھولا جاتا ہے۔\nنیز اس صفحہ میں <code><nowiki>{{</nowiki>#language:…}}</code> جیسے پارسر فنکشنوں اور <code><nowiki>{{</nowiki>CURRENTDAY}}</code> جیسے متغیرات کی معاونت بھی رکھی گئی ہے۔\nدرحقیقت یہاں ہر چیز کو دوہرے محرابی قوسین میں کھول دیا جاتا ہے۔",
+       "expand_templates_title": "اس عبارت کا عنوان، مثلاً {{FULLPAGENAME}} وغیرہ کے لیے:",
        "expand_templates_input": "ان پٹ متن:",
        "expand_templates_output": "نتیجہ",
        "expand_templates_xml_output": "XML آؤٹ پٹ",
        "expand_templates_generate_xml": "ایکس ایم ایل تجزیہ کے درخت کو دکھائیں",
        "expand_templates_generate_rawhtml": "خام اہچ ٹی ایم ایل دکھائیں",
        "expand_templates_preview": "پیش نظارہ",
+       "expand_templates_preview_fail_html": "<em>چونکہ {{SITENAME}} نے خام ایچ ٹی ایم ایل فعال کر رکھا ہے اور نشست کا ڈیٹا گم ہو گیا ہے لہذا جاوا اسکرپٹ کے طوفان بدتمیزی سے تحفظ کے لیے نمائش کو پوشیدہ رکھا گیا ہے۔</em>\n\n<strong>اگر نمائش کی یہ کوشش درست ہے تو براہ کرم دوبارہ کوشش کریں۔</strong>\nاگر اب بھی کامیابی نہ ملے تو [[Special:UserLogout|خارج ہو کر]] دوبارہ داخل ہوں، نیز اپنے براؤز کی ترتیبات کو بھی جانچ لیں کہ آیا اس میں کوکیز کو ذخیرہ کرنے کی اجازت ہے یا نہیں۔",
+       "expand_templates_preview_fail_html_anon": "<em>چونکہ {{SITENAME}} نے خام ایچ ٹی ایم ایل فعال کر رکھا ہے اور آپ داخل نہیں ہیں لہذا جاوا اسکرپٹ کے طوفان بدتمیزی سے تحفظ کے لیے نمائش کو پوشیدہ رکھا گیا ہے۔</em>\n\n<strong>اگر نمائش کی یہ کوشش درست ہے تو براہ کرم [[Special:UserLogin|داخل ہوں]] اور دوبارہ کوشش کریں۔</strong>",
+       "expand_templates_input_missing": "آپ کو کم از کم کچھ متن درج کرنا ہوگا۔",
        "pagelanguage": "صفحے کی زبان تبدیل کریں",
        "pagelang-name": "صفحہ",
        "pagelang-language": "زبان",
        "action-pagelang": "صفحے کی زبان تبدیل کریں",
        "log-name-pagelang": "نوشتہ تبدیلی زبان",
        "log-description-pagelang": "ذیل میں زبانوں کے صفحہ میں ہونے والی تبدیلیوں کا نوشتہ ہے۔",
+       "logentry-pagelang-pagelang": "$1 نے $3 کی زبان کو $4 سے $5 میں {{GENDER:$2|تبدیل کیا}}",
+       "default-skin-not-found": "اوہ! <code>$wgDefaultSkin</code> میں <code>$1</code> کے نام سے درج شدہ آپ کی ویکی کی ابتدائی پوشاک دستیاب نہیں ہے۔\n\nایسا معلوم ہوتا ہے کہ آپ کی تنصیب میں حسب ذیل {{PLURAL:$4|پوشاک|پوشاکیں}} موجود {{PLURAL:$4|ہے|ہیں}}۔ {{PLURAL:$4|پوشاک|پوشاکوں}} کو فعال کرنے اور ابتدائی پوشاک کو منتخب کرنے کے بارے میں مزید تفصیل کے لیے [https://www.mediawiki.org/wiki/Manual:Skin_configuration رہنما: ترتیبات پوشاک] ملاحظہ فرمائیں۔\n\n$2\n\n;اگر آپ نے میڈیاویکی کو ابھی نصب کیا ہے تو:\n:شاید آپ نے اسے گٹ سے یا کوئی دوسرا طریقہ استعمال کرکے براہ راست سورس کوڈ سے نصب کیا ہے۔ میڈیاویکی 1.24 اور اس کے بعد کی اشاعتوں میں پوشاکیں شامل نہیں ہیں۔ چنانچہ [https://www.mediawiki.org/wiki/Category:All_skins میڈیاویکی ڈاٹ آرگ میں موجود پوشاکوں کی ڈائرکٹری] سے کچھ پوشاکیں نصب کرنے کی کوشش کریں، جس کے لئے آپ:\n:* [https://www.mediawiki.org/wiki/Download ٹاربال انسٹالر] ڈاؤنلوڈ کریں، اس میں متعدد پوشاکیں اور کچھ توسیعیں موجود ہیں۔ آپ اس کی <code>skins/</code> ڈائرکٹری کو نقل و چسپاں کر سکتے ہیں۔\n:* انفرادی پوشاکوں کے ٹاربال [https://www.mediawiki.org/wiki/Special:SkinDistributor میڈیاویکی ڈاٹ آرگ] سے ڈاؤنلوڈ کریں۔\n:* [https://www.mediawiki.org/wiki/Download_from_Git#Using_Git_to_download_MediaWiki_skins گٹ کے ذریعہ پوشاکیں ڈاؤنلوڈ کریں]۔\n:اگر آپ میڈیاویکی کے ترقی دہندہ ہیں تو اس عمل کے دوران میں اپنے گٹ ذخیرے سے تعارض نہ کریں۔\n\n; اگر آپ نے ابھی میڈیاویکی کی تجدید کی ہو تو:\n: میڈیاویکی 1.24 اور اس کے بعد کی اشاعتوں میں خودکار طور پر نصب شدہ پوشاکیں فعال نہیں ہوتیں (مزید تفصیل کے لیے [https://www.mediawiki.org/wiki/Manual:Skin_autodiscovery رہنما: پوشاک کی خودکار دریافت] ملاحظہ فرمائیں)۔ نیز آپ {{PLURAL:$5|پوشاک|تمام پوشاکوں}} کو فعال کرنے کے لیے درج ذیل {{PLURAL:$5|سطر|سطروں}} کو <code>LocalSettings.php</code> میں چسپاں کر سکتے ہیں:\n\n<pre dir=\"ltr\">$3</pre>\n\n; اگر آپ نے ابھی <code>LocalSettings.php</code> میں تبدیلی کی ہو اور پوشاک فعال نہ ہو رہی ہو تو:\n: اپنی تبدیلی کو دوبارہ جانچ لیں، کہیں لکھنے کے دوران میں ہجے غلط نہ ہو گئے ہو۔",
+       "default-skin-not-found-no-skins": "اوہ! <code>$wgDefaultSkin</code> میں <code>$1</code> کے نام سے درج شدہ آپ کی ویکی کی ابتدائی پوشاک دستیاب نہیں ہے۔\n\nاور آپ نے کسی پوشاک کو نصب نہیں کیا ہے۔\n\n;اگر آپ نے میڈیاویکی کو ابھی نصب کیا ہے یا اس کی تجدید کی ہے تو:\n:شاید آپ نے اسے گٹ سے یا کوئی دوسرا طریقہ استعمال کرکے براہ راست سورس کوڈ سے نصب کیا ہے۔ میڈیاویکی 1.24 اور اس کے بعد کی اشاعتوں میں پوشاکیں شامل نہیں ہیں۔ چنانچہ [https://www.mediawiki.org/wiki/Category:All_skins میڈیاویکی ڈاٹ آرگ میں موجود پوشاکوں کی ڈائرکٹری] سے کچھ پوشاکیں نصب کرنے کی کوشش کریں، جس کے لئے آپ:\n:* [https://www.mediawiki.org/wiki/Download ٹاربال انسٹالر] ڈاؤنلوڈ کریں، اس میں متعدد پوشاکیں اور کچھ توسیعیں موجود ہیں۔ آپ اس کی <code>skins/</code> ڈائرکٹری کو نقل و چسپاں کر سکتے ہیں۔\n:* انفرادی پوشاکوں کے ٹاربال [https://www.mediawiki.org/wiki/Special:SkinDistributor میڈیاویکی ڈاٹ آرگ] سے ڈاؤنلوڈ کریں۔\n:* [https://www.mediawiki.org/wiki/Download_from_Git#Using_Git_to_download_MediaWiki_skins گٹ کے ذریعہ پوشاکیں ڈاؤنلوڈ کریں]۔\n:اگر آپ میڈیاویکی کے ترقی دہندہ ہیں تو اس عمل کے دوران میں اپنے گٹ ذخیرے سے تعارض نہ کریں۔ نیز پوشاکوں کو فعال کرنے اور ابتدائی پوشاک کو منتخب کرنے کے بارے میں مزید تفصیل کے لیے [https://www.mediawiki.org/wiki/Manual:Skin_configuration رہنما: ترتیبات پوشاک] ملاحظہ فرمائیں۔",
        "default-skin-not-found-row-enabled": "* <code>$1</code> / $2 (فعال)",
+       "default-skin-not-found-row-disabled": "* <code>$1</code> / $2 (<strong>غیر فعال</strong>)",
        "mediastatistics": "میڈیا کے اعداد و شمار",
+       "mediastatistics-summary": "اپلوڈ کردہ فائلوں کی اقسام کے اعداد و شمار۔ ان میں محض فائل کے تازہ ترین نسخے ہی شامل اور قدیم یا حذف شدہ نسخے خارج کر دیے گئے ہیں۔",
+       "mediastatistics-nbytes": "{{PLURAL:$1|$1 بائٹ}} ($2؛ $3%)",
+       "mediastatistics-bytespertype": "اس قطعہ کی تمام فائلوں کا کل حجم: {{PLURAL:$1|$1 بائٹ}} ($2؛ $3%)",
+       "mediastatistics-allbytes": "تمام فائلوں کا کل حجم: {{PLURAL:$1|$1 بائٹ}} ($2)",
        "mediastatistics-table-mimetype": "MIME قسم",
        "mediastatistics-table-extensions": "ممکنہ توسیعات",
        "mediastatistics-table-count": "فائلوں کی تعداد",
        "mediastatistics-header-drawing": "خاکے (ویکٹر تصویریں)",
        "mediastatistics-header-audio": "آڈیو",
        "mediastatistics-header-video": "ویڈیو",
+       "mediastatistics-header-multimedia": "رچ میڈیا",
        "mediastatistics-header-office": "دفتر",
        "mediastatistics-header-text": "متنی",
        "mediastatistics-header-executable": "قابل تنفیذ",
        "mediastatistics-header-archive": "کمپریس شدہ فارمیٹ",
        "mediastatistics-header-total": "تمام فائلیں",
+       "json-warn-trailing-comma": "آخر میں رہ جانے والے $1 {{PLURAL:$1|وقفہ|وقفوں}} کو جے سن سے حذف کر دیا گیا ہے",
        "json-error-unknown": "جے سن میں کوئی مسئلہ تھا۔ نقص: $1",
+       "json-error-depth": "اسٹیک کی گہرائی کی آخری حد تجاوز کر چکی ہے۔",
+       "json-error-state-mismatch": "نادرست یا بدشکل جے سن",
+       "json-error-ctrl-char": "کنٹرول حروف میں نقص، ممکنہ طور پر انہیں غلط کوڈ کیا گیا ہے",
        "json-error-syntax": "نحوی غلطی",
+       "json-error-utf8": "نادرست یو ٹی ایف 8 حروف، ممکنہ طور پر انہیں غلط کوڈ کیا گیا ہے",
+       "json-error-recursion": "اینکوڈ کی جانے والی قدر میں ایک یا زائد متواتر حوالے موجود ہیں",
+       "json-error-inf-or-nan": "NAN یا INF کی ایک یا زائد قدریں اینکوڈ کی جانے والی قدر میں موجود ہیں",
+       "json-error-unsupported-type": "ایسی قدر دی گئی ہے جسے اینکوڈ نہیں کیا جا سکتا",
        "headline-anchor-title": "اس قطعہ کا ربط",
        "special-characters-group-latin": "لاطینی محارف",
        "special-characters-group-latinextended": "وسیع لاطینی",
        "special-characters-group-thai": "سیامی",
        "special-characters-group-lao": "لاوسی",
        "special-characters-group-khmer": "کھمیری",
-       "special-characters-title-endash": "خط Ù\81اصÙ\84Û\81",
+       "special-characters-title-endash": "عÙ\84اÙ\85ت Ø®Ø·",
        "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 کا رجوع مکرر",
+       "sessionmanager-tie": "تصدیقی درخواست کی متعدد قسموں کو یکجا نہیں کیا جا سکتا: $1",
        "sessionprovider-generic": "$1 کی نشستیں",
        "sessionprovider-mediawiki-session-cookiesessionprovider": "کوکی پر مبنی نشستیں",
        "sessionprovider-nocookies": "شاید کوکی غیر فعال ہے۔ براہ کرم کوکی فعال کرنے کے بعد دوبارہ کوشش کریں۔",
+       "randomrootpage": "بے ترتيب بنیادی صفحہ",
        "log-action-filter-block": "پابندی کی نوعیت:",
        "log-action-filter-contentmodel": "مواد کے ماڈل کی تبدیلی کی نوعیت:",
        "log-action-filter-delete": "حذف کی نوعیت:",
        "log-action-filter-suppress-reblock": "بذریعہ باز پابندی صارف کی پوشیدگی",
        "log-action-filter-upload-upload": "نیا اپلوڈ",
        "log-action-filter-upload-overwrite": "دوبارہ لوڈ",
+       "authmanager-authn-not-in-progress": "تصدیق کا عمل جاری نہیں ہے یا نشست کا ڈیٹا گم ہو چکا ہے۔ براہ کرم آغاز سے دوبارہ کوشش کریں۔",
+       "authmanager-authn-no-primary": "فراہم کردہ وثیقوں کی تصدیق نہیں ہو سکی۔",
+       "authmanager-authn-no-local-user": "فراہم کردہ وثیقے اس ویکی کے کسی صارف سے منسلک نہیں ہیں۔",
+       "authmanager-authn-no-local-user-link": "فراہم کردہ وثیقے اس ویکی کے کسی صارف سے منسلک نہیں ہیں۔ کسی دوسرے طریقے سے لاگ ہوں یا نیا کھاتا بنائیں۔ اس صورت میں آپ کو یہ اختیار حاصل ہوگا کہ سابقہ وثیقوں کو اس کھاتے سے مربوط کر سکیں۔",
        "authmanager-authn-autocreate-failed": "خودکار مقامی کھاتہ سازی ناکام: $1",
+       "authmanager-change-not-supported": "فراہم کردہ وثیقے غیر مستعمل ہونے کی وجہ سے انہیں تبدیل نہیں کیا جا سکتا۔",
        "authmanager-create-disabled": "کھاتہ سازی غیر فعال ہے۔",
+       "authmanager-create-from-login": "اپنا کھاتہ بنانے کے لیے براہ کرم ذیل میں موجود خانوں کو پُر کریں۔",
+       "authmanager-create-not-in-progress": "کھاتہ سازی کا عمل جاری نہیں ہے یا نشست کا ڈیٹا گم ہو چکا ہے۔ براہ کرم آغاز سے دوبارہ کوشش کریں۔",
+       "authmanager-create-no-primary": "فراہم کردہ وثیقوں کو کھاتہ سازی کے لیے استعمال نہیں کیا جا سکا۔",
+       "authmanager-link-no-primary": "فراہم کردہ وثیقوں کو کھاتوں سے مربوط کرنے کے لیے استعمال نہیں کیا جا سکا۔",
+       "authmanager-link-not-in-progress": "کھاتوں کو مربوط کرنے کا عمل جاری نہ رہ سکا یا نشست کا ڈیٹا گم ہو چکا ہے۔ براہ کرم آغاز سے دوبارہ کوشش کریں۔",
        "authmanager-authplugin-setpass-failed-title": "پاس ورڈ کی تبدیلی ناکام رہی",
+       "authmanager-authplugin-setpass-failed-message": "تصدیقی ہلگ ان نے پاس ورڈ کی تبدیلی کو رد کر دیا۔",
+       "authmanager-authplugin-create-fail": "تصدیقی ہلگ ان نے کھاتہ سازی کو رد کر دیا۔",
+       "authmanager-authplugin-setpass-denied": "تصدیقی ہلگ ان میں پاس ورڈ کی تبدیلی کی اجازت نہیں ہے۔",
        "authmanager-authplugin-setpass-bad-domain": "نادرست ڈومین۔",
        "authmanager-autocreate-noperm": "خودکار کھاتہ سازی کی اجازت نہیں ہے۔",
        "authmanager-autocreate-exception": "سابقہ نقص کی وجہ سے عارضی طور پر خودکار کھاتہ سازی غیر فعال ہے۔",
        "authmanager-userdoesnotexist": "«$1» کے نام سے صارف کھاتہ مندرج نہیں ہے۔",
+       "authmanager-userlogin-remembermypassword-help": "نشست کی مدت سے زیادہ عرصہ کے لیے پاس ورڈ کو یاد رکھیں۔",
        "authmanager-username-help": "صارف نام برائے تصدیق",
        "authmanager-password-help": "پاس ورڈ برائے تصدیق",
        "authmanager-domain-help": "ڈومین برائے خارجی تصدیق",
        "authmanager-provider-password": "پاس ورڈ پر مبنی تصدیق",
        "authmanager-provider-password-domain": "پاس ورڈ اور ڈومین پر مبنی تصدیق",
        "authmanager-provider-temporarypassword": "عارضی پاس ورڈ",
+       "authprovider-confirmlink-message": "آپ کی جانب سے لاگ ان کی حالیہ کوششوں کے پیش نظر، آپ ذیل میں موجود کھاتوں کو اپنے ویکی کھاتے سے منسلک کر سکتے ہیں۔ چنانچہ انہیں مربوط کرنے کے بعد آپ ان کھاتوں کی مدد سے بھی داخل ہو سکیں گے۔ لہذا جنہیں منسلک کرنا ہو انہیں منتخب کریں۔",
        "authprovider-confirmlink-request-label": "جن کھاتوں کو مربوط کرنا ہو",
        "authprovider-confirmlink-success-line": "$1: کامیابی سے مربوط کر دیے گئے۔",
        "authprovider-confirmlink-failed": "کھاتوں کو مربوط کرنے کا عمل مکمل نہیں ہو سکا: $1",
+       "authprovider-confirmlink-ok-help": "ناکامی کے پیغام کی نمائش کے بعد جاری رکھیں",
        "authprovider-resetpass-skip-label": "آگے بڑھیں",
        "authprovider-resetpass-skip-help": "پاس ورڈ کی ترتیب نو کو رہنے دیں",
+       "authform-nosession-login": "تصدیق کامیاب رہی لیکن آپ کا براؤزر لاگ ان کو \"برقرار\" نہیں رکھ سکا۔\n\n$1",
+       "authform-nosession-signup": "کھاتہ بن چکا ہے لیکن آپ کا براؤزر لاگ ان کو \"برقرار\" نہیں رکھ سکا۔\n\n$1",
        "authform-newtoken": "ٹوکن مفقود۔ $1",
        "authform-notoken": "ٹوکن مفقود",
        "authform-wrongtoken": "غلط ٹوکن",
        "unlinkaccounts-success": "مربوط کھاتہ علاحدہ کر دیا گیا۔",
        "authenticationdatachange-ignored": "تصدیقی معلومات کی تبدیلی نہیں ہو سکی۔ شاید کوئی پرووائڈر فراہم نہیں کیا گیا؟",
        "userjsispublic": "براہ کرم اس بات کا خیال رکھیں کہ جاوا اسکرپٹ کے ذیلی صفحات میں خفیہ معلومات نہیں رکھی جانی چاہئیں کیونکہ ان صفحات کو دیگر صارفین بھی دیکھ سکتے ہیں۔",
-       "usercssispublic": "براہ کرم اس بات کا خیال رکھیں کہ سی ایس ایس کے ذیلی صفحات میں خفیہ معلومات نہیں رکھی جانی چاہئیں کیونکہ ان صفحات کو دیگر صارفین بھی دیکھ سکتے ہیں۔"
+       "usercssispublic": "براہ کرم اس بات کا خیال رکھیں کہ سی ایس ایس کے ذیلی صفحات میں خفیہ معلومات نہیں رکھی جانی چاہئیں کیونکہ ان صفحات کو دیگر صارفین بھی دیکھ سکتے ہیں۔",
+       "restrictionsfield-badip": "آئی پی پتا یا رینج نادرست ہے: $1",
+       "restrictionsfield-label": "آئی پی کی اجازت یافتہ رینج:",
+       "restrictionsfield-help": "فی سطر ایک آئی پی پتا یا سی آئی ڈی آر رینج۔ تمام کو فعال کرنے کے لیے <br><code>0.0.0.0/0</code><br><code>::/0</code> استعمال کریں"
 }
index 803c6a2..d2f0247 100644 (file)
        "botpasswords-label-cancel": "אַנולירן",
        "botpasswords-label-delete": "אויסמעקן",
        "botpasswords-label-resetpassword": "ווידערשטעלן פאַסווארט",
-       "botpasswords-label-restrictions": "באניץ באגרענעצונגען:",
        "botpasswords-label-grants-column": "נאכגעגעבן",
        "botpasswords-bad-appid": "דער באט נאמען \"$1\" איז אומגילטיק.",
        "botpasswords-created-title": "באט פאסווארט געשאפן",
        "randompage-nopages": "נישטא קיין בלעטער אין {{PLURAL:$2|דעם פאלגנדן נאמענטייל |די פאלגנדע נאמענטיילן}} \"$1\".",
        "randomincategory": "צופעליקער בלאט אין קאטעגאריע",
        "randomincategory-invalidcategory": "\"$1\" איז נישט קיין גילטיקער קאטעגאריע נאמען.",
-       "randomincategory-nopages": "נישט פאראן קיין בלעטער אין [[:Category:$1]].",
+       "randomincategory-nopages": "נישט פאראן קיין בלעטער אין דער [[:Category:$1]] קאטעגאריע.",
        "randomincategory-category": "קאַטעגאריע:",
        "randomincategory-legend": "צופעליקער בלאט אין קאטעגאריע",
        "randomincategory-submit": "גיין",
        "htmlform-cloner-create": "צולייגן נאך",
        "htmlform-cloner-delete": "אַראָפּנעמען",
        "htmlform-title-not-exists": "$1 עקזיסטירט נישט",
-       "sqlite-has-fts": "$1 מיט פולן-טעקסט זוכן שטיץ",
-       "sqlite-no-fts": "$1 אָן פֿולן-טעקסט זוכן שטיץ",
        "logentry-delete-delete": "$1 {{GENDER:$2|האט אויסגעמעקט}} בלאט $3",
        "logentry-delete-restore": "$1 {{GENDER:$2|האט צוריקגעשטעלט }} בלאט $3",
        "logentry-delete-event": "$1 {{GENDER:$2|האט געענדערט}} די זעבארקייט פון {{PLURAL:$5|א לאגבוך אקטיוויטעט|$5 לאגבוך אקטיוויטעטן}} אויף $3: $4",
index a45d3d2..3798d91 100644 (file)
        "welcomecreation-msg": "您的账户已创建。\n如果需要,您可以更改您在{{SITENAME}}的[[Special:Preferences|参数设置]]。",
        "yourname": "用户名:",
        "userlogin-yourname": "用户名",
-       "userlogin-yourname-ph": "请输入的用户名",
+       "userlogin-yourname-ph": "请输入的用户名",
        "createacct-another-username-ph": "请输入用户名",
        "yourpassword": "密码:",
        "userlogin-yourpassword": "密码",
        "createaccount": "创建账户",
        "gotaccount": "已经拥有账户?请$1。",
        "gotaccountlink": "登录",
-       "userlogin-resetlink": "忘记的登录信息?",
+       "userlogin-resetlink": "忘记的登录信息?",
        "userlogin-resetpassword-link": "忘记密码?",
        "userlogin-helplink2": "登录帮助",
        "userlogin-loggedin": "您已经以{{GENDER:$1|$1}}的身份登录。使用下面的表格以其他用户的身份登录。",
        "action-userrights-interwiki": "编辑其他wiki用户的用户权限",
        "action-siteadmin": "锁定或解锁数据库",
        "action-sendemail": "发送电子邮件",
-       "action-editmywatchlist": "编辑的监视列表",
-       "action-viewmywatchlist": "查看的监视列表",
+       "action-editmywatchlist": "编辑的监视列表",
+       "action-viewmywatchlist": "查看的监视列表",
        "action-viewmyprivateinfo": "查看您的私人信息",
-       "action-editmyprivateinfo": "编辑的私人信息",
+       "action-editmyprivateinfo": "编辑的私人信息",
        "action-editcontentmodel": "编辑页面的内容模型",
        "action-managechangetags": "创建和(取消)激活标签",
        "action-applychangetags": "连同您的更改应用标签",
        "img-auth-public": "img_auth.php的功能是从非公开wiki输出文件。本wiki已被设置为公开。为了最佳安全状况,img_auth.php已停用。",
        "img-auth-noread": "用户无权读取“$1”。",
        "http-invalid-url": "无效URL:$1",
-       "http-invalid-scheme": "不支持带有“$1”的URL",
+       "http-invalid-scheme": "带“$1”方案的URL不受支持。",
        "http-request-error": "未知的错误令到HTTP请求失败。",
        "http-read-error": "HTTP读取错误。",
        "http-timed-out": "HTTP请求已过时。",
        "exif-imagewidth": "宽度",
        "exif-imagelength": "高度",
        "exif-bitspersample": "每像素字节数",
-       "exif-compression": "压缩方",
+       "exif-compression": "压缩方",
        "exif-photometricinterpretation": "像素构成",
        "exif-orientation": "方位",
        "exif-samplesperpixel": "像素数",
        "unlinkaccounts-success": "账户已取消链接。",
        "authenticationdatachange-ignored": "身份验证数据更改未处理。也许没有配置的提供者?",
        "userjsispublic": "请注意:JavaScript子页面不应包含机密数据,因为它们可以被其他用户查看。",
-       "usercssispublic": "请注意:CSS子页面不应包含机密数据,因为它们可以被其他用户查看。"
+       "usercssispublic": "请注意:CSS子页面不应包含机密数据,因为它们可以被其他用户查看。",
+       "restrictionsfield-badip": "无效的IP地址或段:$1",
+       "restrictionsfield-label": "允许的IP段:",
+       "restrictionsfield-help": "每行一个IP地址或CIDR段。要启用所有,可使用<br><code>0.0.0.0/0</code><br><code>::/0</code>"
 }
index 589144c..67369e2 100644 (file)
@@ -104,9 +104,9 @@ $namespaceAliases = [];
  * Mapping NS_xxx to array of GENDERKEY to alias.
  * Example:
  * @code
- * $namespaceGenderAliases = array(
- *     NS_USER => array( 'male' => 'Male_user', 'female' => 'Female_user' ),
- * );
+ * $namespaceGenderAliases = [
+ *     NS_USER => [ 'male' => 'Male_user', 'female' => 'Female_user' ],
+ * ];
  * @endcode
  */
 $namespaceGenderAliases = [];
index b8a246e..8672223 100644 (file)
@@ -147,7 +147,6 @@ TEXT
                        } else {
                                $where = [];
                        }
-                       $i = 0;
 
                        $this->output( "Removing empty categories without description pages...\n" );
                        while ( true ) {
index 6b06da7..96aea03 100644 (file)
@@ -42,8 +42,6 @@ in the load balancer, usually indicating a replication environment.' );
                $user = $dbw->tableName( 'user' );
                $revision = $dbw->tableName( 'revision' );
 
-               $dbver = $dbw->getServerVersion();
-
                // Autodetect mode...
                if ( $this->hasOption( 'background' ) ) {
                        $backgroundMode = true;
index baa9c71..baf917c 100644 (file)
@@ -96,7 +96,7 @@ if ( $run ) {
 
                if ( !strcmp( $runMode, 'php' ) ) {
                        print "<?php\n";
-                       print '$dupeMessages = array(' . "\n";
+                       print '$dupeMessages = [' . "\n";
                }
                foreach ( $wgMessages[$langCodeC] as $key => $value ) {
                        foreach ( $wgMessages[$langCode] as $ckey => $cvalue ) {
@@ -118,7 +118,7 @@ if ( $run ) {
                        }
                }
                if ( !strcmp( $runMode, 'php' ) ) {
-                       print ");\n";
+                       print "];\n";
                }
                if ( !strcmp( $runMode, 'text' ) ) {
                        if ( $count == 1 ) {
index 46616db..5bdc8a7 100644 (file)
@@ -55,12 +55,12 @@ class Digit2Html extends Maintenance {
                                continue;
                        }
 
-                       $this->output( "OK\n\$digitTransformTable = array(\n" );
+                       $this->output( "OK\n\$digitTransformTable = [\n" );
                        foreach ( $digitTransformTable as $latin => $translation ) {
                                $htmlent = utf8ToHexSequence( $translation );
                                $this->output( "'$latin' => '$translation', # &#x$htmlent;\n" );
                        }
-                       $this->output( ");\n" );
+                       $this->output( "];\n" );
                }
        }
 }
index d102e08..2503ed2 100644 (file)
@@ -43,7 +43,7 @@ class PPFuzzTester {
        public $minLength = 0;
        public $maxLength = 20;
        public $maxTemplates = 5;
-       // public $outputTypes = array( 'OT_HTML', 'OT_WIKI', 'OT_PREPROCESS' );
+       // public $outputTypes = [ 'OT_HTML', 'OT_WIKI', 'OT_PREPROCESS' ];
        public $entryPoints = [ 'testSrvus', 'testPst', 'testPreprocess' ];
        public $verbose = false;
 
index 2287559..da8a6bc 100644 (file)
@@ -96,7 +96,6 @@ class RebuildFileCache extends Maintenance {
                $blockEnd = $start + $this->mBatchSize - 1;
 
                $dbw = $this->getDB( DB_MASTER );
-               $mainContext = RequestContext::getMain();
                // Go through each page and save the output
                while ( $blockEnd <= $end ) {
                        // Get the pages
index 289d22d..28be6a3 100644 (file)
@@ -384,7 +384,7 @@ class CompressOld extends Maintenance {
 
                                        if ( $text === false ) {
                                                $this->error( "\nError, unable to get text in old_id $oldid" );
-                                               # $dbw->delete( 'old', array( 'old_id' => $oldid ) );
+                                               # $dbw->delete( 'old', [ 'old_id' => $oldid ] );
                                        }
 
                                        if ( $extdb == "" && $j == 0 ) {
index 89168db..b81fbde 100644 (file)
@@ -1083,6 +1083,7 @@ return [
                        'resources/src/mediawiki/htmlform/autocomplete.js',
                        'resources/src/mediawiki/htmlform/autoinfuse.js',
                        'resources/src/mediawiki/htmlform/checkmatrix.js',
+                       'resources/src/mediawiki/htmlform/datetime.js',
                        'resources/src/mediawiki/htmlform/cloner.js',
                        'resources/src/mediawiki/htmlform/hide-if.js',
                        'resources/src/mediawiki/htmlform/multiselect.js',
@@ -1269,6 +1270,7 @@ return [
                'messages' => [
                        'upload-dialog-title',
                        'upload-dialog-button-cancel',
+                       'upload-dialog-button-back',
                        'upload-dialog-button-done',
                        'upload-dialog-button-save',
                        'upload-dialog-button-upload',
index 77e80b0..28ad10a 100644 (file)
@@ -6,16 +6,16 @@
 @colorGray2: #222;
 @colorGray3: #333;
 @colorGray4: #444;
-@colorGray5: #555;
+@colorGray5: #54595d;
 @colorGray6: #666;
 @colorGray7: #72777d;
 @colorGray8: #888;
 @colorGray9: #999;
-@colorGray10: #aaa;
+@colorGray10: #a2a9b1;
 @colorGray11: #bbb;
-@colorGray12: #ccc;
+@colorGray12: #c8ccd1;
 @colorGray13: #ddd;
-@colorGray14: #eee;
+@colorGray14: #eaecf0;
 @colorGray15: #f8f9fa; // lightest
 
 // Semantic background colors
index 01d3442..91f797d 100644 (file)
                        } );
                }
 
+               // Our form input *should* be type="hidden". But if we're infusing from
+               // PHP, it's not.
+               if ( this.$input.attr( 'type' ) !== 'hidden' ) {
+                       try {
+                               this.$input.attr( 'type', 'hidden' );
+                       } catch ( e ) {
+                       }
+                       // IE <= 8, and IE 9 in quirks mode, doesn't allow changing the
+                       // type, so just hide the field with CSS. IE 9 in quirks mode
+                       // doesn't even throw an error, so do that unconditionally. Sigh.
+                       this.$input.css( 'display', 'none' );
+               }
+
                // Initialization
                this.setTabIndex( -1 );
 
diff --git a/resources/src/mediawiki/htmlform/datetime.js b/resources/src/mediawiki/htmlform/datetime.js
new file mode 100644 (file)
index 0000000..2fd2396
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * HTMLForm enhancements:
+ * Add minimal help for date and time fields
+ */
+( function ( mw ) {
+
+       mw.hook( 'htmlform.enhance' ).add( function ( $root ) {
+               var supported = {};
+
+               $root
+                       .find( 'input.mw-htmlform-datetime-field' )
+                       .each( function () {
+                               var input,
+                                       type = this.getAttribute( 'type' );
+
+                               if ( type !== 'date' && type !== 'time' && type !== 'datetime' ) {
+                                       // WTF?
+                                       return;
+                               }
+
+                               if ( supported[ type ] === undefined ) {
+                                       // Assume that if the browser implements validation (so it
+                                       // rejects "bogus" as a value) then it supports a proper UI too.
+                                       input = document.createElement( 'input' );
+                                       input.setAttribute( 'type', type );
+                                       input.value = 'bogus';
+                                       supported[ type ] = ( input.value !== 'bogus' );
+                               }
+
+                               if ( supported[ type ] ) {
+                                       if ( !this.getAttribute( 'min' ) ) {
+                                               this.setAttribute( 'min', this.getAttribute( 'data-min' ) );
+                                       }
+                                       if ( !this.getAttribute( 'max' ) ) {
+                                               this.setAttribute( 'max', this.getAttribute( 'data-max' ) );
+                                       }
+                                       if ( !this.getAttribute( 'step' ) ) {
+                                               this.setAttribute( 'step', this.getAttribute( 'data-step' ) );
+                                       }
+                               }
+                       } );
+       } );
+
+}( mediaWiki ) );
index e8a85f1..1ea7e04 100644 (file)
                        flags: 'safe',
                        action: 'cancel',
                        label: mw.msg( 'upload-dialog-button-cancel' ),
-                       modes: [ 'upload', 'insert', 'info' ]
+                       modes: [ 'upload', 'insert' ]
+               },
+               {
+                       flags: 'safe',
+                       action: 'cancelupload',
+                       label: mw.msg( 'upload-dialog-button-back' ),
+                       modes: [ 'info' ]
                },
                {
                        flags: [ 'primary', 'progressive' ],
                if ( action === 'cancel' ) {
                        return new OO.ui.Process( this.close() );
                }
+               if ( action === 'cancelupload' ) {
+                       return new OO.ui.Process( this.uploadBooklet.initialize() );
+               }
 
                return mw.Upload.Dialog.parent.prototype.getActionProcess.call( this, action );
        };
index d2968a1..369cd0e 100644 (file)
@@ -49,7 +49,7 @@ class ParserTestRunner {
 
        /**
         * Our connection to the database
-        * @var DatabaseBase
+        * @var Database
         */
        private $db;
 
index c952229..45a7ce5 100644 (file)
@@ -42,7 +42,7 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
        /**
         * Primary database
         *
-        * @var DatabaseBase
+        * @var Database
         * @since 1.18
         */
        protected $db;
@@ -1070,11 +1070,11 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
         * Clones all tables in the given database (whatever database that connection has
         * open), to versions with the test prefix.
         *
-        * @param DatabaseBase $db Database to use
+        * @param Database $db Database to use
         * @param string $prefix Prefix to use for test tables
         * @return bool True if tables were cloned, false if only the prefix was changed
         */
-       protected static function setupDatabaseWithTestPrefix( DatabaseBase $db, $prefix ) {
+       protected static function setupDatabaseWithTestPrefix( Database $db, $prefix ) {
                $tablesCloned = self::listTables( $db );
                $dbClone = new CloneDatabase( $db, $tablesCloned, $prefix );
                $dbClone->useTemporaryTables( self::$useTemporaryTables );
@@ -1123,12 +1123,12 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
         * @note this method only works when first called. Subsequent calls have no effect,
         * even if using different parameters.
         *
-        * @param DatabaseBase $db The database connection
+        * @param Database $db The database connection
         * @param string $prefix The prefix to use for the new table set (aka schema).
         *
         * @throws MWException If the database table prefix is already $prefix
         */
-       public static function setupTestDB( DatabaseBase $db, $prefix ) {
+       public static function setupTestDB( Database $db, $prefix ) {
                if ( self::$dbSetup ) {
                        return;
                }
@@ -1139,7 +1139,7 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
                }
 
                // TODO: the below should be re-written as soon as LBFactory, LoadBalancer,
-               // and DatabaseBase no longer use global state.
+               // and Database no longer use global state.
 
                self::$dbSetup = true;
 
@@ -1178,7 +1178,7 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
         * Gets master database connections for all of the ExternalStoreDB
         * stores configured in $wgDefaultExternalStore.
         *
-        * @return DatabaseBase[] Array of DatabaseBase master connections
+        * @return Database[] Array of Database master connections
         */
 
        protected static function getExternalStoreDatabaseConnections() {
@@ -1192,7 +1192,7 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
                        if ( strpos( $url, 'DB://' ) === 0 ) {
                                list( $proto, $cluster ) = explode( '://', $url, 2 );
                                // Avoid getMaster() because setupDatabaseWithTestPrefix()
-                               // requires DatabaseBase instead of plain DBConnRef/IDatabase
+                               // requires Database instead of plain DBConnRef/IDatabase
                                $lb = $externalStoreDB->getLoadBalancer( $cluster );
                                $dbw = $lb->getConnection( DB_MASTER );
                                $dbws[] = $dbw;
@@ -1226,7 +1226,7 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
        /**
         * Empty all tables so they can be repopulated for tests
         *
-        * @param DatabaseBase $db|null Database to reset
+        * @param Database $db|null Database to reset
         * @param array $tablesUsed Tables to reset
         */
        private function resetDB( $db, $tablesUsed ) {
@@ -1309,11 +1309,11 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
        /**
         * @since 1.18
         *
-        * @param DatabaseBase $db
+        * @param Database $db
         *
         * @return array
         */
-       public static function listTables( DatabaseBase $db ) {
+       public static function listTables( Database $db ) {
                $prefix = $db->tablePrefix();
                $tables = $db->listTables( $prefix, __METHOD__ );
 
index 1d232fe..93e0b57 100644 (file)
@@ -6,10 +6,10 @@
 class WatchedItemQueryServiceUnitTest extends PHPUnit_Framework_TestCase {
 
        /**
-        * @return PHPUnit_Framework_MockObject_MockObject|DatabaseBase
+        * @return PHPUnit_Framework_MockObject_MockObject|Database
         */
        private function getMockDb() {
-               $mock = $this->getMockBuilder( DatabaseBase::class )
+               $mock = $this->getMockBuilder( Database::class )
                        ->disableOriginalConstructor()
                        ->getMock();
 
index 030d9d5..c51d496 100644 (file)
@@ -28,12 +28,12 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase {
                        ->getMock();
                if ( $expectedConnectionType !== null ) {
                        $mock->expects( $this->any() )
-                               ->method( 'getConnection' )
+                               ->method( 'getConnectionRef' )
                                ->with( $expectedConnectionType )
                                ->will( $this->returnValue( $mockDb ) );
                } else {
                        $mock->expects( $this->any() )
-                               ->method( 'getConnection' )
+                               ->method( 'getConnectionRef' )
                                ->will( $this->returnValue( $mockDb ) );
                }
                $mock->expects( $this->any() )
index 78cb7fb..d5c17ee 100644 (file)
@@ -218,7 +218,7 @@ class RandomImageGenerator {
        }
 
        /**
-        * Given array( array('x' => 10, 'y' => 20), array( 'x' => 30, y=> 5 ) )
+        * Given [ [ 'x' => 10, 'y' => 20 ], [ 'x' => 30, y=> 5 ] ]
         * returns "10,20 30,5"
         * Useful for SVG and imagemagick command line arguments
         * @param array $shape Array of arrays, each array containing x & y keys mapped to numeric values
@@ -430,7 +430,7 @@ class RandomImageGenerator {
 
        /**
         * Get an array of random pairs of random words, like
-        * array( array( 'foo', 'bar' ), array( 'quux', 'baz' ) );
+        * [ [ 'foo', 'bar' ], [ 'quux', 'baz' ] ];
         *
         * @param int $number Number of pairs
         * @return array Two-element arrays
diff --git a/tests/phpunit/includes/content/FileContentHandlerTest.php b/tests/phpunit/includes/content/FileContentHandlerTest.php
new file mode 100644 (file)
index 0000000..276a86e
--- /dev/null
@@ -0,0 +1,50 @@
+<?php
+
+/**
+ * @group ContentHandler
+ */
+class FileContentHandlerTest extends MediaWikiLangTestCase {
+       /**
+        * @var FileContentHandler
+        */
+       private $handler;
+
+       protected function setUp() {
+               parent::setUp();
+
+               $this->handler = new FileContentHandler();
+       }
+
+       public function testIndexMapping() {
+               $mockEngine = $this->getMock( 'SearchEngine' );
+
+               $mockEngine->expects( $this->atLeastOnce() )
+                       ->method( 'makeSearchFieldMapping' )
+                       ->willReturnCallback( function ( $name, $type ) {
+                               $mockField =
+                                       $this->getMockBuilder( 'SearchIndexFieldDefinition' )
+                                               ->setMethods( [ 'getMapping' ] )
+                                               ->setConstructorArgs( [ $name, $type ] )
+                                               ->getMock();
+                               return $mockField;
+                       } );
+
+               $map = $this->handler->getFieldsForSearchIndex( $mockEngine );
+               $expect = [
+                       'file_media_type' => 1,
+                       'file_mime' => 1,
+                       'file_size' => 1,
+                       'file_width' => 1,
+                       'file_height' => 1,
+                       'file_bits' => 1,
+                       'file_resolution' => 1,
+                       'file_text' => 1,
+               ];
+               foreach ( $map as $name => $field ) {
+                       $this->assertInstanceOf( 'SearchIndexField', $field );
+                       $this->assertEquals( $name, $field->getName() );
+                       unset( $expect[$name] );
+               }
+               $this->assertEmpty( $expect );
+       }
+}
index 9d4abe8..ec97d76 100644 (file)
@@ -249,11 +249,20 @@ class WikitextContentHandlerTest extends MediaWikiLangTestCase {
                $title = Title::newFromText( 'Somefile.jpg', NS_FILE );
                $page = new WikiPage( $title );
 
+               $fileHandler = $this->getMockBuilder( FileContentHandler::class )
+                       ->disableOriginalConstructor()
+                       ->setMethods( [ 'getDataForSearchIndex' ] )
+                       ->getMock();
+
                $handler = $this->getMockBuilder( WikitextContentHandler::class )
                        ->disableOriginalConstructor()
-                       ->setMethods( [ 'getFileText' ] )
+                       ->setMethods( [ 'getFileHandler' ] )
                        ->getMock();
-               $handler->method( 'getFileText' )->will( $this->returnValue( 'This is file content' ) );
+
+               $handler->method( 'getFileHandler' )->will( $this->returnValue( $fileHandler ) );
+               $fileHandler->expects( $this->once() )
+                       ->method( 'getDataForSearchIndex' )
+                       ->will( $this->returnValue( [ 'file_text' => 'This is file content' ] ) );
 
                $data = $handler->getDataForSearchIndex( $page, new ParserOutput(), $mockEngine );
                $this->assertArrayHasKey( 'file_text', $data );
index c014e84..dbb126f 100644 (file)
@@ -29,7 +29,7 @@
  * Fake class around abstract class so we can call concrete methods.
  */
 class FakeDatabaseMysqlBase extends DatabaseMysqlBase {
-       // From DatabaseBase
+       // From Database
        function __construct() {
                $this->profiler = new ProfilerStub( [] );
                $this->trxProfiler = new TransactionProfiler();
@@ -89,7 +89,6 @@ class FakeDatabaseMysqlBase extends DatabaseMysqlBase {
 
        }
 
-       // From interface DatabaseType
        function insertId() {
        }
 
index 68bc964..656e661 100644 (file)
@@ -26,7 +26,7 @@ class DatabaseSQLTest extends MediaWikiTestCase {
 
        /**
         * @dataProvider provideSelect
-        * @covers DatabaseBase::select
+        * @covers Database::select
         */
        public function testSelect( $sql, $sqlText ) {
                $this->database->select(
@@ -132,7 +132,7 @@ class DatabaseSQLTest extends MediaWikiTestCase {
 
        /**
         * @dataProvider provideUpdate
-        * @covers DatabaseBase::update
+        * @covers Database::update
         */
        public function testUpdate( $sql, $sqlText ) {
                $this->database->update(
@@ -184,7 +184,7 @@ class DatabaseSQLTest extends MediaWikiTestCase {
 
        /**
         * @dataProvider provideDelete
-        * @covers DatabaseBase::delete
+        * @covers Database::delete
         */
        public function testDelete( $sql, $sqlText ) {
                $this->database->delete(
@@ -217,7 +217,7 @@ class DatabaseSQLTest extends MediaWikiTestCase {
 
        /**
         * @dataProvider provideUpsert
-        * @covers DatabaseBase::upsert
+        * @covers Database::upsert
         */
        public function testUpsert( $sql, $sqlText ) {
                $this->database->upsert(
@@ -253,7 +253,7 @@ class DatabaseSQLTest extends MediaWikiTestCase {
 
        /**
         * @dataProvider provideDeleteJoin
-        * @covers DatabaseBase::deleteJoin
+        * @covers Database::deleteJoin
         */
        public function testDeleteJoin( $sql, $sqlText ) {
                $this->database->deleteJoin(
@@ -300,7 +300,7 @@ class DatabaseSQLTest extends MediaWikiTestCase {
 
        /**
         * @dataProvider provideInsert
-        * @covers DatabaseBase::insert
+        * @covers Database::insert
         */
        public function testInsert( $sql, $sqlText ) {
                $this->database->insert(
@@ -353,7 +353,7 @@ class DatabaseSQLTest extends MediaWikiTestCase {
 
        /**
         * @dataProvider provideInsertSelect
-        * @covers DatabaseBase::insertSelect
+        * @covers Database::insertSelect
         */
        public function testInsertSelect( $sql, $sqlTextNative, $sqlSelect, $sqlInsert ) {
                $this->database->insertSelect(
@@ -440,7 +440,7 @@ class DatabaseSQLTest extends MediaWikiTestCase {
 
        /**
         * @dataProvider provideReplace
-        * @covers DatabaseBase::replace
+        * @covers Database::replace
         */
        public function testReplace( $sql, $sqlText ) {
                $this->database->replace(
@@ -555,7 +555,7 @@ class DatabaseSQLTest extends MediaWikiTestCase {
 
        /**
         * @dataProvider provideNativeReplace
-        * @covers DatabaseBase::nativeReplace
+        * @covers Database::nativeReplace
         */
        public function testNativeReplace( $sql, $sqlText ) {
                $this->database->nativeReplace(
@@ -582,7 +582,7 @@ class DatabaseSQLTest extends MediaWikiTestCase {
 
        /**
         * @dataProvider provideConditional
-        * @covers DatabaseBase::conditional
+        * @covers Database::conditional
         */
        public function testConditional( $sql, $sqlText ) {
                $this->assertEquals( trim( $this->database->conditional(
@@ -623,7 +623,7 @@ class DatabaseSQLTest extends MediaWikiTestCase {
 
        /**
         * @dataProvider provideBuildConcat
-        * @covers DatabaseBase::buildConcat
+        * @covers Database::buildConcat
         */
        public function testBuildConcat( $stringList, $sqlText ) {
                $this->assertEquals( trim( $this->database->buildConcat(
@@ -646,7 +646,7 @@ class DatabaseSQLTest extends MediaWikiTestCase {
 
        /**
         * @dataProvider provideBuildLike
-        * @covers DatabaseBase::buildLike
+        * @covers Database::buildLike
         */
        public function testBuildLike( $array, $sqlText ) {
                $this->assertEquals( trim( $this->database->buildLike(
@@ -677,7 +677,7 @@ class DatabaseSQLTest extends MediaWikiTestCase {
 
        /**
         * @dataProvider provideUnionQueries
-        * @covers DatabaseBase::unionQueries
+        * @covers Database::unionQueries
         */
        public function testUnionQueries( $sql, $sqlText ) {
                $this->assertEquals( trim( $this->database->unionQueries(
@@ -713,7 +713,7 @@ class DatabaseSQLTest extends MediaWikiTestCase {
        }
 
        /**
-        * @covers DatabaseBase::commit
+        * @covers Database::commit
         */
        public function testTransactionCommit() {
                $this->database->begin( __METHOD__ );
@@ -722,7 +722,7 @@ class DatabaseSQLTest extends MediaWikiTestCase {
        }
 
        /**
-        * @covers DatabaseBase::rollback
+        * @covers Database::rollback
         */
        public function testTransactionRollback() {
                $this->database->begin( __METHOD__ );
@@ -731,7 +731,7 @@ class DatabaseSQLTest extends MediaWikiTestCase {
        }
 
        /**
-        * @covers DatabaseBase::dropTable
+        * @covers Database::dropTable
         */
        public function testDropTable() {
                $this->database->setExistingTables( [ 'table' ] );
@@ -740,7 +740,7 @@ class DatabaseSQLTest extends MediaWikiTestCase {
        }
 
        /**
-        * @covers DatabaseBase::dropTable
+        * @covers Database::dropTable
         */
        public function testDropNonExistingTable() {
                $this->assertFalse(
@@ -750,7 +750,7 @@ class DatabaseSQLTest extends MediaWikiTestCase {
 
        /**
         * @dataProvider provideMakeList
-        * @covers DatabaseBase::makeList
+        * @covers Database::makeList
         */
        public function testMakeList( $list, $mode, $sqlText ) {
                $this->assertEquals( trim( $this->database->makeList(
index 80fb826..172d686 100644 (file)
@@ -7,7 +7,7 @@ class DatabaseSqliteMock extends DatabaseSqlite {
                $p['dbFilePath'] = ':memory:';
                $p['schema'] = false;
 
-               return DatabaseBase::factory( 'SqliteMock', $p );
+               return Database::factory( 'SqliteMock', $p );
        }
 
        function query( $sql, $fname = '', $tempIgnore = false ) {
index 48dc332..606a209 100644 (file)
@@ -2,11 +2,11 @@
 
 /**
  * @group Database
- * @group DatabaseBase
+ * @group Database
  */
 class DatabaseTest extends MediaWikiTestCase {
        /**
-        * @var DatabaseBase
+        * @var Database
         */
        protected $db;
 
@@ -27,7 +27,7 @@ class DatabaseTest extends MediaWikiTestCase {
        }
 
        /**
-        * @covers DatabaseBase::dropTable
+        * @covers Database::dropTable
         */
        public function testAddQuotesNull() {
                $check = "NULL";
@@ -266,7 +266,7 @@ class DatabaseTest extends MediaWikiTestCase {
        }
 
        /**
-        * @covers DatabaseBase::setTransactionListener()
+        * @covers Database::setTransactionListener()
         */
        public function testTransactionListener() {
                $db = $this->db;
@@ -298,7 +298,7 @@ class DatabaseTest extends MediaWikiTestCase {
        }
 
        /**
-        * @covers DatabaseBase::flushSnapshot()
+        * @covers Database::flushSnapshot()
         */
        public function testFlushSnapshot() {
                $db = $this->db;
@@ -350,9 +350,9 @@ class DatabaseTest extends MediaWikiTestCase {
        }
 
        /**
-        * @covers DatabaseBase::getFlag(
-        * @covers DatabaseBase::setFlag()
-        * @covers DatabaseBase::restoreFlags()
+        * @covers Database::getFlag(
+        * @covers Database::setFlag()
+        * @covers Database::restoreFlags()
         */
        public function testFlagSetting() {
                $db = $this->db;
@@ -390,8 +390,8 @@ class DatabaseTest extends MediaWikiTestCase {
        }
 
        /**
-        * @covers DatabaseBase::tablePrefix()
-        * @covers DatabaseBase::dbSchema()
+        * @covers Database::tablePrefix()
+        * @covers Database::dbSchema()
         */
        public function testMutators() {
                $old = $this->db->tablePrefix();
index 31b692b..c5603c4 100644 (file)
@@ -1,10 +1,10 @@
 <?php
 
 /**
- * Helper for testing the methods from the DatabaseBase class
+ * Helper for testing the methods from the Database class
  * @since 1.22
  */
-class DatabaseTestHelper extends DatabaseBase {
+class DatabaseTestHelper extends Database {
 
        /**
         * __CLASS__ of the test suite,
@@ -14,7 +14,7 @@ class DatabaseTestHelper extends DatabaseBase {
 
        /**
         * Array of lastSqls passed to query(),
-        * This is an array since some methods in DatabaseBase can do more than one
+        * This is an array since some methods in Database can do more than one
         * query. Cleared when calling getLastSqls().
         */
        protected $lastSqls = [];
@@ -161,7 +161,7 @@ class DatabaseTestHelper extends DatabaseBase {
                return false;
        }
 
-       function indexInfo( $table, $index, $fname = 'DatabaseBase::indexInfo' ) {
+       function indexInfo( $table, $index, $fname = 'Database::indexInfo' ) {
                return false;
        }
 
index d72768d..0f4484e 100644 (file)
@@ -270,7 +270,7 @@ class LBFactoryTest extends MediaWikiTestCase {
                );
                unset( $db );
 
-               /** @var DatabaseBase $db */
+               /** @var Database $db */
                $db = $lb->getConnection( DB_MASTER, [], '' );
                $lb->reuseConnection( $db ); // don't care
 
@@ -322,7 +322,7 @@ class LBFactoryTest extends MediaWikiTestCase {
                $factory = $this->newLBFactoryMulti(
                        [ 'localDomain' => $dbname ], [ 'dbname' => $dbname ] );
                $lb = $factory->getMainLB();
-               /** @var DatabaseBase $db */
+               /** @var Database $db */
                $db = $lb->getConnection( DB_MASTER, [], '' );
                $lb->reuseConnection( $db ); // don't care
 
index f01c47d..22d52f0 100644 (file)
@@ -16,7 +16,7 @@ class DatabaseUpdaterTest extends MediaWikiTestCase {
        }
 }
 
-class FakeDatabase extends DatabaseBase {
+class FakeDatabase extends Database {
        public $lastInsertTable;
        public $lastInsertData;
 
@@ -70,7 +70,7 @@ class FakeDatabase extends DatabaseBase {
         * member variables.
         * If no more rows are available, false is returned.
         *
-        * @param ResultWrapper|stdClass $res Object as returned from DatabaseBase::query(), etc.
+        * @param ResultWrapper|stdClass $res Object as returned from Database::query(), etc.
         * @return stdClass|bool
         * @throws DBUnexpectedError Thrown if the database returns an error
         */
@@ -83,7 +83,7 @@ class FakeDatabase extends DatabaseBase {
         * form. Fields are retrieved with $row['fieldname'].
         * If no more rows are available, false is returned.
         *
-        * @param ResultWrapper $res Result object as returned from DatabaseBase::query(), etc.
+        * @param ResultWrapper $res Result object as returned from Database::query(), etc.
         * @return array|bool
         * @throws DBUnexpectedError Thrown if the database returns an error
         */
index 560b6d2..ce6894e 100644 (file)
@@ -129,7 +129,7 @@ class BatchRowUpdateTest extends MediaWikiTestCase {
                $db = $this->mockDb();
                $db->expects( $this->once() )
                        ->method( 'select' )
-                       // only testing second parameter of DatabaseBase::select
+                       // only testing second parameter of Database::select
                        ->with( 'some_table', $columns )
                        ->will( $this->returnValue( new ArrayIterator( [] ) ) );
 
@@ -164,7 +164,7 @@ class BatchRowUpdateTest extends MediaWikiTestCase {
 
        /**
         * Slightly hackish to use reflection, but asserting different parameters
-        * to consecutive calls of DatabaseBase::select in phpunit is error prone
+        * to consecutive calls of Database::select in phpunit is error prone
         *
         * @dataProvider provider_readerSelectConditions
         */
@@ -214,7 +214,7 @@ class BatchRowUpdateTest extends MediaWikiTestCase {
        protected function consecutivelyReturnFromSelect( array $results ) {
                $retvals = [];
                foreach ( $results as $rows ) {
-                       // The DatabaseBase::select method returns iterators, so we do too.
+                       // The Database::select method returns iterators, so we do too.
                        $retvals[] = $this->returnValue( new ArrayIterator( $rows ) );
                }
 
@@ -235,8 +235,7 @@ class BatchRowUpdateTest extends MediaWikiTestCase {
        }
 
        protected function mockDb() {
-               // Cant mock from DatabaseType or DatabaseBase, they dont
-               // have the full gamut of methods
+               // @TODO: mock from Database
                // FIXME: the constructor normally sets mAtomicLevels and mSrvCache
                $databaseMysql = $this->getMockBuilder( 'DatabaseMysql' )
                        ->disableOriginalConstructor()