Merge "rdbms: make select() warn when FOR UPDATE is used with aggregation"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Mon, 23 Apr 2018 20:01:13 +0000 (20:01 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Mon, 23 Apr 2018 20:01:13 +0000 (20:01 +0000)
174 files changed:
INSTALL
RELEASE-NOTES-1.31
RELEASE-NOTES-1.32
autoload.php
composer.json
docs/scripts.txt
includes/Category.php
includes/CategoryViewer.php
includes/DefaultSettings.php
includes/GlobalFunctions.php
includes/NoLocalSettings.php
includes/OutputPage.php
includes/Revision.php
includes/ServiceWiring.php
includes/Setup.php
includes/Storage/RevisionArchiveRecord.php
includes/Storage/RevisionStore.php
includes/Storage/RevisionStoreRecord.php
includes/Storage/SqlBlobStore.php
includes/WebRequest.php
includes/WebStart.php
includes/api/ApiMove.php
includes/api/ApiUserrights.php
includes/db/MWLBFactory.php
includes/deferred/LinksDeletionUpdate.php
includes/filebackend/FileBackendGroup.php
includes/filebackend/filejournal/DBFileJournal.php
includes/filerepo/FileBackendDBRepoWrapper.php
includes/filerepo/FileRepo.php
includes/filerepo/ForeignAPIRepo.php
includes/filerepo/LocalRepo.php
includes/filerepo/RepoGroup.php
includes/filerepo/file/ArchivedFile.php
includes/filerepo/file/File.php
includes/filerepo/file/ForeignAPIFile.php
includes/filerepo/file/ForeignDBFile.php
includes/filerepo/file/LocalFile.php
includes/filerepo/file/OldLocalFile.php
includes/import/ImportStreamSource.php
includes/import/ImportableUploadRevisionImporter.php
includes/installer/DatabaseUpdater.php
includes/installer/WebInstallerOptions.php
includes/installer/i18n/be-tarask.json
includes/installer/i18n/de.json
includes/installer/i18n/el.json
includes/installer/i18n/fr.json
includes/installer/i18n/he.json
includes/installer/i18n/ko.json
includes/installer/i18n/li.json
includes/installer/i18n/mk.json
includes/installer/i18n/pt.json
includes/installer/i18n/qqq.json
includes/installer/i18n/sv.json
includes/installer/i18n/yi.json
includes/installer/i18n/zh-hans.json
includes/installer/i18n/zh-hant.json
includes/libs/CSSMin.php
includes/libs/CryptRand.php
includes/libs/rdbms/database/Database.php
includes/libs/rdbms/database/IDatabase.php
includes/libs/rdbms/lbfactory/LBFactory.php
includes/libs/rdbms/loadbalancer/ILoadBalancer.php
includes/libs/rdbms/loadbalancer/LoadBalancer.php
includes/media/Bitmap.php
includes/objectcache/ObjectCache.php
includes/page/Article.php
includes/page/WikiPage.php
includes/parser/CacheTime.php
includes/parser/DateFormatter.php
includes/parser/ParserCache.php
includes/parser/ParserOptions.php
includes/parser/ParserOutput.php
includes/resourceloader/ResourceLoaderClientHtml.php
includes/resourceloader/ResourceLoaderStartUpModule.php
includes/resourceloader/ResourceLoaderWikiModule.php
includes/skins/MediaWikiI18N.php [deleted file]
includes/skins/QuickTemplate.php
includes/sparql/SparqlClient.php
includes/specials/SpecialAutoblockList.php
includes/specials/SpecialBlockList.php
includes/specials/SpecialFileDuplicateSearch.php
includes/specials/SpecialNewpages.php
includes/specials/SpecialPrefixindex.php
includes/specials/SpecialProtectedpages.php
includes/specials/SpecialProtectedtitles.php
includes/specials/SpecialUnblock.php
includes/specials/SpecialUserrights.php
includes/templates/NoLocalSettings.mustache
includes/user/User.php
languages/i18n/ar.json
languages/i18n/ast.json
languages/i18n/be-tarask.json
languages/i18n/be.json
languages/i18n/bn.json
languages/i18n/bs.json
languages/i18n/cdo.json
languages/i18n/ce.json
languages/i18n/cs.json
languages/i18n/de.json
languages/i18n/egl.json
languages/i18n/el.json
languages/i18n/en.json
languages/i18n/es.json
languages/i18n/et.json
languages/i18n/eu.json
languages/i18n/fi.json
languages/i18n/fr.json
languages/i18n/gl.json
languages/i18n/he.json
languages/i18n/ilo.json
languages/i18n/io.json
languages/i18n/it.json
languages/i18n/ja.json
languages/i18n/km.json
languages/i18n/ko.json
languages/i18n/lb.json
languages/i18n/li.json
languages/i18n/lv.json
languages/i18n/mk.json
languages/i18n/ml.json
languages/i18n/nl.json
languages/i18n/pl.json
languages/i18n/ps.json
languages/i18n/pt.json
languages/i18n/qqq.json
languages/i18n/ru.json
languages/i18n/sah.json
languages/i18n/skr-arab.json
languages/i18n/sl.json
languages/i18n/sr-ec.json
languages/i18n/sr-el.json
languages/i18n/sv.json
languages/i18n/szl.json
languages/i18n/ur.json
languages/i18n/vi.json
languages/i18n/yi.json
languages/i18n/yue.json
languages/i18n/zh-hans.json
languages/i18n/zh-hant.json
languages/messages/MessagesEs.php
languages/messages/MessagesGor.php [new file with mode: 0644]
load.php
mw-config/config.js
package.json
resources/Resources.php
resources/src/jquery/jquery.makeCollapsible.css
resources/src/jquery/jquery.makeCollapsible.js
resources/src/jquery/jquery.tablesorter.js
resources/src/mediawiki.action/mediawiki.action.delete.file.js
resources/src/mediawiki.action/mediawiki.action.delete.js
resources/src/mediawiki.legacy/wikibits.js
resources/src/mediawiki.special/mediawiki.special.edittags.js
resources/src/mediawiki.special/mediawiki.special.revisionDelete.js
resources/src/mediawiki.special/mediawiki.special.userrights.js
resources/src/mediawiki.widgets.visibleLengthLimit/mediawiki.widgets.visibleLengthLimit.js
tests/common/TestsAutoLoader.php
tests/parser/ParserTestRunner.php
tests/phpunit/ResourceLoaderTestCase.php
tests/phpunit/includes/OutputPageTest.php
tests/phpunit/includes/Storage/MutableRevisionRecordTest.php
tests/phpunit/includes/Storage/RevisionArchiveRecordTest.php [new file with mode: 0644]
tests/phpunit/includes/Storage/RevisionRecordTests.php [new file with mode: 0644]
tests/phpunit/includes/Storage/RevisionStoreRecordTest.php
tests/phpunit/includes/Storage/SqlBlobStoreTest.php
tests/phpunit/includes/api/ApiBaseTest.php
tests/phpunit/includes/api/ApiMoveTest.php [new file with mode: 0644]
tests/phpunit/includes/db/LoadBalancerTest.php
tests/phpunit/includes/libs/CSSMinTest.php
tests/phpunit/includes/libs/rdbms/database/DatabaseSQLTest.php
tests/phpunit/includes/libs/rdbms/database/DatabaseTest.php
tests/phpunit/includes/resourceloader/ResourceLoaderClientHtmlTest.php
tests/phpunit/includes/resourceloader/ResourceLoaderWikiModuleTest.php
tests/qunit/suites/resources/jquery/jquery.tablesorter.test.js
tests/selenium/selenium.sh

diff --git a/INSTALL b/INSTALL
index 1a59f0b..3b93505 100644 (file)
--- a/INSTALL
+++ b/INSTALL
@@ -9,7 +9,7 @@ Required software:
 * Web server with PHP 5.5.9 or higher.
 * A SQL server, the following types are supported
 ** MySQL 5.5.8 or higher
-** PostgreSQL 8.3 or higher
+** PostgreSQL 9.2 or higher
 ** SQLite 3.3.7 or higher
 ** Oracle 9.0.1 or higher
 ** Microsoft SQL Server 2005 (9.00.1399)
index 21b29cb..f6b4cfe 100644 (file)
@@ -37,6 +37,12 @@ production.
   set $wgTidyConfig to null and also set $wgUseTidy to true.
 * $wgLogAutopatrol now defaults to false instead of true.
 * $wgValidateAllHtml was removed and will be ignored.
+* $wgScriptExtension was removed (deprecated and ignored since 1.25).
+  See 1.25 release notes for more information.
+* $wgUseAjax is now marked as deprecated, just like the deprecated AJAX
+  framework that it enables. Some extensions mistakenly used this to check
+  whether any AJAX functionality at all should be enabled, further making this
+  problematic to retain.
 
 === New features in 1.31 ===
 * (T76554) User sub-pages named ….json are now protected in the same way that ….js
@@ -104,7 +110,7 @@ production.
 * Updated wikimedia/running-stat from 1.1.0 to 1.2.0.
 * Updated wikimedia/wrappedstring from 2.2.0 to 2.3.0.
 * Updated mediawiki/at-ease from 1.1.0 to 1.2.0.
-* Updated wikimedia/php-session-serializer from 1.0.4 to 1.0.5.
+* Updated wikimedia/php-session-serializer from 1.0.4 to 1.0.6.
 * Updated wikimedia/remex-html from 1.0.2 to 1.0.3.
 * …
 
@@ -121,14 +127,19 @@ production.
   'mediawiki.viewport' module instead.
 * The deprecated 'mediawiki.widgets.CategorySelector' module alias was removed.
   Use the 'mediawiki.widgets.CategoryMultiselectWidget' module directly instead.
+* mediawiki/at-ease was replaced with wikimedia/at-ease.
 
 === Bug fixes in 1.31 ===
-* (T90902) Non-breaking space in header ID breaks anchor
+* (T90902) Non-breaking space in header ID breaks anchor.
+* (T189375) CSSMin now allows quoted urls in `url()` syntax to start with a space.
 
 === Action API changes in 1.31 ===
 * (T185058) The 'name' value to tgprop for action=query&list=tags has been
   removed. It has never made a difference in the output, the name was always
   returned regardless.
+* The 'watch' and 'unwatch' parameters for action=move have been removed.  They
+  were deprecated and also accidentally nonfunctional since 1.17 in 2010.  Use
+  'watchlist' instead.
 
 === Action API internal changes in 1.31 ===
 * ApiBase::getProfileDBTime was removed (deprecated since 1.25)
@@ -147,6 +158,7 @@ changes to languages because of Phabricator reports.
 * (T186647) New language support: Kumyk [къумукъ] (kum).
 * (T187750) New language support: Spanish formal address (es-formal).
 * (T187824) New language support: Hungarian formal address (hu-formal).
+* (T189127) New language support: Gorontalo (gor).
 
 === Breaking changes in 1.31 ===
 * MessageBlobStore::insertMessageBlob() (deprecated in 1.27) was removed.
@@ -372,7 +384,7 @@ Oracle and Microsoft SQL Server.
 
 The supported versions are:
 
-* MySQL 5.0.3 or later
+* MySQL 5.5.8 or later
 * PostgreSQL 9.2 or later
 * SQLite 3.3.7 or later
 * Oracle 9.0.1 or later
index 57c6e6a..2eb3679 100644 (file)
@@ -7,7 +7,10 @@ production.
 
 === Configuration changes in 1.32 ===
 * (T115414) The $wgEnableAPI and $wgEnableWriteAPI settings, deprecated in 1.31, have been removed.
-* The $wgUseAjax setting is now formally deprecated, and MediaWiki will act as if it is always set.
+* The $wgUseAjax setting, deprecated in 1.31, is now ignored.
+* The $wgSiteSupportPage setting, unused since 1.5, was removed.
+* $wgJpegQuality was added to allow configuring the quality of JPEG thumbnails (default 80).
+* The default quality of JPEG thumbnails generated by GD was reduced from 95 to 80.
 * …
 
 === New features in 1.32 ===
@@ -42,8 +45,17 @@ changes to languages because of Phabricator reports.
 * …
 
 === Breaking changes in 1.32 ===
-* $wgRequestTime (deprecated in 1.25) was removed.
+* $wgRequestTime was removed (deprecated in 1.25).
   Use $_SERVER['REQUEST_TIME_FLOAT'] or WebRequest::getElapsedTime() instead.
+* The MediaWikiI18N class was removed (deprecated in 1.31).
+* QuickTemplate::setTranslator() was removed (deprecated in 1.31).
+  Use Skin::msg() instead.
+* wfInitShellLocale() was removed (deprecated in 1.30).
+* wfShellExecDisabled() was removed (deprecated in 1.30).
+* The type string for the parameter $lang of DateFormatter::getInstance is
+  removed (deprecated in 1.31).
+* The EDIT_TOKEN_SUFFIX constant was removed (deprecated in 1.27).
+  Use MediaWiki\Session\Token::SUFFIX instead.
 
 === Deprecations in 1.32 ===
 * Use of a StartProfiler.php file is deprecated in favour of placing
@@ -62,7 +74,7 @@ Oracle and Microsoft SQL Server.
 
 The supported versions are:
 
-* MySQL 5.0.3 or later
+* MySQL 5.5.8 or later
 * PostgreSQL 9.2 or later
 * SQLite 3.3.7 or later
 * Oracle 9.0.1 or later
index 0e1b30f..bc0e69e 100644 (file)
@@ -843,7 +843,6 @@ $wgAutoloadLocalClasses = [
        'MediaTransformInvalidParametersException' => __DIR__ . '/includes/media/MediaTransformInvalidParametersException.php',
        'MediaTransformOutput' => __DIR__ . '/includes/media/MediaTransformOutput.php',
        'MediaWiki' => __DIR__ . '/includes/MediaWiki.php',
-       'MediaWikiI18N' => __DIR__ . '/includes/skins/MediaWikiI18N.php',
        'MediaWikiShell' => __DIR__ . '/maintenance/shell.php',
        'MediaWikiSite' => __DIR__ . '/includes/site/MediaWikiSite.php',
        'MediaWikiTitleCodec' => __DIR__ . '/includes/title/MediaWikiTitleCodec.php',
index ebc800a..98e4d49 100644 (file)
                "ext-mbstring": "*",
                "ext-xml": "*",
                "liuggio/statsd-php-client": "1.0.18",
-               "mediawiki/at-ease": "1.2.0",
                "oojs/oojs-ui": "v0.26.4",
                "oyejorge/less.php": "1.7.0.14",
                "php": ">=5.5.9",
                "psr/log": "1.0.2",
                "wikimedia/assert": "0.2.2",
+               "wikimedia/at-ease": "1.2.0",
                "wikimedia/base-convert": "1.0.1",
                "wikimedia/cdb": "1.4.1",
                "wikimedia/cldr-plural-rule-parser": "1.0.0",
@@ -37,7 +37,7 @@
                "wikimedia/html-formatter": "1.0.1",
                "wikimedia/ip-set": "1.2.0",
                "wikimedia/object-factory": "1.0.0",
-               "wikimedia/php-session-serializer": "1.0.5",
+               "wikimedia/php-session-serializer": "1.0.6",
                "wikimedia/purtle": "1.0.7",
                "wikimedia/relpath": "2.1.1",
                "wikimedia/remex-html": "1.0.3",
index 53dff36..dff428c 100644 (file)
@@ -39,14 +39,10 @@ Primary scripts:
     maintenance/archives/patch-profiling.sql patch to the database.
 
     To enable the profileinfo.php itself, you'll need to set $wgDBadminuser
-    and $wgDBadminpassword in your LocalSettings.php, as well as $wgEnableProfileInfo 
+    and $wgDBadminpassword in your LocalSettings.php, as well as $wgEnableProfileInfo
     See also https://www.mediawiki.org/wiki/Manual:Profiling .
 
   thumb.php
     Script used to resize images if it is configured to be done when the web
     browser requests the image and not when generating the page. This script can
     be used as a 404 handler to generate image thumbs when they don't exist.
-
-There is also a file with a .php5 extension for each script. They can be used if
-the web server needs a .php5 to run the file with the PHP 5 engine and runs .php
-scripts with PHP 4. You should not use them anymore.
index ac5cc42..46b86d8 100644 (file)
@@ -328,7 +328,7 @@ class Category {
                $dbw = wfGetDB( DB_MASTER );
                # Avoid excess contention on the same category (T162121)
                $name = __METHOD__ . ':' . md5( $this->mName );
-               $scopedLock = $dbw->getScopedLockAndFlush( $name, __METHOD__, 1 );
+               $scopedLock = $dbw->getScopedLockAndFlush( $name, __METHOD__, 0 );
                if ( !$scopedLock ) {
                        return false;
                }
index f36c758..4202249 100644 (file)
@@ -735,11 +735,7 @@ class CategoryViewer extends ContextSource {
                        $totalcnt = $dbcnt;
                } elseif ( $rescnt < $this->limit && !$fromOrUntil ) {
                        // Case 2: not sane, but salvageable.  Use the number of results.
-                       // Since there are fewer than 200, we can also take this opportunity
-                       // to refresh the incorrect category table entry -- which should be
-                       // quick due to the small number of entries.
                        $totalcnt = $rescnt;
-                       DeferredUpdates::addCallableUpdate( [ $this->cat, 'refreshCounts' ] );
                } else {
                        // Case 3: hopeless.  Don't give a total count at all.
                        // Messages: category-subcat-count-limited, category-article-count-limited,
index f34b00a..7c7277a 100644 (file)
@@ -157,19 +157,6 @@ $wgUsePathInfo = ( strpos( PHP_SAPI, 'cgi' ) === false ) &&
        ( strpos( PHP_SAPI, 'apache2filter' ) === false ) &&
        ( strpos( PHP_SAPI, 'isapi' ) === false );
 
-/**
- * The extension to append to script names by default.
- *
- * Some hosting providers used PHP 4 for *.php files, and PHP 5 for *.php5.
- * This variable was provided to support those providers.
- *
- * @since 1.11
- * @deprecated since 1.25; support for '.php5' has been phased out of MediaWiki
- *  proper. Backward-compatibility can be maintained by configuring your web
- *  server to rewrite URLs. See RELEASE-NOTES for details.
- */
-$wgScriptExtension = '.php';
-
 /**@}*/
 
 /************************************************************************//**
@@ -503,9 +490,6 @@ $wgImgAuthUrlPathMap = [];
  *   - descBaseUrl       URL of image description pages, e.g. https://en.wikipedia.org/wiki/File:
  *   - scriptDirUrl      URL of the MediaWiki installation, equivalent to $wgScriptPath, e.g.
  *                       https://en.wikipedia.org/w
- *   - scriptExtension   Script extension of the MediaWiki installation, equivalent to
- *                       $wgScriptExtension, e.g. ".php5". Defaults to ".php".
- *
  *   - articleUrl        Equivalent to $wgArticlePath, e.g. https://en.wikipedia.org/wiki/$1
  *   - fetchDescription  Fetch the text of the remote file description page. Equivalent to
  *                       $wgFetchCommonsDescriptions.
@@ -1101,6 +1085,15 @@ $wgJpegTran = '/usr/bin/jpegtran';
  */
 $wgJpegPixelFormat = 'yuv420';
 
+/**
+ * When scaling a JPEG thumbnail, this is the quality we request
+ * from the backend. It should be an int between 1 and 100,
+ * with 100 indicating 100% quality.
+ *
+ * @since 1.32
+ */
+$wgJpegQuality = 80;
+
 /**
  * Some tests and extensions use exiv2 to manipulate the Exif metadata in some
  * image formats.
@@ -3260,11 +3253,6 @@ $wgXhtmlNamespaces = [];
  */
 $wgSiteNotice = '';
 
-/**
- * If this is set, a "donate" link will appear in the sidebar. Set it to a URL.
- */
-$wgSiteSupportPage = '';
-
 /**
  * Default skin, for new users and anonymous visitors. Registered users may
  * change this to any one of the other available skins in their preferences.
@@ -8183,7 +8171,7 @@ $wgAPIUselessQueryPages = [
 /**
  * Enable AJAX framework
  *
- * @deprecated since MediaWiki 1.32 and ignored
+ * @deprecated (officially) since MediaWiki 1.31 and ignored since 1.32
  */
 $wgUseAjax = true;
 
@@ -8294,7 +8282,7 @@ $wgMaxShellWallClockTime = 180;
 $wgShellCgroup = false;
 
 /**
- * Executable path of the PHP cli binary (php/php5). Should be set up on install.
+ * Executable path of the PHP cli binary. Should be set up on install.
  */
 $wgPhpCli = '/usr/bin/php';
 
index 3dfe12e..519b22c 100644 (file)
@@ -2269,18 +2269,6 @@ function wfEscapeShellArg( /*...*/ ) {
        return call_user_func_array( Shell::class . '::escape', $args );
 }
 
-/**
- * Check if wfShellExec() is effectively disabled via php.ini config
- *
- * @return bool|string False or 'disabled'
- * @since 1.22
- * @deprecated since 1.30 use MediaWiki\Shell::isDisabled()
- */
-function wfShellExecDisabled() {
-       wfDeprecated( __FUNCTION__, '1.30' );
-       return Shell::isDisabled() ? 'disabled' : false;
-}
-
 /**
  * Execute a shell command, with time and memory limits mirrored from the PHP
  * configuration if supported.
@@ -2362,18 +2350,6 @@ function wfShellExecWithStderr( $cmd, &$retval = null, $environ = [], $limits =
                [ 'duplicateStderr' => true, 'profileMethod' => wfGetCaller() ] );
 }
 
-/**
- * Formerly set the locale for locale-sensitive operations
- *
- * This is now done in Setup.php.
- *
- * @deprecated since 1.30, no longer needed
- * @see $wgShellLocale
- */
-function wfInitShellLocale() {
-       wfDeprecated( __FUNCTION__, '1.30' );
-}
-
 /**
  * Generate a shell-escaped command line string to run a MediaWiki cli script.
  * Note that $parameters should be a flat array and an option with an argument
@@ -2583,6 +2559,7 @@ function wfDiff( $before, $after, $params = '-u' ) {
  * @throws MWException
  */
 function wfUsePHP( $req_ver ) {
+       wfDeprecated( __FUNCTION__, '1.30' );
        $php_ver = PHP_VERSION;
 
        if ( version_compare( $php_ver, (string)$req_ver, '<' ) ) {
@@ -3059,6 +3036,7 @@ function wfWaitForSlaves(
  * @param int $seconds
  */
 function wfCountDown( $seconds ) {
+       wfDeprecated( __FUNCTION__, '1.31' );
        for ( $i = $seconds; $i >= 0; $i-- ) {
                if ( $i != $seconds ) {
                        echo str_repeat( "\x08", strlen( $i + 1 ) );
index b8bfd6a..46e9630 100644 (file)
 
 # T32219 : can not use pathinfo() on URLs since slashes do not match
 $matches = [];
-$ext = 'php';
 $path = '/';
 foreach ( array_filter( explode( '/', $_SERVER['PHP_SELF'] ) ) as $part ) {
-       if ( !preg_match( '/\.(php5?)$/', $part, $matches ) ) {
+       if ( !preg_match( '/\.(php)$/', $part, $matches ) ) {
                $path .= "$part/";
        } else {
-               $ext = $matches[1] == 'php5' ? 'php5' : 'php';
                break;
        }
 }
@@ -56,7 +54,6 @@ try {
                [
                        'wgVersion' => ( isset( $wgVersion ) ? $wgVersion : 'VERSION' ),
                        'path' => $path,
-                       'ext' => $ext,
                        'localSettingsExists' => file_exists( MW_CONFIG_FILE ),
                        'installerStarted' => $installerStarted
                ]
index dd64413..37527cf 100644 (file)
@@ -752,8 +752,10 @@ class OutputPage extends ContextSource {
                        'epoch' => $config->get( 'CacheEpoch' )
                ];
                if ( $config->get( 'UseSquid' ) ) {
-                       // T46570: the core page itself may not change, but resources might
-                       $modifiedTimes['sepoch'] = wfTimestamp( TS_MW, time() - $config->get( 'SquidMaxage' ) );
+                       $modifiedTimes['sepoch'] = wfTimestamp( TS_MW, $this->getCdnCacheEpoch(
+                               time(),
+                               $config->get( 'SquidMaxage' )
+                       ) );
                }
                Hooks::run( 'OutputPageCheckLastModified', [ &$modifiedTimes, $this ] );
 
@@ -815,6 +817,19 @@ class OutputPage extends ContextSource {
                return true;
        }
 
+       /**
+        * @param int $reqTime Time of request (eg. now)
+        * @param int $maxAge Cache TTL in seconds
+        * @return int Timestamp
+        */
+       private function getCdnCacheEpoch( $reqTime, $maxAge ) {
+               // Ensure Last-Modified is never more than (wgSquidMaxage) in the past,
+               // because even if the wiki page content hasn't changed since, static
+               // resources may have changed (skin HTML, interface messages, urls, etc.)
+               // and must roll-over in a timely manner (T46570)
+               return $reqTime - $maxAge;
+       }
+
        /**
         * Override the last modified timestamp
         *
index 22eb115..c948d9e 100644 (file)
@@ -1069,7 +1069,9 @@ class Revision implements IDBAccessObject {
                        return false;
                }
 
-               $cacheKey = isset( $row->old_id ) ? ( 'tt:' . $row->old_id ) : null;
+               $cacheKey = isset( $row->old_id )
+                       ? SqlBlobStore::makeAddressFromTextId( $row->old_id )
+                       : null;
 
                return self::getBlobStore( $wiki )->expandBlob( $text, $flags, $cacheKey );
        }
index da3f320..f97d60d 100644 (file)
@@ -62,7 +62,7 @@ return [
                $class = MWLBFactory::getLBFactoryClass( $lbConf );
 
                $instance = new $class( $lbConf );
-               MWLBFactory::setSchemaAliases( $instance );
+               MWLBFactory::setSchemaAliases( $instance, $mainConfig );
 
                return $instance;
        },
index 6513cdd..6825c7b 100644 (file)
@@ -37,6 +37,11 @@ if ( !defined( 'MEDIAWIKI' ) ) {
  * Pre-config setup: Before loading LocalSettings.php
  */
 
+// Sanity check (T5782, T122807)
+if ( ini_get( 'mbstring.func_overload' ) ) {
+       die( 'MediaWiki does not support installations where mbstring.func_overload is non-zero.' );
+}
+
 // Start the autoloader, so that extensions can derive classes from core files
 require_once "$IP/includes/AutoLoader.php";
 
@@ -279,7 +284,6 @@ if ( !$wgLocalFileRepo ) {
                'name' => 'local',
                'directory' => $wgUploadDirectory,
                'scriptDirUrl' => $wgScriptPath,
-               'scriptExtension' => '.php',
                'url' => $wgUploadBaseUrl ? $wgUploadBaseUrl . $wgUploadPath : $wgUploadPath,
                'hashLevels' => $wgHashedUploadDirectory ? 2 : 0,
                'thumbScriptUrl' => $wgThumbnailScriptPath,
index 9999179..213ee3c 100644 (file)
@@ -67,6 +67,9 @@ class RevisionArchiveRecord extends RevisionRecord {
                parent::__construct( $title, $slots, $wikiId );
                Assert::parameterType( 'object', $row, '$row' );
 
+               $timestamp = wfTimestamp( TS_MW, $row->ar_timestamp );
+               Assert::parameter( is_string( $timestamp ), '$row->rev_timestamp', 'must be a valid timestamp' );
+
                $this->mArchiveId = intval( $row->ar_id );
 
                // NOTE: ar_page_id may be different from $this->mTitle->getArticleID() in some cases,
@@ -81,11 +84,11 @@ class RevisionArchiveRecord extends RevisionRecord {
                $this->mId = isset( $row->ar_rev_id ) ? intval( $row->ar_rev_id ) : null;
                $this->mComment = $comment;
                $this->mUser = $user;
-               $this->mTimestamp = wfTimestamp( TS_MW, $row->ar_timestamp );
+               $this->mTimestamp = $timestamp;
                $this->mMinorEdit = boolval( $row->ar_minor_edit );
                $this->mDeleted = intval( $row->ar_deleted );
-               $this->mSize = intval( $row->ar_len );
-               $this->mSha1 = isset( $row->ar_sha1 ) ? $row->ar_sha1 : null;
+               $this->mSize = isset( $row->ar_len ) ? intval( $row->ar_len ) : null;
+               $this->mSha1 = !empty( $row->ar_sha1 ) ? $row->ar_sha1 : null;
        }
 
        /**
@@ -94,7 +97,7 @@ class RevisionArchiveRecord extends RevisionRecord {
         * @return int
         */
        public function getArchiveId() {
-               return $this->mId;
+               return $this->mArchiveId;
        }
 
        /**
index 1f0afae..1d921e3 100644 (file)
@@ -391,7 +391,7 @@ class RevisionStore
 
                // getTextIdFromAddress() is free to insert something into the text table, so $textId
                // may be a new value, not anything already contained in $blobAddress.
-               $blobAddress = 'tt:' . $textId;
+               $blobAddress = SqlBlobStore::makeAddressFromTextId( $textId );
 
                $comment = $this->failOnNull( $rev->getComment( RevisionRecord::RAW ), 'comment' );
                $user = $this->failOnNull( $rev->getUser( RevisionRecord::RAW ), 'user' );
@@ -769,7 +769,9 @@ class RevisionStore
 
                        if ( isset( $row->rev_text_id ) && $row->rev_text_id > 0 ) {
                                $mainSlotRow->slot_content_id = $row->rev_text_id;
-                               $mainSlotRow->content_address = 'tt:' . $row->rev_text_id;
+                               $mainSlotRow->content_address = SqlBlobStore::makeAddressFromTextId(
+                                       $row->rev_text_id
+                               );
                        }
 
                        // This is used by null-revisions
@@ -808,7 +810,7 @@ class RevisionStore
                                ? intval( $row['slot_origin'] )
                                : null;
                        $mainSlotRow->content_address = isset( $row['text_id'] )
-                               ? 'tt:' . intval( $row['text_id'] )
+                               ? SqlBlobStore::makeAddressFromTextId( intval( $row['text_id'] ) )
                                : null;
                        $mainSlotRow->content_size = isset( $row['len'] ) ? intval( $row['len'] ) : null;
                        $mainSlotRow->content_sha1 = isset( $row['sha1'] ) ? strval( $row['sha1'] ) : null;
index e8efcfa..d092f22 100644 (file)
@@ -81,7 +81,7 @@ class RevisionStoreRecord extends RevisionRecord {
                // allows rev_parent_id to be NULL.
                $this->mParentId = isset( $row->rev_parent_id ) ? intval( $row->rev_parent_id ) : null;
                $this->mSize = isset( $row->rev_len ) ? intval( $row->rev_len ) : null;
-               $this->mSha1 = isset( $row->rev_sha1 ) ? $row->rev_sha1 : null;
+               $this->mSha1 = !empty( $row->rev_sha1 ) ? $row->rev_sha1 : null;
 
                // NOTE: we must not call $this->mTitle->getLatestRevID() here, since the state of
                // page_latest may be in limbo during revision creation. In that case, calling
index 0ff7c13..70d7d42 100644 (file)
@@ -244,7 +244,7 @@ class SqlBlobStore implements IDBAccessObject, BlobStore {
 
                        $textId = $dbw->insertId();
 
-                       return 'tt:' . $textId;
+                       return self::makeAddressFromTextId( $textId );
                } catch ( MWException $e ) {
                        throw new BlobAccessException( $e->getMessage(), 0, $e );
                }
@@ -542,11 +542,12 @@ class SqlBlobStore implements IDBAccessObject, BlobStore {
         * Currently, $address must start with 'tt:' followed by a decimal integer representing
         * the old_id; if $address does not start with 'tt:', null is returned. However,
         * the implementation may change to insert rows into the text table on the fly.
+        * This implies that this method cannot be static.
         *
         * @note This method exists for use with the text table based storage schema.
         * It should not be assumed that is will function with all future kinds of content addresses.
         *
-        * @deprecated since 1.31, so not assume that all blob addresses refer to a row in the text
+        * @deprecated since 1.31, so don't assume that all blob addresses refer to a row in the text
         * table. This method should become private once the relevant refactoring in WikiPage is
         * complete.
         *
@@ -570,6 +571,22 @@ class SqlBlobStore implements IDBAccessObject, BlobStore {
                return $textId;
        }
 
+       /**
+        * Returns an address referring to content stored in the text table row with the given ID.
+        * The address schema for blobs stored in the text table is "tt:" followed by an integer
+        * that corresponds to a value of the old_id field.
+        *
+        * @deprecated since 1.31. This method should become private once the relevant refactoring
+        * in WikiPage is complete.
+        *
+        * @param int $id
+        *
+        * @return string
+        */
+       public static function makeAddressFromTextId( $id ) {
+               return 'tt:' . $id;
+       }
+
        /**
         * Splits a blob address into three parts: the schema, the ID, and parameters/flags.
         *
index fa8f84d..c6ddf81 100644 (file)
@@ -141,7 +141,7 @@ class WebRequest {
                                $router->add( "$wgScript/$1" );
 
                                if ( isset( $_SERVER['SCRIPT_NAME'] )
-                                       && preg_match( '/\.php5?/', $_SERVER['SCRIPT_NAME'] )
+                                       && preg_match( '/\.php/', $_SERVER['SCRIPT_NAME'] )
                                ) {
                                        # Check for SCRIPT_NAME, we handle index.php explicitly
                                        # But we do have some other .php files such as img_auth.php
index b24ff7a..878dd3e 100644 (file)
  * @file
  */
 
-if ( ini_get( 'mbstring.func_overload' ) ) {
-       die( 'MediaWiki does not support installations where mbstring.func_overload is non-zero.' );
-}
-
 # T17461: Make IE8 turn off content sniffing. Everybody else should ignore this
 # We're adding it here so that it's *always* set, even for alternate entry
 # points and when $wgOut gets disabled or overridden.
index 2814564..f6b6b35 100644 (file)
@@ -99,7 +99,6 @@ class ApiMove extends ApiBase {
                // a redirect to the new title. This is not safe, but what we did before was
                // even worse: we just determined whether a redirect should have been created,
                // and reported that it was created if it should have, without any checks.
-               // Also note that isRedirect() is unreliable because of T39209.
                $r['redirectcreated'] = $fromTitle->exists();
 
                $r['moveoverredirect'] = $toTitleExists;
@@ -152,10 +151,6 @@ class ApiMove extends ApiBase {
                $watch = 'preferences';
                if ( isset( $params['watchlist'] ) ) {
                        $watch = $params['watchlist'];
-               } elseif ( $params['watch'] ) {
-                       $watch = 'watch';
-               } elseif ( $params['unwatch'] ) {
-                       $watch = 'unwatch';
                }
 
                // Watch pages
@@ -250,14 +245,6 @@ class ApiMove extends ApiBase {
                        'movetalk' => false,
                        'movesubpages' => false,
                        'noredirect' => false,
-                       'watch' => [
-                               ApiBase::PARAM_DFLT => false,
-                               ApiBase::PARAM_DEPRECATED => true,
-                       ],
-                       'unwatch' => [
-                               ApiBase::PARAM_DFLT => false,
-                               ApiBase::PARAM_DEPRECATED => true,
-                       ],
                        'watchlist' => [
                                ApiBase::PARAM_DFLT => 'preferences',
                                ApiBase::PARAM_TYPE => [
index 56c2c84..47f3bc5 100644 (file)
@@ -100,7 +100,7 @@ class ApiUserrights extends ApiBase {
                $tags = $params['tags'];
 
                // Check if user can add tags
-               if ( !is_null( $tags ) ) {
+               if ( $tags !== null ) {
                        $ableToTag = ChangeTags::canAddTagsAccompanyingChange( $tags, $pUser );
                        if ( !$ableToTag->isOK() ) {
                                $this->dieStatus( $ableToTag );
@@ -112,8 +112,9 @@ class ApiUserrights extends ApiBase {
                $r['user'] = $user->getName();
                $r['userid'] = $user->getId();
                list( $r['added'], $r['removed'] ) = $form->doSaveUserGroups(
+                       // Don't pass null to doSaveUserGroups() for array params, cast to empty array
                        $user, (array)$add, (array)$params['remove'],
-                       $params['reason'], $tags, $groupExpiries
+                       $params['reason'], (array)$tags, $groupExpiries
                );
 
                $result = $this->getResult();
index 82d9c1d..79f787d 100644 (file)
@@ -208,10 +208,8 @@ abstract class MWLBFactory {
                return $class;
        }
 
-       public static function setSchemaAliases( LBFactory $lbFactory ) {
-               $mainLB = $lbFactory->getMainLB();
-               $masterType = $mainLB->getServerType( $mainLB->getWriterIndex() );
-               if ( $masterType === 'mysql' ) {
+       public static function setSchemaAliases( LBFactory $lbFactory, Config $config ) {
+               if ( $config->get( 'DBtype' ) === 'mysql' ) {
                        /**
                         * When SQLite indexes were introduced in r45764, it was noted that
                         * SQLite requires index names to be unique within the whole database,
index 52e996a..3c86d11 100644 (file)
@@ -96,13 +96,12 @@ class LinksDeletionUpdate extends DataUpdate implements EnqueueableDataUpdate {
                        }
                }
 
-               // Refresh the category table entry if it seems to have no pages. Check
-               // master for the most up-to-date cat_pages count.
+               // Refresh counts on categories that should be empty now
                if ( $title->getNamespace() === NS_CATEGORY ) {
                        $row = $dbw->selectRow(
                                'category',
                                [ 'cat_id', 'cat_title', 'cat_pages', 'cat_subcats', 'cat_files' ],
-                               [ 'cat_title' => $title->getDBkey(), 'cat_pages <= 0' ],
+                               [ 'cat_title' => $title->getDBkey(), 'cat_pages <= 100' ],
                                __METHOD__
                        );
                        if ( $row ) {
index 9239c6c..454b633 100644 (file)
@@ -112,7 +112,7 @@ class FileBackendGroup {
        /**
         * Register an array of file backend configurations
         *
-        * @param array $configs
+        * @param array[] $configs
         * @param string|null $readOnlyReason
         * @throws InvalidArgumentException
         */
index 4269f91..3dc9f18 100644 (file)
@@ -124,9 +124,9 @@ class DBFileJournal extends FileJournal {
 
        /**
         * @see FileJournal::doGetChangeEntries()
-        * @param int $start
+        * @param int|null $start
         * @param int $limit
-        * @return array
+        * @return array[]
         */
        protected function doGetChangeEntries( $start, $limit ) {
                $dbw = $this->getMasterDB();
index 21b7ac2..dbb5421 100644 (file)
@@ -92,9 +92,9 @@ class FileBackendDBRepoWrapper extends FileBackend {
         * E.g. mwstore://local-backend/local-public/a/ab/<name>.jpg
         * => mwstore://local-backend/local-original/x/y/z/<sha1>.jpg
         *
-        * @param array $paths
+        * @param string[] $paths
         * @param bool $latest
-        * @return array Translated paths in same order
+        * @return string[] Translated paths in same order
         */
        public function getBackendPaths( array $paths, $latest = true ) {
                $db = $this->getDB( $latest ? DB_MASTER : DB_REPLICA );
@@ -341,8 +341,8 @@ class FileBackendDBRepoWrapper extends FileBackend {
         *
         * This leaves destination paths alone since we don't want those to mutate
         *
-        * @param array $ops
-        * @return array
+        * @param array[] $ops
+        * @return array[]
         */
        protected function mungeOpPaths( array $ops ) {
                // Ops that use 'src' and do not mutate core file data there
index e430bc8..28021ef 100644 (file)
@@ -78,10 +78,6 @@ class FileRepo {
         */
        protected $scriptDirUrl;
 
-       /** @var string Script extension of the MediaWiki installation, equivalent
-        *    to the old $wgScriptExtension, e.g. .php5 defaults to .php */
-       protected $scriptExtension;
-
        /** @var string Equivalent to $wgArticlePath, e.g. https://en.wikipedia.org/wiki/$1 */
        protected $articleUrl;
 
@@ -166,7 +162,7 @@ class FileRepo {
                $optionalSettings = [
                        'descBaseUrl', 'scriptDirUrl', 'articleUrl', 'fetchDescription',
                        'thumbScriptUrl', 'pathDisclosureProtection', 'descriptionCacheExpiry',
-                       'scriptExtension', 'favicon', 'thumbProxyUrl', 'thumbProxySecret'
+                       'favicon', 'thumbProxyUrl', 'thumbProxySecret',
                ];
                foreach ( $optionalSettings as $var ) {
                        if ( isset( $info[$var] ) ) {
@@ -582,8 +578,8 @@ class FileRepo {
         * Get an array of arrays or iterators of file objects for files that
         * have the given SHA-1 content hashes.
         *
-        * @param array $hashes An array of hashes
-        * @return array An Array of arrays or iterators of file objects and the hash as key
+        * @param string[] $hashes An array of hashes
+        * @return array[] An Array of arrays or iterators of file objects and the hash as key
         */
        public function findBySha1s( array $hashes ) {
                $result = [];
@@ -603,7 +599,7 @@ class FileRepo {
         * STUB
         * @param string $prefix The prefix to search for
         * @param int $limit The maximum amount of files to return
-        * @return array
+        * @return LocalFile[]
         */
        public function findFilesByPrefix( $prefix, $limit ) {
                return [];
@@ -744,9 +740,7 @@ class FileRepo {
         */
        public function makeUrl( $query = '', $entry = 'index' ) {
                if ( isset( $this->scriptDirUrl ) ) {
-                       $ext = isset( $this->scriptExtension ) ? $this->scriptExtension : '.php';
-
-                       return wfAppendQuery( "{$this->scriptDirUrl}/{$entry}{$ext}", $query );
+                       return wfAppendQuery( "{$this->scriptDirUrl}/{$entry}.php", $query );
                }
 
                return false;
@@ -795,7 +789,7 @@ class FileRepo {
         * should use File::getDescriptionText().
         *
         * @param string $name Name of image to fetch
-        * @param string $lang Language to fetch it in, if any.
+        * @param string|null $lang Language to fetch it in, if any.
         * @return string|false
         */
        public function getDescriptionRenderUrl( $name, $lang = null ) {
@@ -934,7 +928,7 @@ class FileRepo {
         * Each file can be a (zone, rel) pair, virtual url, storage path.
         * It will try to delete each file, but ignores any errors that may occur.
         *
-        * @param array $files List of files to delete
+        * @param string[] $files List of files to delete
         * @param int $flags Bitwise combination of the following flags:
         *   self::SKIP_LOCKING      Skip any file locking when doing the deletions
         * @return Status
@@ -1384,7 +1378,7 @@ class FileRepo {
        /**
         * Checks existence of an array of files.
         *
-        * @param array $files Virtual URLs (or storage paths) of files to check
+        * @param string[] $files Virtual URLs (or storage paths) of files to check
         * @return array Map of files and existence flags, or false
         */
        public function fileExistsBatch( array $files ) {
@@ -1490,7 +1484,7 @@ class FileRepo {
         * Delete files in the deleted directory if they are not referenced in the filearchive table
         *
         * STUB
-        * @param array $storageKeys
+        * @param string[] $storageKeys
         */
        public function cleanupDeletedBatch( array $storageKeys ) {
                $this->assertWritableRepo();
@@ -1706,7 +1700,7 @@ class FileRepo {
        /**
         * Get a callback function to use for cleaning error message parameters
         *
-        * @return array
+        * @return string[]
         */
        function getErrorCleanupFunction() {
                switch ( $this->pathDisclosureProtection ) {
@@ -1895,7 +1889,7 @@ class FileRepo {
        /**
         * Get an UploadStash associated with this repo.
         *
-        * @param User $user
+        * @param User|null $user
         * @return UploadStash
         */
        public function getUploadStash( User $user = null ) {
@@ -1928,7 +1922,7 @@ class FileRepo {
 
                $optionalSettings = [
                        'url', 'thumbUrl', 'initialCapital', 'descBaseUrl', 'scriptDirUrl', 'articleUrl',
-                       'fetchDescription', 'descriptionCacheExpiry', 'scriptExtension', 'favicon'
+                       'fetchDescription', 'descriptionCacheExpiry', 'favicon'
                ];
                foreach ( $optionalSettings as $k ) {
                        if ( isset( $this->$k ) ) {
index 1a86648..06b21a8 100644 (file)
@@ -120,7 +120,7 @@ class ForeignAPIRepo extends FileRepo {
        }
 
        /**
-        * @param array $files
+        * @param string[] $files
         * @return array
         */
        function fileExistsBatch( array $files ) {
@@ -176,7 +176,7 @@ class ForeignAPIRepo extends FileRepo {
 
        /**
         * @param string $virtualUrl
-        * @return bool
+        * @return false
         */
        function getFileProps( $virtualUrl ) {
                return false;
@@ -231,7 +231,7 @@ class ForeignAPIRepo extends FileRepo {
 
        /**
         * @param string $hash
-        * @return array
+        * @return ForeignAPIFile[]
         */
        function findBySha1( $hash ) {
                $results = $this->fetchImageQuery( [
@@ -257,10 +257,10 @@ class ForeignAPIRepo extends FileRepo {
         * @param string $name
         * @param int $width
         * @param int $height
-        * @param array &$result
+        * @param array|null &$result Output-only parameter, guaranteed to become an array
         * @param string $otherParams
         *
-        * @return bool
+        * @return string|false
         */
        function getThumbUrl( $name, $width = -1, $height = -1, &$result = null, $otherParams = '' ) {
                $data = $this->fetchImageQuery( [
@@ -287,7 +287,7 @@ class ForeignAPIRepo extends FileRepo {
         * @param int $width
         * @param int $height
         * @param string $otherParams
-        * @param string $lang Language code for language of error
+        * @param string|null $lang Language code for language of error
         * @return bool|MediaTransformError
         * @since 1.22
         */
index 1bf5346..76043d5 100644 (file)
@@ -91,7 +91,7 @@ class LocalRepo extends FileRepo {
         * interleave database locks with file operations, which is potentially a
         * remote operation.
         *
-        * @param array $storageKeys
+        * @param string[] $storageKeys
         *
         * @return Status
         */
@@ -371,7 +371,7 @@ class LocalRepo extends FileRepo {
         * SHA-1 content hash.
         *
         * @param string $hash A sha1 hash to look for
-        * @return File[]
+        * @return LocalFile[]
         */
        function findBySha1( $hash ) {
                $dbr = $this->getReplicaDB();
@@ -400,8 +400,8 @@ class LocalRepo extends FileRepo {
         *
         * Overrides generic implementation in FileRepo for performance reason
         *
-        * @param array $hashes An array of hashes
-        * @return array An Array of arrays or iterators of file objects and the hash as key
+        * @param string[] $hashes An array of hashes
+        * @return array[] An Array of arrays or iterators of file objects and the hash as key
         */
        function findBySha1s( array $hashes ) {
                if ( !count( $hashes ) ) {
@@ -434,7 +434,7 @@ class LocalRepo extends FileRepo {
         *
         * @param string $prefix The prefix to search for
         * @param int $limit The maximum amount of files to return
-        * @return array
+        * @return LocalFile[]
         */
        public function findFilesByPrefix( $prefix, $limit ) {
                $selectOptions = [ 'ORDER BY' => 'img_name', 'LIMIT' => intval( $limit ) ];
index 24d1ab2..b797790 100644 (file)
@@ -423,7 +423,7 @@ class RepoGroup {
         * Split a virtual URL into repo, zone and rel parts
         * @param string $url
         * @throws MWException
-        * @return array Containing repo, zone and rel
+        * @return string[] Containing repo, zone and rel
         */
        function splitVirtualUrl( $url ) {
                if ( substr( $url, 0, 9 ) != 'mwrepo://' ) {
index 982fea4..d9763c6 100644 (file)
@@ -214,7 +214,7 @@ class ArchivedFile {
        /**
         * Fields in the filearchive table
         * @deprecated since 1.31, use self::getQueryInfo() instead.
-        * @return array
+        * @return string[]
         */
        static function selectFields() {
                global $wgActorTableSchemaMigrationStage;
@@ -258,7 +258,7 @@ class ArchivedFile {
         * Return the tables, fields, and join conditions to be selected to create
         * a new archivedfile object.
         * @since 1.31
-        * @return array With three keys:
+        * @return array[] With three keys:
         *   - tables: (string[]) to include in the `$table` to `IDatabase->select()`
         *   - fields: (string[]) to include in the `$vars` to `IDatabase->select()`
         *   - joins: (array) to include in the `$join_conds` to `IDatabase->select()`
index d4605d3..cfd1cf2 100644 (file)
@@ -268,7 +268,7 @@ abstract class File implements IDBAccessObject {
         * a two-part name, set the minor type to 'unknown'.
         *
         * @param string $mime "text/html" etc
-        * @return array ("text", "html") etc
+        * @return string[] ("text", "html") etc
         */
        public static function splitMime( $mime ) {
                if ( strpos( $mime, '/' ) !== false ) {
@@ -569,7 +569,7 @@ abstract class File implements IDBAccessObject {
         * format does not support that sort of thing, returns
         * an empty array.
         *
-        * @return array
+        * @return string[]
         * @since 1.23
         */
        public function getAvailableLanguages() {
@@ -1423,7 +1423,7 @@ abstract class File implements IDBAccessObject {
         * Get all thumbnail names previously generated for this file
         * STUB
         * Overridden by LocalFile
-        * @return array
+        * @return string[]
         */
        function getThumbnails() {
                return [];
@@ -1474,9 +1474,9 @@ abstract class File implements IDBAccessObject {
         * Return a fragment of the history of file.
         *
         * STUB
-        * @param int $limit Limit of rows to return
-        * @param string $start Only revisions older than $start will be returned
-        * @param string $end Only revisions newer than $end will be returned
+        * @param int|null $limit Limit of rows to return
+        * @param string|int|null $start Only revisions older than $start will be returned
+        * @param string|int|null $end Only revisions newer than $end will be returned
         * @param bool $inc Include the endpoints of the time range
         *
         * @return File[]
@@ -2099,9 +2099,9 @@ abstract class File implements IDBAccessObject {
         *   File::FOR_PUBLIC       to be displayed to all users
         *   File::FOR_THIS_USER    to be displayed to the given user
         *   File::RAW              get the description regardless of permissions
-        * @param User $user User object to check for, only if FOR_THIS_USER is
+        * @param User|null $user User object to check for, only if FOR_THIS_USER is
         *   passed to the $audience parameter
-        * @return string
+        * @return null|string
         */
        function getDescription( $audience = self::FOR_PUBLIC, User $user = null ) {
                return null;
@@ -2161,7 +2161,7 @@ abstract class File implements IDBAccessObject {
         * field of this file, if it's marked as deleted.
         * STUB
         * @param int $field
-        * @param User $user User object to check, or null to use $wgUser
+        * @param User|null $user User object to check, or null to use $wgUser
         * @return bool
         */
        function userCan( $field, User $user = null ) {
@@ -2177,7 +2177,7 @@ abstract class File implements IDBAccessObject {
        }
 
        /**
-        * @return array HTTP header name/value map to use for HEAD/GET request responses
+        * @return string[] HTTP header name/value map to use for HEAD/GET request responses
         * @since 1.30
         */
        function getContentHeaders() {
index 2a40942..be88b49 100644 (file)
@@ -192,8 +192,8 @@ class ForeignAPIFile extends File {
        }
 
        /**
-        * @param array $metadata
-        * @return array
+        * @param mixed $metadata
+        * @return mixed
         */
        public static function parseMetadata( $metadata ) {
                if ( !is_array( $metadata ) ) {
@@ -254,7 +254,7 @@ class ForeignAPIFile extends File {
 
        /**
         * @param int $audience
-        * @param User $user
+        * @param User|null $user
         * @return null|string
         */
        public function getDescription( $audience = self::FOR_PUBLIC, User $user = null ) {
@@ -333,7 +333,7 @@ class ForeignAPIFile extends File {
        }
 
        /**
-        * @return array
+        * @return string[]
         */
        function getThumbnails() {
                $dir = $this->getThumbPath( $this->getName() );
index cf21161..388e950 100644 (file)
@@ -74,7 +74,7 @@ class ForeignDBFile extends LocalFile {
         * @param string $source
         * @param bool $watch
         * @param bool|string $timestamp
-        * @param User $user User object or null to use $wgUser
+        * @param User|null $user User object or null to use $wgUser
         * @return bool
         * @throws MWException
         */
index 0464f07..cff1044 100644 (file)
@@ -141,7 +141,7 @@ class LocalFile extends File {
         * @param FileRepo $repo
         * @param null $unused
         *
-        * @return LocalFile
+        * @return self
         */
        static function newFromTitle( $title, $repo, $unused = null ) {
                return new self( $title, $repo );
@@ -154,7 +154,7 @@ class LocalFile extends File {
         * @param stdClass $row
         * @param FileRepo $repo
         *
-        * @return LocalFile
+        * @return self
         */
        static function newFromRow( $row, $repo ) {
                $title = Title::makeTitle( NS_FILE, $row->img_name );
@@ -195,7 +195,7 @@ class LocalFile extends File {
        /**
         * Fields in the image table
         * @deprecated since 1.31, use self::getQueryInfo() instead.
-        * @return array
+        * @return string[]
         */
        static function selectFields() {
                global $wgActorTableSchemaMigrationStage;
@@ -235,7 +235,7 @@ class LocalFile extends File {
         * @since 1.31
         * @param string[] $options
         *   - omit-lazy: Omit fields that are lazily cached.
-        * @return array With three keys:
+        * @return array[] With three keys:
         *   - tables: (string[]) to include in the `$table` to `IDatabase->select()`
         *   - fields: (string[]) to include in the `$vars` to `IDatabase->select()`
         *   - joins: (array) to include in the `$join_conds` to `IDatabase->select()`
@@ -405,7 +405,7 @@ class LocalFile extends File {
        /**
         * Returns the list of object properties that are included as-is in the cache.
         * @param string $prefix Must be the empty string
-        * @return array
+        * @return string[]
         * @since 1.31 No longer accepts a non-empty $prefix
         */
        protected function getCacheFields( $prefix = 'img_' ) {
@@ -427,7 +427,7 @@ class LocalFile extends File {
         * Returns the list of object properties that are included as-is in the
         * cache, only when they're not too big, and are lazily loaded by self::loadExtraFromDB().
         * @param string $prefix Must be the empty string
-        * @return array
+        * @return string[]
         * @since 1.31 No longer accepts a non-empty $prefix
         */
        protected function getLazyCacheFields( $prefix = 'img_' ) {
@@ -500,7 +500,7 @@ class LocalFile extends File {
        /**
         * @param IDatabase $dbr
         * @param string $fname
-        * @return array|bool
+        * @return string[]|bool
         */
        private function loadExtraFieldsWithTimestamp( $dbr, $fname ) {
                $fieldMap = false;
@@ -1160,9 +1160,9 @@ class LocalFile extends File {
        /** purgeEverything inherited */
 
        /**
-        * @param int $limit Optional: Limit to number of results
-        * @param int $start Optional: Timestamp, start from
-        * @param int $end Optional: Timestamp, end at
+        * @param int|null $limit Optional: Limit to number of results
+        * @param string|int|null $start Optional: Timestamp, start from
+        * @param string|int|null $end Optional: Timestamp, end at
         * @param bool $inc
         * @return OldLocalFile[]
         */
@@ -2105,8 +2105,8 @@ class LocalFile extends File {
         * This is not used by ImagePage for local files, since (among other things)
         * it skips the parser cache.
         *
-        * @param Language $lang What language to get description in (Optional)
-        * @return bool|mixed
+        * @param Language|null $lang What language to get description in (Optional)
+        * @return string|false
         */
        function getDescriptionText( $lang = null ) {
                $revision = Revision::newFromTitle( $this->title, false, Revision::READ_NORMAL );
@@ -2124,7 +2124,7 @@ class LocalFile extends File {
 
        /**
         * @param int $audience
-        * @param User $user
+        * @param User|null $user
         * @return string
         */
        function getDescription( $audience = self::FOR_PUBLIC, User $user = null ) {
@@ -2369,7 +2369,7 @@ class LocalFileDeleteBatch {
 
        /**
         * Add the old versions of the image to the batch
-        * @return array List of archive names from old versions
+        * @return string[] List of archive names from old versions
         */
        public function addOlds() {
                $archiveNames = [];
@@ -2762,10 +2762,10 @@ class LocalFileRestoreBatch {
        /** @var LocalFile */
        private $file;
 
-       /** @var array List of file IDs to restore */
+       /** @var string[] List of file IDs to restore */
        private $cleanupBatch;
 
-       /** @var array List of file IDs to restore */
+       /** @var string[] List of file IDs to restore */
        private $ids;
 
        /** @var bool Add all revisions of the file */
@@ -2780,7 +2780,7 @@ class LocalFileRestoreBatch {
         */
        function __construct( File $file, $unsuppress = false ) {
                $this->file = $file;
-               $this->cleanupBatch = $this->ids = [];
+               $this->cleanupBatch = [];
                $this->ids = [];
                $this->unsuppress = $unsuppress;
        }
@@ -3097,8 +3097,8 @@ class LocalFileRestoreBatch {
 
        /**
         * Removes non-existent files from a cleanup batch.
-        * @param array $batch
-        * @return array
+        * @param string[] $batch
+        * @return string[]
         */
        protected function removeNonexistentFromCleanup( $batch ) {
                $files = $newBatch = [];
@@ -3142,7 +3142,7 @@ class LocalFileRestoreBatch {
         * rollback by removing all items that were succesfully copied.
         *
         * @param Status $storeStatus
-        * @param array $storeBatch
+        * @param array[] $storeBatch
         */
        protected function cleanupFailedBatch( $storeStatus, $storeBatch ) {
                $cleanupBatch = [];
@@ -3208,7 +3208,7 @@ class LocalFileMoveBatch {
 
        /**
         * Add the old versions of the image to the batch
-        * @return array List of archive names from old versions
+        * @return string[] List of archive names from old versions
         */
        public function addOlds() {
                $archiveBase = 'archive';
@@ -3409,7 +3409,7 @@ class LocalFileMoveBatch {
 
        /**
         * Generate triplets for FileRepo::storeBatch().
-        * @return array
+        * @return array[]
         */
        protected function getMoveTriplets() {
                $moves = array_merge( [ $this->cur ], $this->olds );
@@ -3461,7 +3461,7 @@ class LocalFileMoveBatch {
        /**
         * Cleanup a partially moved array of triplets by deleting the target
         * files. Called if something went wrong half way.
-        * @param array $triplets
+        * @param array[] $triplets
         */
        protected function cleanupTarget( $triplets ) {
                // Create dest pairs from the triplets
@@ -3477,7 +3477,7 @@ class LocalFileMoveBatch {
        /**
         * Cleanup a fully moved array of triplets by deleting the source files.
         * Called at the end of the move process if everything else went ok.
-        * @param array $triplets
+        * @param array[] $triplets
         */
        protected function cleanupSource( $triplets ) {
                // Create source file names from the triplets
index 65f0fb1..3a6b879 100644 (file)
@@ -27,7 +27,7 @@
  * @ingroup FileAbstraction
  */
 class OldLocalFile extends LocalFile {
-       /** @var string Timestamp */
+       /** @var string|int Timestamp */
        protected $requestedTime;
 
        /** @var string Archive name */
@@ -39,8 +39,8 @@ class OldLocalFile extends LocalFile {
        /**
         * @param Title $title
         * @param FileRepo $repo
-        * @param null|int $time Timestamp or null
-        * @return OldLocalFile
+        * @param string|int $time
+        * @return self
         * @throws MWException
         */
        static function newFromTitle( $title, $repo, $time = null ) {
@@ -56,7 +56,7 @@ class OldLocalFile extends LocalFile {
         * @param Title $title
         * @param FileRepo $repo
         * @param string $archiveName
-        * @return OldLocalFile
+        * @return self
         */
        static function newFromArchiveName( $title, $repo, $archiveName ) {
                return new self( $title, $repo, null, $archiveName );
@@ -65,7 +65,7 @@ class OldLocalFile extends LocalFile {
        /**
         * @param stdClass $row
         * @param FileRepo $repo
-        * @return OldLocalFile
+        * @return self
         */
        static function newFromRow( $row, $repo ) {
                $title = Title::makeTitle( NS_FILE, $row->oi_name );
@@ -107,7 +107,7 @@ class OldLocalFile extends LocalFile {
        /**
         * Fields in the oldimage table
         * @deprecated since 1.31, use self::getQueryInfo() instead.
-        * @return array
+        * @return string[]
         */
        static function selectFields() {
                global $wgActorTableSchemaMigrationStage;
@@ -149,7 +149,7 @@ class OldLocalFile extends LocalFile {
         * @since 1.31
         * @param string[] $options
         *   - omit-lazy: Omit fields that are lazily cached.
-        * @return array With three keys:
+        * @return array[] With three keys:
         *   - tables: (string[]) to include in the `$table` to `IDatabase->select()`
         *   - fields: (string[]) to include in the `$vars` to `IDatabase->select()`
         *   - joins: (array) to include in the `$join_conds` to `IDatabase->select()`
@@ -191,8 +191,8 @@ class OldLocalFile extends LocalFile {
        /**
         * @param Title $title
         * @param FileRepo $repo
-        * @param string $time Timestamp or null to load by archive name
-        * @param string $archiveName Archive name or null to load by timestamp
+        * @param string|int|null $time Timestamp or null to load by archive name
+        * @param string|null $archiveName Archive name or null to load by timestamp
         * @throws MWException
         */
        function __construct( $title, $repo, $time, $archiveName ) {
index cf382e4..ebac200 100644 (file)
@@ -74,20 +74,21 @@ class ImportStreamSource implements ImportSource {
                }
                if ( !empty( $upload['error'] ) ) {
                        switch ( $upload['error'] ) {
-                               case 1:
-                                       # The uploaded file exceeds the upload_max_filesize directive in php.ini.
+                               case UPLOAD_ERR_INI_SIZE:
+                                       // The uploaded file exceeds the upload_max_filesize directive in php.ini.
                                        return Status::newFatal( 'importuploaderrorsize' );
-                               case 2:
-                                       # The uploaded file exceeds the MAX_FILE_SIZE directive that
-                                       # was specified in the HTML form.
+                               case UPLOAD_ERR_FORM_SIZE:
+                                       // The uploaded file exceeds the MAX_FILE_SIZE directive that
+                                       // was specified in the HTML form.
+                                       // FIXME This is probably never used since that directive was removed in 8e91c520?
                                        return Status::newFatal( 'importuploaderrorsize' );
-                               case 3:
-                                       # The uploaded file was only partially uploaded
+                               case UPLOAD_ERR_PARTIAL:
+                                       // The uploaded file was only partially uploaded
                                        return Status::newFatal( 'importuploaderrorpartial' );
-                               case 6:
-                                       # Missing a temporary folder.
+                               case UPLOAD_ERR_NO_TMP_DIR:
+                                       // Missing a temporary folder.
                                        return Status::newFatal( 'importuploaderrortemp' );
-                               # case else: # Currently impossible
+                               // Other error codes get the generic 'importnofile' error message below
                        }
 
                }
index 495b3d6..b64114c 100644 (file)
@@ -50,7 +50,7 @@ class ImportableUploadRevisionImporter implements UploadRevisionImporter {
                        $file->load( File::READ_LATEST );
                        $this->logger->debug( __METHOD__ . 'Importing new file as ' . $file->getName() . "\n" );
                        if ( $file->exists() && $file->getTimestamp() > $importableRevision->getTimestamp() ) {
-                               $archiveName = $file->getTimestamp() . '!' . $file->getName();
+                               $archiveName = $importableRevision->getTimestamp() . '!' . $file->getName();
                                $file = OldLocalFile::newFromArchiveName( $importableRevision->getTitle(),
                                        RepoGroup::singleton()->getLocalRepo(), $archiveName );
                                $this->logger->debug( __METHOD__ . "File already exists; importing as $archiveName\n" );
index 04132ad..ecd3081 100644 (file)
@@ -136,7 +136,7 @@ abstract class DatabaseUpdater {
                        $wgExtPGAlteredFields, $wgExtNewIndexes, $wgExtModifiedFields;
 
                # For extensions only, should be populated via hooks
-               # $wgDBtype should be checked to specifiy the proper file
+               # $wgDBtype should be checked to specify the proper file
                $wgExtNewTables = []; // table, dir
                $wgExtNewFields = []; // table, column, dir
                $wgExtPGNewFields = []; // table, column, column attributes; for PostgreSQL
index 2027c97..d798ea1 100644 (file)
@@ -175,7 +175,10 @@ class WebInstallerOptions extends WebInstallerPage {
                                        if ( isset( $info['url'] ) ) {
                                                $urlText = ' ' . Html::element( 'a', [ 'href' => $info['url'] ], '(more information)' );
                                        }
-                                       $attribs = [ 'data-name' => $ext ];
+                                       $attribs = [
+                                               'data-name' => $ext,
+                                               'class' => 'config-ext-input'
+                                       ];
                                        $labelAttribs = [];
                                        $fullDepList = [];
                                        if ( isset( $info['requires']['extensions'] ) ) {
index 4c4504e..19e1ea0 100644 (file)
        "config-nofile": "Файл «$1» ня знойдзены. Ці быў ён выдалены?",
        "config-extension-link": "Ці ведаеце вы, што вашая вікі падтрымлівае [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Extensions пашырэньні]?\n\nВы можаце праглядзець [https://www.mediawiki.org/wiki/Special:MyLanguage/Category:Extensions_by_category пашырэньні паводле катэгорыяў] або [https://www.mediawiki.org/wiki/Extension_Matrix матрыцу пашырэньняў], каб пабачыць поўны сьпіс.",
        "config-skins-screenshots": "$1 (здымкі экрану: $2)",
+       "config-extensions-requires": "$1 (патрабуе $2)",
        "config-screenshot": "здымак экрану",
        "mainpagetext": "<strong>MediaWiki была ўсталяваная.</strong>",
        "mainpagedocfooter": "Глядзіце [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Contents дапаможнік карыстальніка] для атрыманьня інфармацыі па карыстаньні вікі-праграмамі.\n\n== З чаго пачаць ==\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings Сьпіс парамэтраў канфігурацыі]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ Частыя пытаньні MediaWiki]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce Рассылка паведамленьняў пра зьяўленьне новых вэрсіяў MediaWiki]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation#Translation_resources Пераклад MediaWiki на вашую мову]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Combating_spam Даведайцеся, як змагацца з спамам у вашай вікі]"
index 00005d3..b20e1ed 100644 (file)
        "config-nofile": "Die Datei „$1“ konnte nicht gefunden werden. Wurde sie gelöscht?",
        "config-extension-link": "Wusstest du, dass dein Wiki die Nutzung von [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Extensions Erweiterungen] unterstützt?\n\nDu kannst die [https://www.mediawiki.org/wiki/Special:MyLanguage/Category:Extensions_by_category Erweiterungen nach Kategorie] anzeigen oder die [https://www.mediawiki.org/wiki/Extension_Matrix Erweiterungs-Matrix] aufrufen, um eine vollständige Liste der Erweiterungen zu sehen.",
        "config-skins-screenshots": "$1 (Bildschirmfotos: $2)",
+       "config-extensions-requires": "$1 (erfordert $2)",
        "config-screenshot": "Bildschirmfoto",
        "mainpagetext": "<strong>MediaWiki wurde installiert.</strong>",
        "mainpagedocfooter": "Hilfe zur Benutzung und Konfiguration der Wiki-Software findest du im [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Contents Benutzerhandbuch].\n\n== Starthilfen ==\n\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings Liste der Konfigurationsvariablen]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ MediaWiki-FAQ]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce Mailingliste neuer MediaWiki-Versionen]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation#Translation_resources Übersetze MediaWiki für deine Sprache]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Combating_spam Erfahre, wie du Spam auf deinem Wiki bekämpfen kannst]"
index 39c84ce..2350970 100644 (file)
        "config-nofile": "Το αρχείο «$1» δεν μπορεί να βρεθεί. Μήπως έχει διαγραφεί;",
        "config-extension-link": "Γνωρίζατε ότι το wiki σας υποστηρίζει [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Extensions επεκτάσεις];\n\nΜπορείτε να περιηγηθείτε στις [https://www.mediawiki.org/wiki/Special:MyLanguage/Category:Extensions_by_category επεκτάσεις ανά κατηγορία] ή στον [https://www.mediawiki.org/wiki/Extension_Matrix πίνακα επεκτάσεων] για να δείτε την πλήρη λίστα των επεκτάσεων.",
        "config-skins-screenshots": "$1 (στιγμιότυπα: $2)",
+       "config-extensions-requires": "$1 (απαιτεί το $2)",
        "config-screenshot": "στιγμιότυπο",
        "mainpagetext": "<strong>To MediaWiki εγκαταστάθηκε.</strong>",
        "mainpagedocfooter": "Συμβουλευτείτε τον [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Contents οδηγό χρήστη] για πληροφορίες σχετικά με το λογισμικό wiki.\n\n== Ξεκινώντας ==\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings Λίστα ρυθμίσεων διαμόρφωσης]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ\n Συχνές ερωτήσεις για το MediaWiki]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce Λίστα αλληλογραφίας νέων κυκλοφοριών του MediaWiki]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation#Translation_resources Μεταφράστε το MediaWiki στη γλώσσα σας]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Combating_spam Μάθετε πώς να καταπολεμήσετε το ανεπιθύμητο περιεχόμενο στο wiki σας]"
index 2d9b94f..3d801cc 100644 (file)
        "config-nofile": "Le fichier « $1 » est introuvable. A-t-il été supprimé ?",
        "config-extension-link": "Saviez-vous que votre wiki prend en charge [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Extensions des extensions] ?\n\nVous pouvez consulter les [https://www.mediawiki.org/wiki/Special:MyLanguage/Category:Extensions_by_category extensions par catégorie] ou la [https://www.mediawiki.org/wiki/Extension_Matrix matrice des extensions] pour voir la liste complète des extensions.",
        "config-skins-screenshots": "$1 (captures d’écran : $2)",
+       "config-extensions-requires": "$1 (nécessite $2)",
        "config-screenshot": "Captures d’écrans",
        "mainpagetext": "<strong>MediaWiki a été installé.</strong>",
        "mainpagedocfooter": "Consultez le [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Contents Guide de l’utilisateur] pour plus d’informations sur l’utilisation de ce logiciel de wiki.\n\n== Pour démarrer ==\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings Liste des paramètres de configuration]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ/fr Questions courantes sur MediaWiki]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce Liste de discussion sur les distributions de MediaWiki]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation#Translation_resources Adaptez MediaWiki dans votre langue]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Combating_spam Apprendre comment lutter contre le pourriel dans votre wiki]"
index d388a59..72a4d7d 100644 (file)
        "config-nofile": "הקובץ \"$1\" לא נמצא. האם הוא נמחק?",
        "config-extension-link": "הידעת שמדיה־ויקי תומכת ב־[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Extensions הרחבות]?\n\nבאפשרותך לעיין ב־[https://www.mediawiki.org/wiki/Special:MyLanguage/Category:Extensions_by_category הרחבות לפי קטגוריה].",
        "config-skins-screenshots": "$1 (צילומי מסך: $2)",
+       "config-extensions-requires": "$1 (נדרשת ההרחבה $2)",
        "config-screenshot": "צילום מסך",
        "mainpagetext": "<strong>תוכנת מדיה־ויקי הותקנה בהצלחה.</strong>",
        "mainpagedocfooter": "היעזרו ב[https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Contents מדריך למשתמש] למידע על שימוש בתוכנת הוויקי.\n\n== קישורים שימושיים ==\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings רשימת ההגדרות]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ שאלות ותשובות על מדיה־ויקי]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce רשימת התפוצה על השקת גרסאות]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation#Translation_resources תרגום מדיה־ויקי לשפה שלך]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Combating_spam איך להיאבק נגד ספאם באתר הוויקי שלך]"
index e9314ed..3e646bf 100644 (file)
        "config-nofile": "\"$1\" 파일을 찾을 수 없습니다. 이미 삭제되었나요?",
        "config-extension-link": "당신의 위키가 [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Extensions 확장 기능]을 지원한다는 것을 알고 계십니까?\n\n[https://www.mediawiki.org/wiki/Special:MyLanguage/Category:Extensions_by_category 분류별 확장 기능]을 찾아보실 수 있습니다.",
        "config-skins-screenshots": "$1 (스크린샷: $2)",
+       "config-extensions-requires": "$1 ($2 필요)",
        "config-screenshot": "스크린샷",
        "mainpagetext": "<strong>미디어위키가 설치되었습니다.</strong>",
        "mainpagedocfooter": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Contents 이곳]에서 위키 소프트웨어에 대한 정보를 얻을 수 있습니다.\n\n== 시작하기 ==\n\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings 설정하기 목록]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ 미디어위키 FAQ]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce 미디어위키 릴리스 메일링 리스트]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation#Translation_resources 내 언어로 미디어위키 지역화]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Combating_spam 당신의 위키에서 스팸에 대처하는 법을 배우세요]"
index afd7569..a1b55a8 100644 (file)
@@ -1,9 +1,49 @@
 {
        "@metadata": {
                "authors": [
-                       "Seb35"
+                       "Seb35",
+                       "Ooswesthoesbes"
                ]
        },
-       "mainpagetext": "'''MediaWiki software succesvol geïnsjtalleerd.'''",
-       "mainpagedocfooter": "Raodpleeg de [https://meta.wikimedia.org/wiki/Help:Contents Inhoudsopgave handjleiding] veur informatie euver 't gebroek van de wikisoftware.\n\n== Mieë hölp ==\n\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings Lies mit instellinge]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ MediaWiki VGV (FAQ)]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce MediaWiki mailinglies veur nuuj versies]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation#Translation_resources Localise MediaWiki for your language]"
+       "config-desc": "'t Installeringsprogram veur MediaWiki",
+       "config-title": "MediaWiki-installering $1",
+       "config-information": "Gegaeves",
+       "config-localsettings-key": "Opwardeersleutel:",
+       "config-localsettings-badkey": "De opwardeersleutel dae se höbs opgegaove is ónjuus.",
+       "config-upgrade-key-missing": "'n Bestäönde installaasje van MediaWiki is aangetroffe.\nPlaats de volgende regel óngeraan dien <code>LocalSettings.php</code> veur dees installaasje bie te wirke:\n\n$1",
+       "config-localsettings-incomplete": "De bestäönde inhawd van <code>LocalSettings.php</code> liekent incompleet.\nDe variabele $1 is neet ingestèld.\nVeranger <code>LocalSettings.php</code> zodet dees variabele is ingestèld en klik op \"{{int:Config-continue}}\".",
+       "config-localsettings-connection-error": "'n Fout is opgetraoje tiejes 't verbinje mitte databank mit de instèllinge oet <code>LocalSettings.php</code>. Los 't perbleem op mit de instèllinge en perbeer 't daonao oppernuuj.\n\n$1",
+       "config-session-error": "Fout bie begin vanne sessie: $1",
+       "config-your-language": "Dien spraok:",
+       "config-your-language-help": "Sillekteer de spraok die se wils broeke tiejes 't installaasjepercès.",
+       "config-wiki-language": "Wikispraok:",
+       "config-wiki-language-help": "Sillekteer de spraok wo de wiki veurnamelik in weurt gesjreve.",
+       "config-back": "← Trök",
+       "config-continue": "Gank door →",
+       "config-page-language": "Spraok",
+       "config-page-welcome": "Wilkóm bie MediaWiki!",
+       "config-page-dbconnect": "Maak verbinjing mit database",
+       "config-page-upgrade": "Wirk bestäönde installaasje bie",
+       "config-page-dbsettings": "Databankinstèllinge",
+       "config-page-name": "Naam",
+       "config-page-options": "Opties",
+       "config-page-install": "Installeer",
+       "config-page-complete": "Vaerdig!",
+       "config-page-restart": "Begin installering oppernuuj",
+       "config-page-readme": "Laes mich",
+       "config-page-releasenotes": "Gaef ópmèrkinge vrie",
+       "config-page-copying": "Kopieer",
+       "config-page-upgradedoc": "Wirk bie",
+       "config-page-existingwiki": "Bestäönde wiki",
+       "config-restart": "Jao, begin oppernuuj",
+       "config-env-php": "PHP $1 is geïnstalleerd.",
+       "config-env-hhvm": "HHVM $1 is geïnstalleerd.",
+       "config-diff3-bad": "GNU diff3 neet gevónje.",
+       "config-db-type": "Databanksaort:",
+       "config-db-host": "Databankgashieër:",
+       "config-db-host-oracle": "Databank-TNS:",
+       "config-db-wiki-settings": "Identificeer deze wiki",
+       "config-db-name": "Databanknaam:",
+       "mainpagetext": "<strong>MediaWiki software geïnsjtalleerd.</strong>",
+       "mainpagedocfooter": "Raodpleeg de [https://meta.wikimedia.org/wiki/Help:Contents Inhoudsopgave handjleiding] veur informatie euver 't gebroek van de wikisoftware.\n\n== Mieë hölp ==\n\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings Lies mit instellinge]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ MediaWiki VGV (FAQ)]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce MediaWiki mailinglies veur nuuj versies]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation#Translation_resources Maak MediaWiki besjikbaar in dien spraok]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Combating_spam Lieër wie se spam kans verkómme op diene wiki]"
 }
index a9ae2fe..4598aa9 100644 (file)
        "config-nofile": "Податотеката „$1“ не е пронајдена. Да не е избришана?",
        "config-extension-link": "Дали сте знаеле дека вашето вики поддржува [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Extensions додатоци]?\n\nМожете да ги прелистате [https://www.mediawiki.org/wiki/Special:MyLanguage/Category:Extensions_by_category по категории]",
        "config-skins-screenshots": "$1 (екр. снимки: $2)",
+       "config-extensions-requires": "$1 (бара $2)",
        "config-screenshot": "екранска снимка",
        "mainpagetext": "<strong>МедијаВики е успешно воспоставен.</strong>",
        "mainpagedocfooter": "Погледнете го [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Contents Упатството за корисници] за подетални информации како се користи вики-програмот.\n\n==Од каде да почнете==\n* [https://meta.wikimedia.org/wiki/Manual:Configuration_settings Список на нагодувања]\n* [https://meta.wikimedia.org/wiki/Manual:FAQ ЧПП (често поставувани прашања) за МедијаВики].\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce Поштенски список на МедијаВики за нови верзии]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation#Translation_resources Локализирајте го МедијаВики на вашиот јазик]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Combating_spam Дознајте како да се борите против спам на вашето вики]"
index 21410c8..11f0255 100644 (file)
        "config-profile-help": "As wikis funcionam melhor quando se deixa tantas pessoas editá-las quanto possível.\nNo MediaWiki, é fácil rever as alterações recentes e reverter quaisquer estragos causados por utilizadores novatos ou maliciosos.\n\nNo entanto, muitas pessoas consideram o MediaWiki útil de variadas formas e nem sempre é fácil convencer todas as pessoas dos benefícios desta filosofia wiki.\nPor isso pode optar.\n\nUma '''{{int:config-profile-wiki}}''' permite que todos a editem, sem sequer necessitar de autenticação.\nUma wiki com '''{{int:config-profile-no-anon}}''' atribui mais responsabilidade, mas pode afastar os colaboradores ocasionais.\n\nUm cenário '''{{int:config-profile-fishbowl}}''' permite que os utilizadores aprovados editem, mas que o público visione as páginas, incluindo o historial das mesmas.\nUma '''{{int:config-profile-private}}''' só permite que os utilizadores aprovados visionem as páginas e as editem.\n\nApós a instalação, estarão disponíveis mais configurações de privilégios. Consulte [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:User_rights a entrada relevante no Manual].",
        "config-license": "Direitos de autor e licença:",
        "config-license-none": "Sem rodapé com a licença",
-       "config-license-cc-by-sa": "Creative Commons - Atribuição - Partilha nos Mesmos Termos",
+       "config-license-cc-by-sa": "Creative Commons - Atribuição-CompartilhaIgual",
        "config-license-cc-by": "Creative Commons - Atribuição",
-       "config-license-cc-by-nc-sa": "Creative Commons - Atribuição - Uso Não Comercial - Partilha nos Mesmos Termos",
+       "config-license-cc-by-nc-sa": "Creative Commons - Atribuição-NãoComercial-CompartilhaIgual",
        "config-license-cc-0": "Creative Commons Zero (Domínio Público)",
        "config-license-gfdl": "GNU Free Documentation License 1.3 ou posterior",
        "config-license-pd": "Domínio Público",
        "config-nofile": "Não foi possível encontrar o ficheiro \"$1\". Terá sido apagado?",
        "config-extension-link": "Sabia que a sua wiki suporta [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Extensions extensões]?\n\nPode consultar as [https://www.mediawiki.org/wiki/Special:MyLanguage/Category:Extensions_by_category extensões por categoria] ou a [https://www.mediawiki.org/wiki/Extension_Matrix Matriz de Extensões] para ver a lista completa de extensões.",
        "config-skins-screenshots": "$1 (capturas de ecrã: $2)",
+       "config-extensions-requires": "$1 (requer $2)",
        "config-screenshot": "captura de ecrã",
        "mainpagetext": "<strong>O MediaWiki foi instalado.</strong>",
        "mainpagedocfooter": "Consulte a [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Contents Ajuda do MediaWiki] para informações sobre o uso do software wiki.\n\n== Onde começar ==\n\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings Lista de opções de configuração]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ Perguntas e respostas frequentes sobre o MediaWiki]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce Subscreva a lista de divulgação de novas versões do MediaWiki]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation#Translation_resources Regionalize o MediaWiki para a sua língua]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Combating_spam Aprenda a combater <i>spam</i> na sua wiki]"
index 751b42a..fb546ab 100644 (file)
        "config-extension-link": "Shown on last page of installation to inform about possible extensions.\n{{Identical|Did you know}}",
        "config-skins-screenshots": "Radio button text, $1 is the skin name, and $2 is a list of links to screenshots of that skin",
        "config-skins-screenshot": "Radio button text, $1 is the skin name, and $2 is a link to a screenshot of that skin, where the link text is {{msg-mw|config-screenshot}}.",
-       "config-extensions-requires": "Radio button text, $1 is the extension name, and $2 are links to other extensions that this one requires.",
+       "config-extensions-requires": "Radio button text, $1 is the extension name, and $2 are links to other extensions that this one requires.\n{{Identical|Require}}",
        "config-screenshot": "Link text for the link in {{msg-mw|config-skins-screenshot}}\n{{Identical|Screenshot}}",
        "mainpagetext": "Along with {{msg-mw|mainpagedocfooter}}, the text you will see on the Main Page when your wiki is installed.",
        "mainpagedocfooter": "Along with {{msg-mw|mainpagetext}}, the text you will see on the Main Page when your wiki is installed.\nThis might be a good place to put information about <nowiki>{{GRAMMAR:}}</nowiki>. See [[{{NAMESPACE}}:{{BASEPAGENAME}}/fi]] for an example. For languages having grammatical distinctions and not having an appropriate <nowiki>{{GRAMMAR:}}</nowiki> software available, a suggestion to check and possibly amend the messages having <nowiki>{{SITENAME}}</nowiki> may be valuable. See [[{{NAMESPACE}}:{{BASEPAGENAME}}/ksh]] for an example."
index 0ca73d3..ba2822c 100644 (file)
        "config-nofile": "Filen \"$1\" kunde inte hittas. Har den raderats?",
        "config-extension-link": "Visste du att din wiki stödjer [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Extensions tillägg]?\n\nDu kan bläddra [https://www.mediawiki.org/wiki/Special:MyLanguage/Category:Extensions_by_category tillägg efter kategori].",
        "config-skins-screenshots": "$1 (skärmbilder: $2)",
+       "config-extensions-requires": "$1 (kräver $2)",
        "config-screenshot": "skärmbild",
        "mainpagetext": "<strong>MediaWiki har installerats utan problem.</strong>",
        "mainpagedocfooter": "Information om hur wiki-programvaran används finns i [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Contents användarguiden].\n\n== Att komma igång ==\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings Lista över konfigurationsinställningar]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ MediaWiki FAQ]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce E-postlista för nya versioner av MediaWiki]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation#Translation_resources Lokalisera MediaWiki för ditt språk]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Combating_spam Läs om hur du bekämpar spam på din wiki]"
index 5c5aff5..fe32b22 100644 (file)
@@ -70,6 +70,7 @@
        "config-download-localsettings": "אראפלאדן <code>LocalSettings.php</code>",
        "config-help": "הילף",
        "config-nofile": "מ'האט נישט געקענט טרעפן די טעקע \"$1\". צי האט מען זי אויסגעמעקט?",
+       "config-extensions-requires": "$1 (פֿאדערט $2)",
        "mainpagetext": "<strong> מעדיעוויקי אינסטאלירט.</strong>",
        "mainpagedocfooter": "גיט זיך אן עצה מיט [https://meta.wikimedia.org/wiki/Help:Contents באניצער'ס וועגווײַזער] פֿאר אינפֿארמאציע וויאזוי זיך באנוצן מיט וויקי ווייכוואַרג.\n\n== נוצליכע וועבלינקען פֿאַר אנהייבערס ==\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings רשימה פון קאנפֿיגוראציעס]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ אפֿט געפֿרעגטע שאלות]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce מעדיעוויקי באפֿרײַאונג פאסטליסטע]* [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation#Translation_resources איבערזעצן מעדיעוויקי אין אײַער שפראך]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Combating_spam לערנט וויאזוי צו באקעמפן בפעם אויף אייער וויקי]"
 }
index 635fc34..f3a4321 100644 (file)
        "config-nofile": "找不到文件“$1”。它是否已被删除?",
        "config-extension-link": "您是否知道您的wiki支持[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Extensions 扩展]?\n\n您可以浏览[https://www.mediawiki.org/wiki/Special:MyLanguage/Category:Extensions_by_category 扩展分类]或[https://www.mediawiki.org/wiki/Extension_Matrix 扩展矩阵]以查看完整的扩展列表。",
        "config-skins-screenshots": "$1(截图:$2)",
+       "config-extensions-requires": "$1(需要$2)",
        "config-screenshot": "截图",
        "mainpagetext": "<strong>已安装MediaWiki。</strong>",
        "mainpagedocfooter": "请查阅[https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Contents 用户指导]以获取使用本wiki软件的信息!\n\n== 入门 ==\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings MediaWiki配置设置列表]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ/zh-hans MediaWiki常见问题]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce MediaWiki发布邮件列表]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation#Translation_resources 本地化MediaWiki到您的语言]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Combating_spam 了解如何在您的wiki上打击破坏]"
index acc8302..93c042e 100644 (file)
        "config-nofile": "查無檔案 \"$1\",是否已被刪除?",
        "config-extension-link": "您是否了解您的 Wiki 支援 [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Extensions 擴充套件]?\n\n\n您可以瀏覽 [https://www.mediawiki.org/wiki/Special:MyLanguage/Category:Extensions_by_category 擴充套件分類] 或 [https://www.mediawiki.org/wiki/Extension_Matrix 擴充套件資料表] 以取得相關的資訊。",
        "config-skins-screenshots": "$1 (螢幕截圖: $2)",
+       "config-extensions-requires": "$1(需要 $2)",
        "config-screenshot": "螢幕截圖",
        "mainpagetext": "<strong>已安裝 MediaWiki。</strong>",
        "mainpagedocfooter": "有關使用wiki的訊息,請參閱[https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Contents 使用者指南]。\n\n== 新手入門 ==\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings 系統設定]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ MediaWiki常見問題]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce MediaWiki郵寄清單]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation#Translation_resources 將MediaWiki翻譯至您的語言]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Combating_spam 了解如何在您的wiki上防禦破壞]"
index 73825e8..a6014b1 100644 (file)
@@ -420,7 +420,7 @@ class CSSMin {
                        //   is only supported in PHP 5.6. Use a getter method for now.
                        $urlRegex = '(' .
                                // Unquoted url
-                               'url\(\s*(?P<file0>[^\'"][^\?\)]+?)(?P<query0>\?[^\)]*?|)\s*\)' .
+                               'url\(\s*(?P<file0>[^\s\'"][^\?\)]+?)(?P<query0>\?[^\)]*?|)\s*\)' .
                                // Single quoted url
                                '|url\(\s*\'(?P<file1>[^\?\']+?)(?P<query1>\?[^\']*?|)\'\s*\)' .
                                // Double quoted url
index 474c564..f7702dd 100644 (file)
@@ -259,43 +259,40 @@ class CryptRand {
                        }
                }
 
-               if ( strlen( $buffer ) < $bytes ) {
+               if ( strlen( $buffer ) < $bytes && function_exists( 'mcrypt_create_iv' ) ) {
                        // If available make use of mcrypt_create_iv URANDOM source to generate randomness
                        // On unix-like systems this reads from /dev/urandom but does it without any buffering
                        // and bypasses openbasedir restrictions, so it's preferable to reading directly
                        // On Windows starting in PHP 5.3.0 Windows' native CryptGenRandom is used to generate
                        // entropy so this is also preferable to just trying to read urandom because it may work
                        // on Windows systems as well.
-                       if ( function_exists( 'mcrypt_create_iv' ) ) {
-                               $rem = $bytes - strlen( $buffer );
-                               $iv = mcrypt_create_iv( $rem, MCRYPT_DEV_URANDOM );
-                               if ( $iv === false ) {
-                                       $this->logger->debug( "mcrypt_create_iv returned false." );
-                               } else {
-                                       $buffer .= $iv;
-                                       $this->logger->debug( "mcrypt_create_iv generated " . strlen( $iv ) .
-                                               " bytes of randomness." );
-                               }
+                       $rem = $bytes - strlen( $buffer );
+                       $iv = mcrypt_create_iv( $rem, MCRYPT_DEV_URANDOM );
+                       if ( $iv === false ) {
+                               $this->logger->debug( "mcrypt_create_iv returned false." );
+                       } else {
+                               $buffer .= $iv;
+                               $this->logger->debug( "mcrypt_create_iv generated " . strlen( $iv ) .
+                                       " bytes of randomness." );
                        }
                }
 
-               if ( strlen( $buffer ) < $bytes ) {
-                       if ( function_exists( 'openssl_random_pseudo_bytes' ) ) {
-                               $rem = $bytes - strlen( $buffer );
-                               $openssl_bytes = openssl_random_pseudo_bytes( $rem, $openssl_strong );
-                               if ( $openssl_bytes === false ) {
-                                       $this->logger->debug( "openssl_random_pseudo_bytes returned false." );
-                               } else {
-                                       $buffer .= $openssl_bytes;
-                                       $this->logger->debug( "openssl_random_pseudo_bytes generated " .
-                                               strlen( $openssl_bytes ) . " bytes of " .
-                                               ( $openssl_strong ? "strong" : "weak" ) . " randomness." );
-                               }
-                               if ( strlen( $buffer ) >= $bytes ) {
-                                       // openssl tells us if the random source was strong, if some of our data was generated
-                                       // using it use it's say on whether the randomness is strong
-                                       $this->strong = !!$openssl_strong;
-                               }
+               if ( strlen( $buffer ) < $bytes && function_exists( 'openssl_random_pseudo_bytes' ) ) {
+                       $rem = $bytes - strlen( $buffer );
+                       $openssl_strong = false;
+                       $openssl_bytes = openssl_random_pseudo_bytes( $rem, $openssl_strong );
+                       if ( $openssl_bytes === false ) {
+                               $this->logger->debug( "openssl_random_pseudo_bytes returned false." );
+                       } else {
+                               $buffer .= $openssl_bytes;
+                               $this->logger->debug( "openssl_random_pseudo_bytes generated " .
+                                       strlen( $openssl_bytes ) . " bytes of " .
+                                       ( $openssl_strong ? "strong" : "weak" ) . " randomness." );
+                       }
+                       if ( strlen( $buffer ) >= $bytes ) {
+                               // openssl tells us if the random source was strong, if some of our data was generated
+                               // using it use it's say on whether the randomness is strong
+                               $this->strong = !!$openssl_strong;
                        }
                }
 
index 31ff3dc..5549f28 100644 (file)
@@ -109,11 +109,11 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
        /** @var bool */
        protected $opened = false;
 
-       /** @var array[] List of (callable, method name) */
+       /** @var array[] List of (callable, method name, atomic section id) */
        protected $trxIdleCallbacks = [];
-       /** @var array[] List of (callable, method name) */
+       /** @var array[] List of (callable, method name, atomic section id) */
        protected $trxPreCommitCallbacks = [];
-       /** @var array[] List of (callable, method name) */
+       /** @var array[] List of (callable, method name, atomic section id) */
        protected $trxEndCallbacks = [];
        /** @var callable[] Map of (name => callable) */
        protected $trxRecurringCallbacks = [];
@@ -274,6 +274,11 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
        /** @var int */
        protected $nonNativeInsertSelectBatchSize = 10000;
 
+       /** @var string Idiom used when a cancelable atomic section started the transaction */
+       private static $NOT_APPLICABLE = 'n/a';
+       /** @var string Prefix to the atomic section counter used to make savepoint IDs */
+       private static $SAVEPOINT_PREFIX = 'wikimedia_rdbms_atomic';
+
        /** @var int Transaction is in a error state requiring a full or savepoint rollback */
        const STATUS_TRX_ERROR = 1;
        /** @var int Transaction is active and in a normal state */
@@ -3288,7 +3293,7 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
                if ( !$this->trxLevel ) {
                        throw new DBUnexpectedError( $this, "No transaction is active." );
                }
-               $this->trxEndCallbacks[] = [ $callback, $fname ];
+               $this->trxEndCallbacks[] = [ $callback, $fname, $this->currentAtomicSectionId() ];
        }
 
        final public function onTransactionIdle( callable $callback, $fname = __METHOD__ ) {
@@ -3298,7 +3303,7 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
                        $this->trxAutomatic = true;
                }
 
-               $this->trxIdleCallbacks[] = [ $callback, $fname ];
+               $this->trxIdleCallbacks[] = [ $callback, $fname, $this->currentAtomicSectionId() ];
                if ( !$this->trxLevel ) {
                        $this->runOnTransactionIdleCallbacks( self::TRIGGER_IDLE );
                }
@@ -3312,7 +3317,7 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
                }
 
                if ( $this->trxLevel ) {
-                       $this->trxPreCommitCallbacks[] = [ $callback, $fname ];
+                       $this->trxPreCommitCallbacks[] = [ $callback, $fname, $this->currentAtomicSectionId() ];
                } else {
                        // No transaction is active nor will start implicitly, so make one for this callback
                        $this->startAtomic( __METHOD__, self::ATOMIC_CANCELABLE );
@@ -3326,6 +3331,72 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
                }
        }
 
+       /**
+        * @return AtomicSectionIdentifier|null ID of the topmost atomic section level
+        */
+       private function currentAtomicSectionId() {
+               if ( $this->trxLevel && $this->trxAtomicLevels ) {
+                       $levelInfo = end( $this->trxAtomicLevels );
+
+                       return $levelInfo[1];
+               }
+
+               return null;
+       }
+
+       /**
+        * @param AtomicSectionIdentifier $old
+        * @param AtomicSectionIdentifier $new
+        */
+       private function reassignCallbacksForSection(
+               AtomicSectionIdentifier $old, AtomicSectionIdentifier $new
+       ) {
+               foreach ( $this->trxPreCommitCallbacks as $key => $info ) {
+                       if ( $info[2] === $old ) {
+                               $this->trxPreCommitCallbacks[$key][2] = $new;
+                       }
+               }
+               foreach ( $this->trxIdleCallbacks as $key => $info ) {
+                       if ( $info[2] === $old ) {
+                               $this->trxIdleCallbacks[$key][2] = $new;
+                       }
+               }
+               foreach ( $this->trxEndCallbacks as $key => $info ) {
+                       if ( $info[2] === $old ) {
+                               $this->trxEndCallbacks[$key][2] = $new;
+                       }
+               }
+       }
+
+       /**
+        * @param AtomicSectionIdentifier[] $sectionIds ID of an actual savepoint
+        * @throws UnexpectedValueException
+        */
+       private function modifyCallbacksForCancel( array $sectionIds ) {
+               // Cancel the "on commit" callbacks owned by this savepoint
+               $this->trxIdleCallbacks = array_filter(
+                       $this->trxIdleCallbacks,
+                       function ( $entry ) use ( $sectionIds ) {
+                               return !in_array( $entry[2], $sectionIds, true );
+                       }
+               );
+               $this->trxPreCommitCallbacks = array_filter(
+                       $this->trxPreCommitCallbacks,
+                       function ( $entry ) use ( $sectionIds ) {
+                               return !in_array( $entry[2], $sectionIds, true );
+                       }
+               );
+               // Make "on resolution" callbacks owned by this savepoint to perceive a rollback
+               foreach ( $this->trxEndCallbacks as $key => $entry ) {
+                       if ( in_array( $entry[2], $sectionIds, true ) ) {
+                               $callback = $entry[0];
+                               $this->trxEndCallbacks[$key][0] = function () use ( $callback ) {
+                                       return $callback( self::TRIGGER_ROLLBACK );
+                               };
+                       }
+               }
+       }
+
        final public function setTransactionListener( $name, callable $callback = null ) {
                if ( $callback ) {
                        $this->trxRecurringCallbacks[$name] = $callback;
@@ -3499,28 +3570,44 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
                $this->query( 'ROLLBACK TO SAVEPOINT ' . $this->addIdentifierQuotes( $identifier ), $fname );
        }
 
+       /**
+        * @param string $fname
+        * @return string
+        */
+       private function nextSavepointId( $fname ) {
+               $savepointId = self::$SAVEPOINT_PREFIX . ++$this->trxAtomicCounter;
+               if ( strlen( $savepointId ) > 30 ) {
+                       // 30 == Oracle's identifier length limit (pre 12c)
+                       // With a 22 character prefix, that puts the highest number at 99999999.
+                       throw new DBUnexpectedError(
+                               $this,
+                               'There have been an excessively large number of atomic sections in a transaction'
+                               . " started by $this->trxFname (at $fname)"
+                       );
+               }
+
+               return $savepointId;
+       }
+
        final public function startAtomic(
                $fname = __METHOD__, $cancelable = self::ATOMIC_NOT_CANCELABLE
        ) {
-               $savepointId = $cancelable === self::ATOMIC_CANCELABLE ? 'n/a' : null;
+               $savepointId = $cancelable === self::ATOMIC_CANCELABLE ? self::$NOT_APPLICABLE : null;
+
                if ( !$this->trxLevel ) {
                        $this->begin( $fname, self::TRANSACTION_INTERNAL );
                        // If DBO_TRX is set, a series of startAtomic/endAtomic pairs will result
                        // in all changes being in one transaction to keep requests transactional.
-                       if ( !$this->getFlag( self::DBO_TRX ) ) {
+                       if ( $this->getFlag( self::DBO_TRX ) ) {
+                               // Since writes could happen in between the topmost atomic sections as part
+                               // of the transaction, those sections will need savepoints.
+                               $savepointId = $this->nextSavepointId( $fname );
+                               $this->doSavepoint( $savepointId, $fname );
+                       } else {
                                $this->trxAutomaticAtomic = true;
                        }
                } elseif ( $cancelable === self::ATOMIC_CANCELABLE ) {
-                       $savepointId = 'wikimedia_rdbms_atomic' . ++$this->trxAtomicCounter;
-                       if ( strlen( $savepointId ) > 30 ) { // 30 == Oracle's identifier length limit (pre 12c)
-                               $this->queryLogger->warning(
-                                       'There have been an excessively large number of atomic sections in a transaction'
-                                       . " started by $this->trxFname, reusing IDs (at $fname)",
-                                       [ 'trace' => ( new RuntimeException() )->getTraceAsString() ]
-                               );
-                               $this->trxAtomicCounter = 0;
-                               $savepointId = 'wikimedia_rdbms_atomic' . ++$this->trxAtomicCounter;
-                       }
+                       $savepointId = $this->nextSavepointId( $fname );
                        $this->doSavepoint( $savepointId, $fname );
                }
 
@@ -3537,7 +3624,7 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
 
                // Check if the current section matches $fname
                $pos = count( $this->trxAtomicLevels ) - 1;
-               list( $savedFname, , $savepointId ) = $this->trxAtomicLevels[$pos];
+               list( $savedFname, $sectionId, $savepointId ) = $this->trxAtomicLevels[$pos];
 
                if ( $savedFname !== $fname ) {
                        throw new DBUnexpectedError(
@@ -3546,14 +3633,21 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
                        );
                }
 
-               // Remove the last section and re-index the array
-               $this->trxAtomicLevels = array_slice( $this->trxAtomicLevels, 0, $pos );
+               // Remove the last section (no need to re-index the array)
+               array_pop( $this->trxAtomicLevels );
 
                if ( !$this->trxAtomicLevels && $this->trxAutomaticAtomic ) {
                        $this->commit( $fname, self::FLUSHING_INTERNAL );
-               } elseif ( $savepointId !== null && $savepointId !== 'n/a' ) {
+               } elseif ( $savepointId !== null && $savepointId !== self::$NOT_APPLICABLE ) {
                        $this->doReleaseSavepoint( $savepointId, $fname );
                }
+
+               // Hoist callback ownership for callbacks in the section that just ended;
+               // all callbacks should have an owner that is present in trxAtomicLevels.
+               $currentSectionId = $this->currentAtomicSectionId();
+               if ( $currentSectionId ) {
+                       $this->reassignCallbacksForSection( $sectionId, $currentSectionId );
+               }
        }
 
        final public function cancelAtomic(
@@ -3575,12 +3669,18 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
                                throw new DBUnexpectedError( "Atomic section not found (for $fname)" );
                        }
                        // Remove all descendant sections and re-index the array
+                       $excisedIds = [];
+                       $len = count( $this->trxAtomicLevels );
+                       for ( $i = $pos + 1; $i < $len; ++$i ) {
+                               $excisedIds[] = $this->trxAtomicLevels[$i][1];
+                       }
                        $this->trxAtomicLevels = array_slice( $this->trxAtomicLevels, 0, $pos + 1 );
+                       $this->modifyCallbacksForCancel( $excisedIds );
                }
 
                // Check if the current section matches $fname
                $pos = count( $this->trxAtomicLevels ) - 1;
-               list( $savedFname, , $savepointId ) = $this->trxAtomicLevels[$pos];
+               list( $savedFname, $savedSectionId, $savepointId ) = $this->trxAtomicLevels[$pos];
 
                if ( $savedFname !== $fname ) {
                        throw new DBUnexpectedError(
@@ -3589,12 +3689,13 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
                        );
                }
 
-               // Remove the last section and re-index the array
-               $this->trxAtomicLevels = array_slice( $this->trxAtomicLevels, 0, $pos );
+               // Remove the last section (no need to re-index the array)
+               array_pop( $this->trxAtomicLevels );
+               $this->modifyCallbacksForCancel( [ $savedSectionId ] );
 
                if ( $savepointId !== null ) {
                        // Rollback the transaction to the state just before this atomic section
-                       if ( $savepointId === 'n/a' ) {
+                       if ( $savepointId === self::$NOT_APPLICABLE ) {
                                $this->rollback( $fname, self::FLUSHING_INTERNAL );
                        } else {
                                $this->doRollbackToSavepoint( $savepointId, $fname );
index b50ff70..675ba7f 100644 (file)
@@ -1601,7 +1601,7 @@ interface IDatabase {
         * Example usage (atomic changes that might have to be discarded):
         * @code
         *     // Start a transaction if there isn't one already
-        *     $dbw->startAtomic( __METHOD__, $dbw::ATOMIC_CANCELABLE );
+        *     $sectionId = $dbw->startAtomic( __METHOD__, $dbw::ATOMIC_CANCELABLE );
         *     // Create new record metadata row
         *     $dbw->insert( 'records', $row, __METHOD__ );
         *     // Figure out where to store the data based on the new row's ID
@@ -1622,7 +1622,7 @@ interface IDatabase {
         *         $dbw->endAtomic( __METHOD__ );
         *     } else {
         *         // Discard these writes from the transaction (preserving prior writes)
-        *         $dbw->cancelAtomic( __METHOD__ );
+        *         $dbw->cancelAtomic( __METHOD__, $sectionId );
         *     }
         * @endcode
         *
@@ -1714,9 +1714,9 @@ interface IDatabase {
         *                     $this->blobStore->delete( $path );
         *                 }
         *             },
-        *         },
-        *         __METHOD__
-        *     );
+        *             __METHOD__
+        *          );
+        *     }, $dbw::ATOMIC_CANCELABLE );
         * @endcode
         *
         * Example usage, caller of the "RecordStore::save" method:
@@ -1726,7 +1726,6 @@ interface IDatabase {
         *     try {
         *         $recordStore->save( $record );
         *     } catch ( StoreFailureException $e ) {
-        *         $dbw->cancelAtomic( __METHOD__ );
         *         // ...various SQL writes happen...
         *     }
         *     // ...various SQL writes happen...
index 19b8fdc..c272147 100644 (file)
@@ -30,6 +30,7 @@ use EmptyBagOStuff;
 use WANObjectCache;
 use Exception;
 use RuntimeException;
+use LogicException;
 
 /**
  * An interface for generating database load balancers
@@ -527,7 +528,11 @@ abstract class LBFactory implements ILBFactory {
                        'hostname' => $this->hostname,
                        'cliMode' => $this->cliMode,
                        'agent' => $this->agent,
-                       'chronologyProtector' => $this->getChronologyProtector()
+                       'chronologyCallback' => function ( ILoadBalancer $lb ) {
+                               // Defer ChronologyProtector construction in case setRequestInfo() ends up
+                               // being called later (but before the first connection attempt) (T192611)
+                               $this->getChronologyProtector()->initLB( $lb );
+                       }
                ];
        }
 
@@ -585,6 +590,10 @@ abstract class LBFactory implements ILBFactory {
        }
 
        public function setRequestInfo( array $info ) {
+               if ( $this->chronProt ) {
+                       throw new LogicException( 'ChronologyProtector already initialized.' );
+               }
+
                $this->requestInfo = $info + $this->requestInfo;
        }
 
index 2f493c7..fec496e 100644 (file)
@@ -101,7 +101,7 @@ interface ILoadBalancer {
         *  - maxLag: Avoid replica DB servers with more lag than this [optional]
         *  - srvCache : BagOStuff object for server cache [optional]
         *  - wanCache : WANObjectCache object [optional]
-        *  - chronologyProtector: ChronologyProtector object [optional]
+        *  - chronologyCallback: Callback to run before the first connection attempt [optional]
         *  - hostname : The name of the current server [optional]
         *  - cliMode: Whether the execution context is a CLI script. [optional]
         *  - profiler : Class name or instance with profileIn()/profileOut() methods. [optional]
index 01589ae..51fdfe3 100644 (file)
@@ -59,8 +59,8 @@ class LoadBalancer implements ILoadBalancer {
 
        /** @var ILoadMonitor */
        private $loadMonitor;
-       /** @var ChronologyProtector|null */
-       private $chronProt;
+       /** @var callable|null Callback to run before the first connection attempt */
+       private $chronologyCallback;
        /** @var BagOStuff */
        private $srvCache;
        /** @var WANObjectCache */
@@ -116,8 +116,8 @@ class LoadBalancer implements ILoadBalancer {
 
        /** @var bool */
        private $disabled = false;
-       /** @var bool */
-       private $chronProtInitialized = false;
+       /** @var bool Whether any connection has been attempted yet */
+       private $connectionAttempted = false;
        /** @var int */
        private $maxLag = self::MAX_LAG_DEFAULT;
 
@@ -243,8 +243,8 @@ class LoadBalancer implements ILoadBalancer {
                        : ( PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg' );
                $this->agent = isset( $params['agent'] ) ? $params['agent'] : '';
 
-               if ( isset( $params['chronologyProtector'] ) ) {
-                       $this->chronProt = $params['chronologyProtector'];
+               if ( isset( $params['chronologyCallback'] ) ) {
+                       $this->chronologyCallback = $params['chronologyCallback'];
                }
        }
 
@@ -424,7 +424,7 @@ class LoadBalancer implements ILoadBalancer {
                        } else {
                                $i = false;
                                if ( $this->waitForPos && $this->waitForPos->asOfTime() ) {
-                                       // ChronologyProtecter sets "waitForPos" for session consistency.
+                                       // "chronologyCallback" sets "waitForPos" for session consistency.
                                        // This triggers doWait() after connect, so it's especially good to
                                        // avoid lagged servers so as to avoid excessive delay in that method.
                                        $ago = microtime( true ) - $this->waitForPos->asOfTime();
@@ -849,11 +849,11 @@ class LoadBalancer implements ILoadBalancer {
                        $domain = false; // local connection requested
                }
 
-               if ( !$this->chronProtInitialized && $this->chronProt ) {
+               if ( !$this->connectionAttempted && $this->chronologyCallback ) {
                        $this->connLogger->debug( __METHOD__ . ': calling initLB() before first connection.' );
-                       // Load CP positions before connecting so that doWait() triggers later if needed
-                       $this->chronProtInitialized = true;
-                       $this->chronProt->initLB( $this );
+                       // Load any "waitFor" positions before connecting so that doWait() is triggered
+                       $this->connectionAttempted = true;
+                       call_user_func( $this->chronologyCallback, $this );
                }
 
                // Check if an auto-commit connection is being requested. If so, it will not reuse the
index b88a34d..cda037c 100644 (file)
@@ -134,7 +134,8 @@ class BitmapHandler extends TransformationalImageHandler {
        protected function transformImageMagick( $image, $params ) {
                # use ImageMagick
                global $wgSharpenReductionThreshold, $wgSharpenParameter, $wgMaxAnimatedGifArea,
-                       $wgImageMagickTempDir, $wgImageMagickConvertCommand, $wgJpegPixelFormat;
+                       $wgImageMagickTempDir, $wgImageMagickConvertCommand, $wgJpegPixelFormat,
+                       $wgJpegQuality;
 
                $quality = [];
                $sharpen = [];
@@ -146,7 +147,7 @@ class BitmapHandler extends TransformationalImageHandler {
 
                if ( $params['mimeType'] == 'image/jpeg' ) {
                        $qualityVal = isset( $params['quality'] ) ? (string)$params['quality'] : null;
-                       $quality = [ '-quality', $qualityVal ?: '80' ]; // 80%
+                       $quality = [ '-quality', $qualityVal ?: (string)$wgJpegQuality ]; // 80% by default
                        if ( $params['interlace'] ) {
                                $animation_post = [ '-interlace', 'JPEG' ];
                        }
@@ -276,7 +277,7 @@ class BitmapHandler extends TransformationalImageHandler {
         */
        protected function transformImageMagickExt( $image, $params ) {
                global $wgSharpenReductionThreshold, $wgSharpenParameter, $wgMaxAnimatedGifArea,
-                       $wgJpegPixelFormat;
+                       $wgJpegPixelFormat, $wgJpegQuality;
 
                try {
                        $im = new Imagick();
@@ -293,7 +294,7 @@ class BitmapHandler extends TransformationalImageHandler {
                                        $im->sharpenImage( $radius, $sigma );
                                }
                                $qualityVal = isset( $params['quality'] ) ? (string)$params['quality'] : null;
-                               $im->setCompressionQuality( $qualityVal ?: 80 );
+                               $im->setCompressionQuality( $qualityVal ?: $wgJpegQuality );
                                if ( $params['interlace'] ) {
                                        $im->setInterlaceScheme( Imagick::INTERLACE_JPEG );
                                }
@@ -498,9 +499,19 @@ class BitmapHandler extends TransformationalImageHandler {
 
        /**
         * Callback for transformGd when transforming jpeg images.
+        *
+        * @param resource $dst_image Image resource of the original image
+        * @param string $thumbPath File path to write the thumbnail image to
+        * @param int|null $quality Quality of the thumbnail from 1-100,
+        *    or null to use default quality.
         */
-       // FIXME: transformImageMagick() & transformImageMagickExt() uses JPEG quality 80, here it's 95?
-       static function imageJpegWrapper( $dst_image, $thumbPath, $quality = 95 ) {
+       static function imageJpegWrapper( $dst_image, $thumbPath, $quality = null ) {
+               global $wgJpegQuality;
+
+               if ( $quality === null ) {
+                       $quality = $wgJpegQuality;
+               }
+
                imageinterlace( $dst_image );
                imagejpeg( $dst_image, $thumbPath, $quality );
        }
index 67d2346..a6f55e6 100644 (file)
@@ -337,9 +337,11 @@ class ObjectCache {
                $services = MediaWikiServices::getInstance();
 
                $erGroup = $services->getEventRelayerGroup();
-               foreach ( $params['channels'] as $action => $channel ) {
-                       $params['relayers'][$action] = $erGroup->getRelayer( $channel );
-                       $params['channels'][$action] = $channel;
+               if ( isset( $params['channels'] ) ) {
+                       foreach ( $params['channels'] as $action => $channel ) {
+                               $params['relayers'][$action] = $erGroup->getRelayer( $channel );
+                               $params['channels'][$action] = $channel;
+                       }
                }
                $params['cache'] = self::newFromParams( $params['store'] );
                if ( isset( $params['loggroup'] ) ) {
index 7577972..c865d4e 100644 (file)
@@ -577,7 +577,16 @@ class Article implements Page {
                                        # Preload timestamp to avoid a DB hit
                                        $outputPage->setRevisionTimestamp( $this->mPage->getTimestamp() );
 
-                                       if ( !Hooks::run( 'ArticleContentViewCustom',
+                                       # Pages containing custom CSS or JavaScript get special treatment
+                                       if ( $this->getTitle()->isSiteConfigPage() || $this->getTitle()->isUserConfigPage() ) {
+                                               $dir = $this->getContext()->getLanguage()->getDir();
+                                               $lang = $this->getContext()->getLanguage()->getHtmlCode();
+
+                                               $outputPage->wrapWikiMsg(
+                                                       "<div id='mw-clearyourcache' lang='$lang' dir='$dir' class='mw-content-$dir'>\n$1\n</div>",
+                                                       'clearyourcache'
+                                               );
+                                       } elseif ( !Hooks::run( 'ArticleContentViewCustom',
                                                [ $this->fetchContentObject(), $this->getTitle(), $outputPage ] )
                                        ) {
                                                # Allow extensions do their own custom view for certain pages
@@ -1056,8 +1065,7 @@ class Article implements Page {
                                                'rc_namespace' => NS_FILE,
                                                'rc_cur_id' => $title->getArticleID()
                                        ],
-                                       __METHOD__,
-                                       [ 'USE INDEX' => 'rc_timestamp' ]
+                                       __METHOD__
                                );
                                if ( $rc ) {
                                        // Use patrol message specific to files
index afe266b..cfeb331 100644 (file)
@@ -2117,7 +2117,12 @@ class WikiPage implements Page, IDBAccessObject {
                                        : DB_REPLICA; // T154554
 
                                $edit->popts->setSpeculativeRevIdCallback( function () use ( $dbIndex ) {
-                                       return 1 + (int)wfGetDB( $dbIndex )->selectField(
+                                       $lb = MediaWikiServices::getInstance()->getDBLoadBalancer();
+                                       // Use a fresh connection in order to see the latest data, by avoiding
+                                       // stale data from REPEATABLE-READ snapshots.
+                                       $db = $lb->getConnectionRef( $dbIndex, [], false, $lb::CONN_TRX_AUTO );
+
+                                       return 1 + (int)$db->selectField(
                                                'revision',
                                                'MAX(rev_id)',
                                                [],
@@ -3616,14 +3621,12 @@ class WikiPage implements Page, IDBAccessObject {
                        Hooks::run( 'CategoryAfterPageRemoved', [ $cat, $this, $id ] );
                }
 
-               // Refresh counts on categories that should be empty now, to
-               // trigger possible deletion. Check master for the most
-               // up-to-date cat_pages.
+               // Refresh counts on categories that should be empty now
                if ( count( $deleted ) ) {
                        $rows = $dbw->select(
                                'category',
                                [ 'cat_id', 'cat_title', 'cat_pages', 'cat_subcats', 'cat_files' ],
-                               [ 'cat_title' => $deleted, 'cat_pages <= 0' ],
+                               [ 'cat_title' => $deleted, 'cat_pages <= 100' ],
                                __METHOD__
                        );
                        foreach ( $rows as $row ) {
index 05bcebe..26d5bdd 100644 (file)
  * @ingroup Parser
  */
 class CacheTime {
-       /** @var array|bool ParserOptions which have been taken into account to
-        * produce output or false if not available.
+       /**
+        * @var string[] ParserOptions which have been taken into account to produce output.
         */
        public $mUsedOptions;
 
-       # Compatibility check
+       /**
+        * @var string|null Compatibility check
+        */
        public $mVersion = Parser::VERSION;
 
-       # Time when this object was generated, or -1 for uncacheable. Used in ParserCache.
+       /**
+        * @var string|int TS_MW timestamp when this object was generated, or -1 for uncacheable. Used
+        * in ParserCache.
+        */
        public $mCacheTime = '';
 
-       # Seconds after which the object should expire, use 0 for uncacheable. Used in ParserCache.
+       /**
+        * @var int|null Seconds after which the object should expire, use 0 for uncacheable. Used in
+        * ParserCache.
+        */
        public $mCacheExpiry = null;
 
-       # Revision ID that was parsed
+       /**
+        * @var int|null Revision ID that was parsed
+        */
        public $mCacheRevisionId = null;
 
        /**
@@ -71,7 +81,7 @@ class CacheTime {
 
        /**
         * @since 1.23
-        * @param int $id Revision id
+        * @param int|null $id Revision ID
         */
        public function setCacheRevisionId( $id ) {
                $this->mCacheRevisionId = $id;
@@ -105,7 +115,7 @@ class CacheTime {
         * The value returned by getCacheExpiry is smaller or equal to the smallest number
         * that was provided to a call of updateCacheExpiry(), and smaller or equal to the
         * value of $wgParserCacheExpireTime.
-        * @return int|mixed|null
+        * @return int
         */
        public function getCacheExpiry() {
                global $wgParserCacheExpireTime;
index 0a4a60e..2aefc03 100644 (file)
@@ -130,13 +130,10 @@ class DateFormatter {
         *     Defaults to the site content language
         * @return DateFormatter
         */
-       public static function getInstance( $lang = null ) {
+       public static function getInstance( Language $lang = null ) {
                global $wgContLang, $wgMainCacheType;
 
-               if ( is_string( $lang ) ) {
-                       wfDeprecated( __METHOD__ . ' with type string for $lang', '1.31' );
-               }
-               $lang = $lang ? wfGetLangObj( $lang ) : $wgContLang;
+               $lang = $lang ?: $wgContLang;
                $cache = ObjectCache::getLocalServerInstance( $wgMainCacheType );
 
                static $dateFormatter = false;
index 8a7fca6..e6326e6 100644 (file)
@@ -291,8 +291,8 @@ class ParserCache {
         * @param ParserOutput $parserOutput
         * @param WikiPage $page
         * @param ParserOptions $popts
-        * @param string $cacheTime Time when the cache was generated
-        * @param int $revId Revision ID that was parsed
+        * @param string|null $cacheTime TS_MW timestamp when the cache was generated
+        * @param int|null $revId Revision ID that was parsed
         */
        public function save( $parserOutput, $page, $popts, $cacheTime = null, $revId = null ) {
                $expire = $parserOutput->getCacheExpiry();
index ff21ef0..8fb9857 100644 (file)
@@ -1211,7 +1211,7 @@ class ParserOptions {
         * in 1.16.
         * Used to get the old parser cache entries when available.
         * @deprecated since 1.30. You probably want self::allCacheVaryingOptions() instead.
-        * @return array
+        * @return string[]
         */
        public static function legacyOptions() {
                wfDeprecated( __METHOD__, '1.30' );
@@ -1268,7 +1268,7 @@ class ParserOptions {
         * the same cached data safely.
         *
         * @since 1.17
-        * @param array $forOptions
+        * @param string[] $forOptions
         * @param Title $title Used to get the content language of the page (since r97636)
         * @return string Page rendering hash
         */
index 8f0a1d7..f3a83db 100644 (file)
@@ -177,7 +177,7 @@ class ParserOutput extends CacheTime {
        private $mIndexPolicy = '';
 
        /**
-        * @var array $mAccessedOptions List of ParserOptions (stored in the keys).
+        * @var true[] $mAccessedOptions List of ParserOptions (stored in the keys).
         */
        private $mAccessedOptions = [];
 
@@ -685,9 +685,8 @@ class ParserOutput extends CacheTime {
        /**
         * Register a file dependency for this output
         * @param string $name Title dbKey
-        * @param string $timestamp MW timestamp of file creation (or false if non-existing)
-        * @param string $sha1 Base 36 SHA-1 of file (or false if non-existing)
-        * @return void
+        * @param string|false|null $timestamp MW timestamp of file creation (or false if non-existing)
+        * @param string|false|null $sha1 Base 36 SHA-1 of file (or false if non-existing)
         */
        public function addImage( $name, $timestamp = null, $sha1 = null ) {
                $this->mImages[$name] = 1;
@@ -701,7 +700,6 @@ class ParserOutput extends CacheTime {
         * @param Title $title
         * @param int $page_id
         * @param int $rev_id
-        * @return void
         */
        public function addTemplate( $title, $page_id, $rev_id ) {
                $ns = $title->getNamespace();
@@ -968,8 +966,8 @@ class ParserOutput extends CacheTime {
 
        /**
         * Returns the options from its ParserOptions which have been taken
-        * into account to produce this output or false if not available.
-        * @return array
+        * into account to produce this output.
+        * @return string[]
         */
        public function getUsedOptions() {
                if ( !isset( $this->mAccessedOptions ) ) {
index 545fd3b..6c4a5d0 100644 (file)
@@ -148,15 +148,22 @@ class ResourceLoaderClientHtml {
                                continue;
                        }
 
-                       $context = $this->getContext( $module->getGroup(), ResourceLoaderModule::TYPE_COMBINED );
+                       $group = $module->getGroup();
+                       $context = $this->getContext( $group, ResourceLoaderModule::TYPE_COMBINED );
                        if ( $module->isKnownEmpty( $context ) ) {
                                // Avoid needless request or embed for empty module
                                $data['states'][$name] = 'ready';
                                continue;
                        }
 
-                       if ( $module->shouldEmbedModule( $this->context ) ) {
-                               // Embed via mw.loader.implement per T36907.
+                       if ( $group === 'user' || $module->shouldEmbedModule( $this->context ) ) {
+                               // Call makeLoad() to decide how to load these, instead of
+                               // loading via mw.loader.load().
+                               // - For group=user: We need to provide a pre-generated load.php
+                               //   url to the client that has the 'user' and 'version' parameters
+                               //   filled in. Without this, the client would wrongly use the static
+                               //   version hash, per T64602.
+                               // - For shouldEmbed=true:  Embed via mw.loader.implement, per T36907.
                                $data['embed']['general'][] = $name;
                                // Avoid duplicate request from mw.loader
                                $data['states'][$name] = 'loading';
index c0dd188..2e3c6fc 100644 (file)
@@ -88,7 +88,6 @@ class ResourceLoaderStartUpModule extends ResourceLoaderModule {
                        'wgUrlProtocols' => wfUrlProtocols(),
                        'wgArticlePath' => $conf->get( 'ArticlePath' ),
                        'wgScriptPath' => $conf->get( 'ScriptPath' ),
-                       'wgScriptExtension' => '.php',
                        'wgScript' => wfScript(),
                        'wgSearchType' => $conf->get( 'SearchType' ),
                        'wgVariantArticlePath' => $conf->get( 'VariantArticlePath' ),
index 5b512af..0926b60 100644 (file)
@@ -22,6 +22,7 @@
  * @author Roan Kattouw
  */
 
+use MediaWiki\Linker\LinkTarget;
 use Wikimedia\Rdbms\Database;
 use Wikimedia\Rdbms\IDatabase;
 
@@ -50,7 +51,19 @@ class ResourceLoaderWikiModule extends ResourceLoaderModule {
        // Origin defaults to users with sitewide authority
        protected $origin = self::ORIGIN_USER_SITEWIDE;
 
-       // In-process cache for title info
+       // In-process cache for title info, structured as an array
+       // [
+       //  <batchKey> // Pipe-separated list of sorted keys from getPages
+       //   => [
+       //     <titleKey> => [ // Normalised title key
+       //       'page_len' => ..,
+       //       'page_latest' => ..,
+       //       'page_touched' => ..,
+       //     ]
+       //   ]
+       // ]
+       // @see self::fetchTitleInfo()
+       // @see self::makeTitleKey()
        protected $titleInfo = [];
 
        // List of page names that contain CSS
@@ -295,8 +308,13 @@ class ResourceLoaderWikiModule extends ResourceLoaderModule {
                return count( $revisions ) === 0;
        }
 
-       private function setTitleInfo( $key, array $titleInfo ) {
-               $this->titleInfo[$key] = $titleInfo;
+       private function setTitleInfo( $batchKey, array $titleInfo ) {
+               $this->titleInfo[$batchKey] = $titleInfo;
+       }
+
+       private static function makeTitleKey( LinkTarget $title ) {
+               // Used for keys in titleInfo.
+               return "{$title->getNamespace()}:{$title->getDBkey()}";
        }
 
        /**
@@ -313,11 +331,11 @@ class ResourceLoaderWikiModule extends ResourceLoaderModule {
 
                $pageNames = array_keys( $this->getPages( $context ) );
                sort( $pageNames );
-               $key = implode( '|', $pageNames );
-               if ( !isset( $this->titleInfo[$key] ) ) {
-                       $this->titleInfo[$key] = static::fetchTitleInfo( $dbr, $pageNames, __METHOD__ );
+               $batchKey = implode( '|', $pageNames );
+               if ( !isset( $this->titleInfo[$batchKey] ) ) {
+                       $this->titleInfo[$batchKey] = static::fetchTitleInfo( $dbr, $pageNames, __METHOD__ );
                }
-               return $this->titleInfo[$key];
+               return $this->titleInfo[$batchKey];
        }
 
        protected static function fetchTitleInfo( IDatabase $db, array $pages, $fname = __METHOD__ ) {
@@ -340,8 +358,8 @@ class ResourceLoaderWikiModule extends ResourceLoaderModule {
                        foreach ( $res as $row ) {
                                // Avoid including ids or timestamps of revision/page tables so
                                // that versions are not wasted
-                               $title = Title::makeTitle( $row->page_namespace, $row->page_title );
-                               $titleInfo[$title->getPrefixedText()] = [
+                               $title = new TitleValue( (int)$row->page_namespace, $row->page_title );
+                               $titleInfo[ self::makeTitleKey( $title ) ] = [
                                        'page_len' => $row->page_len,
                                        'page_latest' => $row->page_latest,
                                        'page_touched' => $row->page_touched,
@@ -410,23 +428,23 @@ class ResourceLoaderWikiModule extends ResourceLoaderModule {
                        $pages = $wikiModule->getPages( $context );
                        // Before we intersect, map the names to canonical form (T145673).
                        $intersect = [];
-                       foreach ( $pages as $page => $unused ) {
-                               $title = Title::newFromText( $page );
+                       foreach ( $pages as $pageName => $unused ) {
+                               $title = Title::newFromText( $pageName );
                                if ( $title ) {
-                                       $intersect[ $title->getPrefixedText() ] = 1;
+                                       $intersect[ self::makeTitleKey( $title ) ] = 1;
                                } else {
                                        // Page name may be invalid if user-provided (e.g. gadgets)
                                        $rl->getLogger()->info(
                                                'Invalid wiki page title "{title}" in ' . __METHOD__,
-                                               [ 'title' => $page ]
+                                               [ 'title' => $pageName ]
                                        );
                                }
                        }
                        $info = array_intersect_key( $allInfo, $intersect );
                        $pageNames = array_keys( $pages );
                        sort( $pageNames );
-                       $key = implode( '|', $pageNames );
-                       $wikiModule->setTitleInfo( $key, $info );
+                       $batchKey = implode( '|', $pageNames );
+                       $wikiModule->setTitleInfo( $batchKey, $info );
                }
        }
 
diff --git a/includes/skins/MediaWikiI18N.php b/includes/skins/MediaWikiI18N.php
deleted file mode 100644 (file)
index 731897e..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-<?php
-/**
- * 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
- */
-
-/**
- * Wrapper object for MediaWiki's localization functions,
- * to be passed to the template engine.
- *
- * @private
- * @ingroup Skins
- */
-class MediaWikiI18N {
-       private $context = [];
-
-       /**
-        * @deprecate since 1.31 Use BaseTemplate::msg() or Skin::msg() instead for setting
-        *  message parameters.
-        */
-       function set( $varName, $value ) {
-               wfDeprecated( __METHOD__, '1.31' );
-               $this->context[$varName] = $value;
-       }
-
-       /**
-        * @deprecate since 1.31 Use BaseTemplate::msg(), Skin::msg(), or wfMessage() instead.
-        */
-       function translate( $value ) {
-               wfDeprecated( __METHOD__, '1.31' );
-               // Hack for i18n:attributes in PHPTAL 1.0.0 dev version as of 2004-10-23
-               $value = preg_replace( '/^string:/', '', $value );
-
-               $value = wfMessage( $value )->text();
-               // interpolate variables
-               $m = [];
-               while ( preg_match( '/\$([0-9]*?)/sm', $value, $m ) ) {
-                       list( $src, $var ) = $m;
-                       Wikimedia\suppressWarnings();
-                       $varValue = $this->context[$var];
-                       Wikimedia\restoreWarnings();
-                       $value = str_replace( $src, $varValue, $value );
-               }
-               return $value;
-       }
-}
index 1886746..aa20e20 100644 (file)
@@ -31,11 +31,6 @@ abstract class QuickTemplate {
         */
        public $data;
 
-       /**
-        * @var MediaWikiI18N
-        */
-       public $translator;
-
        /** @var Config $config */
        protected $config;
 
@@ -44,7 +39,6 @@ abstract class QuickTemplate {
         */
        function __construct( Config $config = null ) {
                $this->data = [];
-               $this->translator = new MediaWikiI18N();
                if ( $config === null ) {
                        wfDebug( __METHOD__ . ' was called with no Config instance passed to it' );
                        $config = MediaWikiServices::getInstance()->getMainConfig();
@@ -102,16 +96,6 @@ abstract class QuickTemplate {
                $this->data[$name] =& $value;
        }
 
-       /**
-        * @param MediaWikiI18N &$t
-        * @deprecate since 1.31 Use BaseTemplate::msg() or Skin::msg() instead for setting
-        *  message parameters.
-        */
-       public function setTranslator( &$t ) {
-               wfDeprecated( __METHOD__, '1.31' );
-               $this->translator = &$t;
-       }
-
        /**
         * Main function, used by classes that subclass QuickTemplate
         * to show the actual HTML output
index 6c913d2..778a3b3 100644 (file)
@@ -173,9 +173,9 @@ class SparqlClient {
                        throw new SparqlException( "HTTP error: {$status->getWikiText()}" );
                }
                $result = $request->getContent();
-               \MediaWiki\suppressWarnings();
+               \Wikimedia\suppressWarnings();
                $data = json_decode( $result, true );
-               \MediaWiki\restoreWarnings();
+               \Wikimedia\restoreWarnings();
                if ( $data === null || $data === false ) {
                        throw new SparqlException( "HTTP request failed, response:\n" .
                                substr( $result, 1024 ) );
index bf13865..4d2d1b9 100644 (file)
@@ -74,7 +74,6 @@ class SpecialAutoblockList extends SpecialPage {
                        ->setFormIdentifier( 'blocklist' )
                        ->setWrapperLegendMsg( 'autoblocklist-legend' )
                        ->setSubmitTextMsg( 'autoblocklist-submit' )
-                       ->setSubmitProgressive()
                        ->prepareForm()
                        ->displayForm( false );
 
index 0899d58..667b814 100644 (file)
@@ -108,7 +108,6 @@ class SpecialBlockList extends SpecialPage {
                        ->setFormIdentifier( 'blocklist' )
                        ->setWrapperLegendMsg( 'ipblocklist-legend' )
                        ->setSubmitTextMsg( 'ipblocklist-submit' )
-                       ->setSubmitProgressive()
                        ->prepareForm()
                        ->displayForm( false );
 
index 7694a61..e6d81c9 100644 (file)
@@ -131,7 +131,6 @@ class FileDuplicateSearchPage extends QueryPage {
                $htmlForm->addHiddenFields( $hiddenFields );
                $htmlForm->setAction( wfScript() );
                $htmlForm->setMethod( 'get' );
-               $htmlForm->setSubmitProgressive();
                $htmlForm->setSubmitTextMsg( $this->msg( 'fileduplicatesearch-submit' ) );
 
                // The form should be visible always, even if it was submitted (e.g. to perform another action).
index 46d5276..9e2f55e 100644 (file)
@@ -251,13 +251,12 @@ class SpecialNewpages extends IncludableSpecialPage {
                                'default' => $tagFilterVal,
                        ],
                        'username' => [
-                               'type' => 'text',
+                               'type' => 'user',
                                'name' => 'username',
                                'label-message' => 'newpages-username',
                                'default' => $userText,
                                'id' => 'mw-np-username',
                                'size' => 30,
-                               'cssclass' => 'mw-autocomplete-user', // used by mediawiki.userSuggest
                        ],
                        'size' => [
                                'type' => 'sizefilter',
@@ -269,7 +268,6 @@ class SpecialNewpages extends IncludableSpecialPage {
                $htmlForm = new HTMLForm( $form, $this->getContext() );
 
                $htmlForm->setSubmitText( $this->msg( 'newpages-submit' )->text() );
-               $htmlForm->setSubmitProgressive();
                // The form should be visible on each request (inclusive requests with submitted forms), so
                // return always false here.
                $htmlForm->setSubmitCallback(
index 34ffa07..9ff6d70 100644 (file)
@@ -98,56 +98,39 @@ class SpecialPrefixindex extends SpecialAllPages {
         * @return string
         */
        protected function namespacePrefixForm( $namespace = NS_MAIN, $from = '' ) {
-               $out = Xml::openElement( 'div', [ 'class' => 'namespaceoptions' ] );
-               $out .= Xml::openElement(
-                       'form',
-                       [ 'method' => 'get', 'action' => $this->getConfig()->get( 'Script' ) ]
-               );
-               $out .= Html::hidden( 'title', $this->getPageTitle()->getPrefixedText() );
-               $out .= Xml::openElement( 'fieldset' );
-               $out .= Xml::element( 'legend', null, $this->msg( 'allpages' )->text() );
-               $out .= Xml::openElement( 'table', [ 'id' => 'nsselect', 'class' => 'allpages' ] );
-               $out .= "<tr>
-                               <td class='mw-label'>" .
-                       Xml::label( $this->msg( 'allpagesprefix' )->text(), 'nsfrom' ) .
-                       "</td>
-                               <td class='mw-input'>" .
-                       Xml::input( 'prefix', 30, str_replace( '_', ' ', $from ), [ 'id' => 'nsfrom' ] ) .
-                       "</td>
-                       </tr>
-                       <tr>
-                       <td class='mw-label'>" .
-                       Xml::label( $this->msg( 'namespace' )->text(), 'namespace' ) .
-                       "</td>
-                               <td class='mw-input'>" .
-                       Html::namespaceSelector( [
-                               'selected' => $namespace,
-                       ], [
+               $formDescriptor = [
+                       'prefix' => [
+                               'label-message' => 'allpagesprefix',
+                               'name' => 'prefix',
+                               'type' => 'text',
+                               'size' => '30',
+                       ],
+                       'namespace' => [
+                               'type' => 'namespaceselect',
                                'name' => 'namespace',
                                'id' => 'namespace',
-                               'class' => 'namespaceselector',
-                       ] ) .
-                       Xml::checkLabel(
-                               $this->msg( 'allpages-hide-redirects' )->text(),
-                               'hideredirects',
-                               'hideredirects',
-                               $this->hideRedirects
-                       ) . ' ' .
-                       Xml::checkLabel(
-                               $this->msg( 'prefixindex-strip' )->text(),
-                               'stripprefix',
-                               'stripprefix',
-                               $this->stripPrefix
-                       ) . ' ' .
-                       Xml::submitButton( $this->msg( 'prefixindex-submit' )->text() ) .
-                       "</td>
-                       </tr>";
-               $out .= Xml::closeElement( 'table' );
-               $out .= Xml::closeElement( 'fieldset' );
-               $out .= Xml::closeElement( 'form' );
-               $out .= Xml::closeElement( 'div' );
-
-               return $out;
+                               'label-message' => 'namespace',
+                               'all' => null,
+                               'value' => $namespace,
+                       ],
+                       'hidedirects' => [
+                               'class' => 'HTMLCheckField',
+                               'name' => 'hideredirects',
+                               'label-message' => 'allpages-hide-redirects',
+                       ],
+                       'stripprefix' => [
+                               'class' => 'HTMLCheckField',
+                               'name' => 'stripprefix',
+                               'label-message' => 'prefixindex-strip',
+                       ],
+               ];
+               $htmlForm = new HTMLForm( $formDescriptor, $this->getContext() );
+               $htmlForm
+                       ->setMethod( 'get' )
+                       ->setWrapperLegendMsg( 'allpages' )
+                       ->setSubmitTextMsg( 'prefixindex-submit' );
+
+               return $htmlForm->prepareForm()->getHTML( false );
        }
 
        /**
index d693b99..26f4da5 100644 (file)
@@ -45,9 +45,12 @@ class SpecialProtectedpages extends SpecialPage {
                $sizetype = $request->getVal( 'size-mode' );
                $size = $request->getIntOrNull( 'size' );
                $ns = $request->getIntOrNull( 'namespace' );
-               $indefOnly = $request->getBool( 'indefonly' ) ? 1 : 0;
-               $cascadeOnly = $request->getBool( 'cascadeonly' ) ? 1 : 0;
-               $noRedirect = $request->getBool( 'noredirect' ) ? 1 : 0;
+
+               $filters = $request->getArray( 'wpfilters' );
+               $filters = is_null( $filters ) ? [] : $filters;
+               $indefOnly = in_array( 'indefonly', $filters );
+               $cascadeOnly = in_array( 'cascadeonly', $filters );
+               $noRedirect = in_array( 'noredirect', $filters );
 
                $pager = new ProtectedPagesPager(
                        $this,
@@ -69,9 +72,7 @@ class SpecialProtectedpages extends SpecialPage {
                        $level,
                        $sizetype,
                        $size,
-                       $indefOnly,
-                       $cascadeOnly,
-                       $noRedirect
+                       $filters
                ) );
 
                if ( $pager->getNumRows() ) {
@@ -87,13 +88,12 @@ class SpecialProtectedpages extends SpecialPage {
         * @param string $level Restriction level
         * @param string $sizetype "min" or "max"
         * @param int $size
-        * @param bool $indefOnly Only indefinite protection
-        * @param bool $cascadeOnly Only cascading protection
-        * @param bool $noRedirect Don't show redirects
+        * @param array $filters Filters set for the pager: indefOnly,
+        *   cascadeOnly, noRedirect
         * @return string Input form
         */
        protected function showOptions( $namespace, $type = 'edit', $level, $sizetype,
-               $size, $indefOnly, $cascadeOnly, $noRedirect
+               $size, $filters
        ) {
                $formDescriptor = [
                        'namespace' => [
@@ -106,30 +106,23 @@ class SpecialProtectedpages extends SpecialPage {
                        ],
                        'typemenu' => $this->getTypeMenu( $type ),
                        'levelmenu' => $this->getLevelMenu( $level ),
-                       'expirycheck' => [
-                               'type' => 'check',
-                               'label' => $this->msg( 'protectedpages-indef' )->text(),
-                               'name' => 'indefonly',
-                               'id' => 'indefonly',
-                       ],
-                       'cascadecheck' => [
-                               'type' => 'check',
-                               'label' => $this->msg( 'protectedpages-cascade' )->text(),
-                               'name' => 'cascadeonly',
-                               'id' => 'cascadeonly',
-                       ],
-                       'redirectcheck' => [
-                               'type' => 'check',
-                               'label' => $this->msg( 'protectedpages-noredirect' )->text(),
-                               'name' => 'noredirect',
-                               'id' => 'noredirect',
+                       'filters' => [
+                               'class' => 'HTMLMultiSelectField',
+                               'label' => $this->msg( 'protectedpages-filters' )->text(),
+                               'flatlist' => true,
+                               'options' => [
+                                       $this->msg( 'protectedpages-indef' )->text() => 'indefonly',
+                                       $this->msg( 'protectedpages-cascade' )->text() => 'cascadeonly',
+                                       $this->msg( 'protectedpages-noredirect' )->text() => 'noredirect',
+                               ],
+                               'default' => $filters,
                        ],
                        'sizelimit' => [
                                'class' => HTMLSizeFilterField::class,
                                'name' => 'size',
                        ]
                ];
-               $htmlForm = new HTMLForm( $formDescriptor, $this->getContext() );
+               $htmlForm = HTMLForm::factory( 'ooui', $formDescriptor, $this->getContext() );
                $htmlForm
                        ->setMethod( 'get' )
                        ->setWrapperLegendMsg( 'protectedpages' )
index fa12f50..2770bc5 100644 (file)
@@ -125,7 +125,7 @@ class SpecialProtectedtitles extends SpecialPage {
                        'levelmenu' => $this->getLevelMenu( $level )
                ];
 
-               $htmlForm = new HTMLForm( $formDescriptor, $this->getContext() );
+               $htmlForm = HTMLForm::factory( 'ooui', $formDescriptor, $this->getContext() );
                $htmlForm
                        ->setMethod( 'get' )
                        ->setWrapperLegendMsg( 'protectedtitles' )
index b2d5a16..fe9202e 100644 (file)
@@ -57,7 +57,6 @@ class SpecialUnblock extends SpecialPage {
 
                $out = $this->getOutput();
                $out->setPageTitle( $this->msg( 'unblockip' ) );
-               $out->addModules( [ 'mediawiki.userSuggest' ] );
 
                $form = HTMLForm::factory( 'ooui', $this->getFields(), $this->getContext() );
                $form->setWrapperLegendMsg( 'unblockip' );
@@ -87,12 +86,11 @@ class SpecialUnblock extends SpecialPage {
        protected function getFields() {
                $fields = [
                        'Target' => [
-                               'type' => 'text',
+                               'type' => 'user',
                                'label-message' => 'ipaddressorusername',
                                'autofocus' => true,
                                'size' => '45',
                                'required' => true,
-                               'cssclass' => 'mw-autocomplete-user', // used by mediawiki.userSuggest
                        ],
                        'Name' => [
                                'type' => 'info',
index 40f02a5..6d6bf0e 100644 (file)
@@ -325,8 +325,8 @@ class UserrightsPage extends SpecialPage {
         *   containing only those groups that are to have new expiry values set
         * @return array Tuple of added, then removed groups
         */
-       function doSaveUserGroups( $user, $add, $remove, $reason = '', $tags = [],
-               $groupExpiries = []
+       function doSaveUserGroups( $user, array $add, array $remove, $reason = '',
+               array $tags = [], array $groupExpiries = []
        ) {
                // Validate input set...
                $isself = $user->getName() == $this->getUser()->getName();
@@ -427,13 +427,13 @@ class UserrightsPage extends SpecialPage {
         * @param User|UserRightsProxy $user
         * @param array $oldGroups
         * @param array $newGroups
-        * @param array $reason
+        * @param string $reason
         * @param array $tags Change tags for the log entry
         * @param array $oldUGMs Associative array of (group name => UserGroupMembership)
         * @param array $newUGMs Associative array of (group name => UserGroupMembership)
         */
-       protected function addLogEntry( $user, $oldGroups, $newGroups, $reason, $tags,
-               $oldUGMs, $newUGMs
+       protected function addLogEntry( $user, array $oldGroups, array $newGroups, $reason,
+               array $tags, array $oldUGMs, array $newUGMs
        ) {
                // make sure $oldUGMs and $newUGMs are in the same order, and serialise
                // each UGM object to a simplified array
index 5457949..36391f5 100644 (file)
                {{^localSettingsExists}}
                        <p>LocalSettings.php not found.</p>
                        {{#installerStarted}}
-                               <p>Please <a href="{{path}}mw-config/index.{{ext}}">complete the installation</a> and download LocalSettings.php.</p>
+                               <p>Please <a href="{{path}}mw-config/index.php">complete the installation</a> and download LocalSettings.php.</p>
                        {{/installerStarted}}
                        {{^installerStarted}}
-                               <p>Please <a href="{{path}}mw-config/index.{{ext}}">set up the wiki</a> first.</p>
+                               <p>Please <a href="{{path}}mw-config/index.php">set up the wiki</a> first.</p>
                        {{/installerStarted}}
                {{/localSettingsExists}}
                </div>
        </body>
-</html>
\ No newline at end of file
+</html>
index ea395f4..3335e59 100644 (file)
@@ -33,13 +33,6 @@ use Wikimedia\Rdbms\Database;
 use Wikimedia\Rdbms\DBExpectedError;
 use Wikimedia\Rdbms\IDatabase;
 
-/**
- * String Some punctuation to prevent editing from broken text-mangling proxies.
- * @deprecated since 1.27, use \MediaWiki\Session\Token::SUFFIX
- * @ingroup Constants
- */
-define( 'EDIT_TOKEN_SUFFIX', Token::SUFFIX );
-
 /**
  * The User object encapsulates all of the user-specific settings (user_id,
  * name, rights, email address, options, last login time). Client
@@ -66,7 +59,7 @@ class User implements IDBAccessObject, UserIdentity {
         * magic can be used.
         * @deprecated since 1.27, use \MediaWiki\Session\Token::SUFFIX
         */
-       const EDIT_TOKEN_SUFFIX = EDIT_TOKEN_SUFFIX;
+       const EDIT_TOKEN_SUFFIX = Token::SUFFIX;
 
        /**
         * @const int Serialized record version.
index 88ba7bc..6cd4d37 100644 (file)
        "statistics-files": "الملفات المرفوعة",
        "statistics-edits": "تعديلات الصفحات منذ تنصيب {{SITENAME}}",
        "statistics-edits-average": "متوسط التعديلات لكل صفحة",
-       "statistics-users": "[[Special:ListUsers|مستخدمون]] مسجلون",
+       "statistics-users": "مستخدمون مسجلون",
        "statistics-users-active": "مستخدمون نشطون",
        "statistics-users-active-desc": "المستخدمون الذين قاموا بفعل في آخر {{PLURAL:$1||يوم|يومين|$1 أيام|$1 يوماً|$1 يوم}}",
        "pageswithprop": "صفحات مع خاصية الصفحة",
        "mostinterwikis": "الصفحات التي تحتوي على أغلب وصلات الإنترويكي",
        "mostrevisions": "أكثر الصفحات تعديلا",
        "prefixindex": "كل الصفحات بالبادئة",
-       "prefixindex-namespace": "كل الصفحات مع بادئة ($1 مساحة الأسم)",
+       "prefixindex-namespace": "كل الصفحات مع بادئة (نطاق $1)",
        "prefixindex-submit": "اعرض",
        "prefixindex-strip": "أخف البادئة من القائمة",
        "shortpages": "صفحات قصيرة",
index 39fa8dd..d618ebc 100644 (file)
@@ -52,7 +52,7 @@
        "tog-watchlisthideminor": "Anubrir les ediciones menores na llista de siguimientu",
        "tog-watchlisthideliu": "Anubrir les ediciones d'usuarios identificaos na llista de siguimientu",
        "tog-watchlistreloadautomatically": "Recargar la llista de siguimientu automáticamente cuando se cambie un filtru (rique JavaScript).",
-       "tog-watchlistunwatchlinks": "Añadir enllaces direutos pa siguir o dexar de siguir les entraes de la llista de siguimientu (rique JavaScript p'activar la función)",
+       "tog-watchlistunwatchlinks": "Añadir marcadores direutos pa siguir o dexar de siguir ({{int:Watchlist-unwatch}}/{{int:Watchlist-unwatch-undo}}) les páxines con cambios de la llista de siguimientu (rique JavaScript p'activar la función)",
        "tog-watchlisthideanons": "Anubrir les ediciones d'usuarios anónimos na llista de siguimientu",
        "tog-watchlisthidepatrolled": "Anubrir les ediciones patrullaes na llista de siguimientu",
        "tog-watchlisthidecategorization": "Tapecer la categorización de páxines",
        "password-login-forbidden": "Ta torgao usar esti nome d'usuariu y contraseña.",
        "mailmypassword": "Reaniciar contraseña",
        "passwordremindertitle": "Nueva contraseña provisional pa {{SITENAME}}",
-       "passwordremindertext": "Daquién (seique tu, dende la direición IP $1) solicitó una contraseña\nnueva pa {{SITENAME}} ($4). Creóse una contraseña provisional\npal usuariu «$2» que ye «$3». Si fuisti tu, necesites aniciar\nsesión y escoyer una contraseña nueva agora.\nLa contraseña provisional caducará {{PLURAL:$5|nun día|en $5 díes}}.\n\nSi esta solicitú fizola otra persona, o si recordasti la contraseña,\ny nun quies camudala, pues escaecete d'esti mensaxe y siguir\nusando la contraseña antigua.",
+       "passwordremindertext": "Daquién (dende la direición IP $1) solicitó una contraseña\nnueva pa {{SITENAME}} ($4). Creóse una contraseña provisional\npal usuariu «$2» que ye «$3». Si fuisti tu, necesites aniciar\nsesión y escoyer una contraseña nueva agora.\nLa contraseña provisional caducará {{PLURAL:$5|nun día|en $5 díes}}.\n\nSi esta solicitú fizola otra persona, o si recordasti la contraseña,\ny nun quies camudala, pues escaecete d'esti mensaxe y siguir\nusando la contraseña antigua.",
        "noemail": "L'usuariu «$1» nun tien rexistrada nenguna direición de corréu.",
        "noemailcreate": "Tienes de conseñar una direición de corréu válida.",
        "passwordsent": "Unvióse una contraseña nueva a la direición de corréu rexistrada pa «$1».\nPor favor vuelvi a aniciar sesión depués de recibila.",
        "longpageerror": "'''ERROR: El testu qu'unviasti tien {{PLURAL:$1|un quilobyte|$1 quilobytes}}, que pasa del máximu de {{PLURAL:$2|un quilobyte|$2 quilobytes}}.'''\nNun se pue grabar.",
        "readonlywarning": "<strong>Avisu: La base de datos ta candada por mantenimientu, polo que nun vas poder guardar les tos ediciones nestos momentos.</strong>\nSeique habríes copiar y apegar el testu nun ficheru de testu y guardalu pa intentalo sero.\n\nL'alministrador del sistema que la candó dio esta esplicación: $1",
        "protectedpagewarning": "'''Avisu: Esta páxina ta candada pa que sólo los alministradores puean editala.'''\nLa cabera entrada del rexistru s'ufre darréu pa referencia:",
-       "semiprotectedpagewarning": "'''Nota:''' Esta páxina ta candada pa que nun puean editala namái que los usuarios rexistraos.\nLa cabera entrada del rexistru s'ufre darréu pa referencia:",
+       "semiprotectedpagewarning": "<strong>Nota:</strong> Esta páxina ta candada pa que nun puedan editala namái que los usuarios autoconfirmaos.\nLa cabera entrada del rexistru s'ufre darréu pa referencia:",
        "cascadeprotectedwarning": "<strong>Avisu:</strong> Esta páxina ta candada pa que namái los usuarios con [[Special:ListGroupRights|determinaos permisos]] puedan editala porque ta trescluída {{PLURAL:$1|na siguiente páxina protexida|nes siguientes páxines protexíes}} en cascada:",
        "titleprotectedwarning": "'''Avisu: Esta páxina ta candada pa que necesite [[Special:ListGroupRights|permisos especiales]] pa creala.'''\nLa cabera entrada del rexistru s'ufre darréu pa referencia:",
        "templatesused": "{{PLURAL:$1|Plantía usada|Plantíes usaes}} nesta páxina:",
        "rcfilters-filter-humans-label": "Ser humanu (non bot)",
        "rcfilters-filter-humans-description": "Ediciones feches por editores humanos.",
        "rcfilters-filtergroup-reviewstatus": "Estáu de revisión",
+       "rcfilters-filter-reviewstatus-unpatrolled-description": "Ediciones nun marcaes como patrullaes de mou manual o automáticu.",
        "rcfilters-filter-reviewstatus-unpatrolled-label": "Sin patrullar",
+       "rcfilters-filter-reviewstatus-manual-description": "Ediciones marcaes como patrullaes de mou manual.",
+       "rcfilters-filter-reviewstatus-manual-label": "Patrullaes de mou manual",
+       "rcfilters-filter-reviewstatus-auto-description": "Ediciones d'usuarios avanzaos que se marquen automáticamente como patrullaes.",
+       "rcfilters-filter-reviewstatus-auto-label": "Autopatrullaos",
        "rcfilters-filtergroup-significance": "Significación",
        "rcfilters-filter-minor-label": "Ediciones menores",
        "rcfilters-filter-minor-description": "Ediciones que l'autor etiquetó como menores.",
        "statistics-files": "Ficheros xubíos",
        "statistics-edits": "Ediciones de páxines dende'l principiu de {{SITENAME}}",
        "statistics-edits-average": "Media d'ediciones por páxina",
-       "statistics-users": "[[Special:ListUsers|Usuarios]] rexistraos",
+       "statistics-users": "Usuarios rexistraos",
        "statistics-users-active": "Usuarios activos",
        "statistics-users-active-desc": "Usuarios que ficieron dalguna aición {{PLURAL:$1|nel caberu día|nos caberos $1 díes}}",
        "pageswithprop": "Páxines con una propiedá de páxina",
        "deadendpages": "Páxines ensin salida",
        "deadendpagestext": "Les páxines siguientes nun enllacien a otres páxines de {{SITENAME}}.",
        "protectedpages": "Páxines protexíes",
+       "protectedpages-filters": "Peñeres:",
        "protectedpages-indef": "Namái les proteiciones indefiníes",
        "protectedpages-summary": "Esta páxina amuesa la llista de páxines esistentes que tan protexíes actualmente. Pa la llista de títulos que tienen torgada la creación, ver [[{{#special:ProtectedTitles}}|{{int:protectedtitles}}]].",
        "protectedpages-cascade": "Namái proteiciones en cascada",
        "apisandbox-dynamic-error-exists": "Yá existe un parámetru llamáu «$1».",
        "apisandbox-deprecated-parameters": "Parámetros anticuaos",
        "apisandbox-fetch-token": "Rellenu automáticu del pase",
+       "apisandbox-add-multi": "Amestar",
        "apisandbox-submit-invalid-fields-title": "Dalgunos campos son inválidos",
        "apisandbox-submit-invalid-fields-message": "Por favor, igua los campos señalaos y téntalo nuevamente.",
        "apisandbox-results": "Resultaos",
        "fix-double-redirects": "Actualizar toles redireiciones qu'apunten al títulu orixinal",
        "move-leave-redirect": "Dexar una redireición detrás",
        "protectedpagemovewarning": "'''Avisu: Esta páxina ta candada pa que sólo los alministradores puedan treslladala.'''\nLa cabera entrada del rexistru s'ufre darréu pa referencia:",
-       "semiprotectedpagemovewarning": "'''Nota:''' Esta páxina ta candada pa que namái los usuarios rexistraos puedan treslladala.\nLa cabera entrada del rexistru s'ufre darréu pa referencia:",
+       "semiprotectedpagemovewarning": "<strong>Nota:</strong> Esta páxina ta candada pa que namái los usuarios autoconfirmaos puedan treslladala.\nLa cabera entrada del rexistru s'ufre darréu pa referencia:",
        "move-over-sharedrepo": "\n[[:$1]] esiste nun estoyu compartíu. Si mueves un ficheru a esti títulu saltaráse'l ficheru compartíu.",
        "file-exists-sharedrepo": "El nome de ficheru qu'escoyisti yá ta n'usu nun repositoriu compartíu.\nEscueyi otru nome, por favor.",
        "export": "Esportar páxines",
        "version-specialpages": "Páxines especiales",
        "version-parserhooks": "Hooks d'análisis sintáuticu",
        "version-variables": "Variables",
+       "version-editors": "Editores",
        "version-antispam": "Prevención del corréu puxarra",
        "version-other": "Otros",
        "version-mediahandlers": "Remanadores d'archivos multimedia",
index 15b54ab..652cc1a 100644 (file)
@@ -16,7 +16,8 @@
                        "아라",
                        "Liashko",
                        "Macofe",
-                       "Kareyac"
+                       "Kareyac",
+                       "Artsiom91"
                ]
        },
        "tog-underline": "Падкрэсьліваць спасылкі:",
        "action-protect": "зьмену ўзроўню абароны гэтай старонкі",
        "action-rollback": "хуткі адкат рэдагаваньняў апошняга ўдзельніка, які рэдагаваў старонку",
        "action-import": "імпарт старонак зь іншай вікі",
-       "action-importupload": "Ñ\96мпаÑ\80Ñ\82 Ñ\81Ñ\82аÑ\80онак Ð¿Ñ\80аз Ð·Ð°Ð³Ñ\80Ñ\83зкÑ\83 Ñ\84айла",
+       "action-importupload": "Ñ\96мпаÑ\80Ñ\82 Ñ\81Ñ\82аÑ\80онак Ð¿Ñ\80аз Ð·Ð°Ð³Ñ\80Ñ\83жанÑ\8b Ñ\84айл",
        "action-patrol": "пазначэньне чужых рэдагаваньняў як «патруляваныя»",
        "action-autopatrol": "пазначэньне ўласных рэдагаваньняў як «патруляваныя»",
        "action-unwatchedpages": "прагляд сьпісу старонак, за якімі ніхто не назірае",
        "action-userrights": "рэдагаваньне правоў усіх удзельнікаў",
        "action-userrights-interwiki": "рэдагаваньне правоў удзельнікаў у іншых вікі",
        "action-siteadmin": "блякаваньне і разблякаваньне базы зьвестак",
-       "action-sendemail": "адпÑ\80аÑ\9eлÑ\8fÑ\86Ñ\8c Ð»Ñ\96Ñ\81Ñ\82Ñ\8b Ñ\96нÑ\88Ñ\8bм Ñ\83дзелÑ\8cнÑ\96кам",
+       "action-sendemail": "адпÑ\80аÑ\9eкÑ\83 Ð»Ñ\96Ñ\81Ñ\82оÑ\9e Ñ\8dлекÑ\82Ñ\80оннай Ð¿Ð¾Ñ\88Ñ\82ай",
        "action-editmyoptions": "рэдагаваньне вашых наладаў",
-       "action-editmywatchlist": "рэдагаваць ваш сьпіс назіраньня",
-       "action-viewmywatchlist": "праглядаць ваш сьпіс назіраньня",
+       "action-editmywatchlist": "рэдагаваньне вашага сьпісу назіраньня",
+       "action-viewmywatchlist": "прагляд вашага сьпісу назіраньня",
        "action-viewmyprivateinfo": "прагляд вашых прыватных зьвестак",
        "action-editmyprivateinfo": "рэдагаваньне вашых прыватных зьвестак",
        "action-editcontentmodel": "рэдагаваньне мадэлі зьместу старонкі",
        "rcfilters-filter-reviewstatus-unpatrolled-description": "Рэдагаваньні, якія не былі пазначаныя як патруляваныя, уручную ці аўтаматычна.",
        "rcfilters-filter-reviewstatus-unpatrolled-label": "Неправераныя",
        "rcfilters-filter-reviewstatus-manual-description": "Рэдагаваньні, уручную пазначаныя як патруляваныя.",
+       "rcfilters-filter-reviewstatus-manual-label": "Патруляванае ўручную",
+       "rcfilters-filter-reviewstatus-auto-description": "Рэдагаваньні дасьведчаных удзельнікаў, якія аўтаматычна пазначаюцца як патруляваныя.",
+       "rcfilters-filter-reviewstatus-auto-label": "Аўтаматычна патруляваныя",
        "rcfilters-filtergroup-significance": "Значэньне",
        "rcfilters-filter-minor-label": "Дробныя праўкі",
        "rcfilters-filter-minor-description": "Праўкі, якія аўтар пазначыў як дробныя.",
        "statistics-files": "Колькасьць загружаных файлаў",
        "statistics-edits": "Агульная колькасьць рэдагаваньняў",
        "statistics-edits-average": "Сярэдняя колькасьць рэдагаваньняў на старонку",
-       "statistics-users": "[[Special:ListUsers|Зарэгістраваныя ўдзельнікі]]",
+       "statistics-users": "Зарэгістраваныя ўдзельнікі",
        "statistics-users-active": "Актыўныя ўдзельнікі",
        "statistics-users-active-desc": "Удзельнікі, якія выканалі нейкае дзеяньне цягам {{PLURAL:$1|апошняга $1 дня|апошніх $1 дзён|апошніх $1 дзён}}",
        "pageswithprop": "Старонкі з уласьцівасьцямі старонак",
        "deadendpages": "Тупіковыя старонкі",
        "deadendpagestext": "Наступныя старонкі не спасылаюцца на іншыя старонкі {{GRAMMAR:родны|{{SITENAME}}}}.",
        "protectedpages": "Абароненыя старонкі",
+       "protectedpages-filters": "Фільтры:",
        "protectedpages-indef": "Толькі бестэрміновыя абароны",
        "protectedpages-summary": "На гэтай старонцы пералічаныя старонкі, якія цяпер абароненыя. Для сьпісу назваў, якія забароненыя для стварэньня, глядзіце [[{{#special:ProtectedTitles}}|{{int:protectedtitles}}]].",
        "protectedpages-cascade": "Толькі каскадныя абароны",
        "exif-focalplanexresolution": "Разрозьненьне ў фокуснай плоскасьці па восі X",
        "exif-focalplaneyresolution": "Разрозьненьне ў фокуснай плоскасьці па восі Y",
        "exif-focalplaneresolutionunit": "Адзінка разрозьненьня фокуснай плоскасьці",
-       "exif-subjectlocation": "Месцазнаходжаньне аб'екту",
+       "exif-subjectlocation": "Месцазнаходжаньне абекту",
        "exif-exposureindex": "Індэкс насьвятленьня",
        "exif-sensingmethod": "Тып сэнсару",
        "exif-filesource": "Крыніца файла",
        "exif-gpsimgdirectionref": "Тып азімуту выявы",
        "exif-gpsimgdirection": "Кірунак выявы",
        "exif-gpsmapdatum": "Скарыстаная геадэзічная сыстэма каардынатаў",
-       "exif-gpsdestlatituderef": "Пункт адліку шыраты аб'екту",
+       "exif-gpsdestlatituderef": "Пункт адліку шыраты абекту",
        "exif-gpsdestlatitude": "Шырата аб'екту",
-       "exif-gpsdestlongituderef": "Пункт адліку даўгаты аб'екту",
-       "exif-gpsdestlongitude": "Даўгата аб'екту",
+       "exif-gpsdestlongituderef": "Пункт адліку даўгаты абекту",
+       "exif-gpsdestlongitude": "Даўгата абекту",
        "exif-gpsdestbearingref": "Тып пэленгу аб'екту",
        "exif-gpsdestbearing": "Пэленг аб'екту",
-       "exif-gpsdestdistanceref": "Пункт адліку адлегласьці да аб'екту",
+       "exif-gpsdestdistanceref": "Пункт адліку адлегласьці да абекту",
        "exif-gpsdestdistance": "Адлегласьць да аб'екту",
        "exif-gpsprocessingmethod": "Назва мэтаду вылічэньня GPS",
        "exif-gpsareainformation": "Назва GPS-зоны",
index 67289d5..653e232 100644 (file)
        "and": "&#32;і",
        "faq": "ЧАПЫ",
        "actions": "Дзеянні",
-       "namespaces": "Прасторы імёнаў",
+       "namespaces": "Прасторы назваў",
        "variants": "Варыянты",
        "navigation-heading": "Навігацыя",
        "errorpagetitle": "Памылка",
        "content-model-text": "звычайны тэкст",
        "content-model-javascript": "JavaScript",
        "content-model-css": "CSS",
-       "content-json-empty-object": "Пусты аб'ект",
+       "content-json-empty-object": "Пусты абект",
        "content-json-empty-array": "Пусты масіў",
        "deprecated-self-close-category": "Старонкі з недапушчальнымі самазакрытымі HTML-тэгамі",
        "deprecated-self-close-category-desc": "Старонка ўтрымлівае недапушчальныя самазакрытыя HTML-тэгі, такія як <code>&lt;b/></code> ці <code>&lt;span/></code>. Іх паводзіны ў хуткім часе будуць зменены ў адпаведнасці з спецыфікацыяй HTML5, таму іх ужыванне ў вікітэксце лічыцца састарэлым.",
        "file-thumbnail-no": "Назва файла пачынаецца з <strong>$1</strong>.\nТак можа называцца выява зменшанага памеру ''(драбніца)''.\nКалі гэтая выява сапраўды запісаная ў найлепшым разрозненні, якое ёсць, то ўкладайце яе, а іначай лепей памяняць назву файла.",
        "fileexists-forbidden": "Файл з такой назвай ужо ёсць, і нельга запісаць паўзверх яго. Калі вы жадаеце абавязкова ўкласці свой файл, то выберыце новую назву. [[File:$1|thumb|center|$1]]",
        "fileexists-shared-forbidden": "У агульным сховішчы ўжо існуе файл з такою назвай.\nКалі вы жадаеце ўсё ж укласці свой файл, паўтарыце працэдуру ўкладання, але з іншай назвай. [[File:$1|thumb|center|$1]]",
-       "fileexists-no-change": "Укладанне з'яўляецца дакладнай копіяй бягучай версіі <strong>[[:$1]]</strong>.",
-       "fileexists-duplicate-version": "Укладанне з'яўляецца дакладнай копіяй {{PLURAL:$2|старой версіі|старых версій}} файла <strong>[[:$1]]</strong>.",
-       "file-exists-duplicate": "Гэты файл з'яўляецца дублікатам наступн{{PLURAL:$1|ага файла|ых файлаў}}:",
+       "fileexists-no-change": "Укладанне зяўляецца дакладнай копіяй бягучай версіі <strong>[[:$1]]</strong>.",
+       "fileexists-duplicate-version": "Укладанне зяўляецца дакладнай копіяй {{PLURAL:$2|старой версіі|старых версій}} файла <strong>[[:$1]]</strong>.",
+       "file-exists-duplicate": "Гэты файл зяўляецца дублікатам наступн{{PLURAL:$1|ага файла|ых файлаў}}:",
        "file-deleted-duplicate": "Файл, падобны да гэтага ([[:$1]]), быў сцёрты некалі раней. Трэба праверыць гісторыю таго файла перад тым, як укладваць яго нанова.",
        "file-deleted-duplicate-notitle": "Файл, ідэнтычны гэтаму, быў сцёрты раней, а назва файла заглушана.\nВы мусіце спытаць каго-небудзь з магчымасцю бачыць заглушаныя звесткі па файлах пераглядзець сітуацыю перад тым, як укладваць яго нанова.",
        "uploadwarning": "Папярэджанне пра ўкладанне",
        "upload-form-label-infoform-name": "Назва",
        "upload-form-label-infoform-name-tooltip": "Унікальны апісальны загаловак для файла, які будзе служыць яго назвай. Можаце выкарыстоўваць звычайную мову з прабеламі. Не дадавайце канчатак назвы файла.",
        "upload-form-label-infoform-description": "Апісанне",
-       "upload-form-label-infoform-description-tooltip": "Коратка апішыце ўсё значнае пра гэту працу.\nДля фатаграфіі ўкажыце галоўныя аб'екты, нагоду або месца.",
+       "upload-form-label-infoform-description-tooltip": "Коратка апішыце ўсё значнае пра гэту працу.\nДля фатаграфіі ўкажыце галоўныя абекты, нагоду або месца.",
        "upload-form-label-usage-title": "Выкарыстанне",
        "upload-form-label-usage-filename": "Назва файла",
        "upload-form-label-own-work": "Гэта мая ўласная праца",
        "backend-fail-notexists": "Файл $1 не існуе.",
        "backend-fail-hashes": "Не ўдалося атрымаць хэшы файлаў для параўнання.",
        "backend-fail-notsame": "Ужо існуе неідэнтычны файл $1.",
-       "backend-fail-invalidpath": "$1 не з'яўляецца дапушчальным шляхам",
+       "backend-fail-invalidpath": "$1 не з’яўляецца дапушчальным шляхам.",
        "backend-fail-delete": "Не ўдалося сцерці файл \"$1\".",
        "backend-fail-describe": "Немагчыма змяніць метазвесткі для файла \"$1\".",
        "backend-fail-alreadyexists": "Файл $1 ужо існуе.",
        "lockmanager-fail-svr-acquire": "Не ўдалося атрымаць блакаванні на серверы $1.",
        "lockmanager-fail-svr-release": "Не атрымалася зняць блакаванні на серверы $1.",
        "zip-file-open-error": "Адбылася памылка пры адкрыцці файла для праверкі архіва.",
-       "zip-wrong-format": "Указаны файл не з'яўляецца файлам ZIP.",
+       "zip-wrong-format": "Указаны файл не зяўляецца файлам ZIP.",
        "zip-bad": "ZIP-файл пашкоджаны, або не можа быць прачытаны.\nЁн не можа быць належным чынам правераны.",
        "zip-unsupported": "Гэты ZIP-файл выкарыстоўвае магчымасці, якія не падтрымліваюцца MediaWiki.\nЁн не можа быць належным чынам правераны.",
        "uploadstash": "Схаванае ўкладанне",
        "uploadstash-refresh": "Абнавіць спіс файлаў",
        "uploadstash-thumbnail": "паказаць мініяцюру",
        "uploadstash-file-not-found-no-local-path": "Не знойдзена лакальнага шляху да отмасштабированному файлу.",
-       "uploadstash-file-not-found-no-object": "Не атрымалася стварыць аб'ект лакальнага файла для мініяцюры.",
+       "uploadstash-file-not-found-no-object": "Не атрымалася стварыць абект лакальнага файла для мініяцюры.",
        "uploadstash-file-not-found-missing-content-type": "Отсутствует загаловак content-type.",
        "uploadstash-file-not-found-not-exists": "Шлях не знойдзены, альбо файл незразумелы.",
        "uploadstash-no-extension": "Пустое расшырэнне.",
        "img-auth-nofile": "Файл \" $1 \"не існуе.",
        "img-auth-isdir": "Вы спрабуеце атрымаць доступ да каталога \"$1\"\nДазволены доступ толькі да файлаў.",
        "img-auth-streaming": "Патокавая перадача «$1».",
-       "img-auth-public": "Прызначэннем img_auth.php з'яўляецца вывад файлаў з закрытай вікі.\nГэтая вікі настроена як агульнадаступная.\nДля аптымізацыі бяспекі img_auth.php адключаная.",
+       "img-auth-public": "Прызначэннем img_auth.php з’яўляецца вывад файлаў з закрытага вікіпраекта.\nГэты вікіпраект настроен як агульнадаступны.\nДля аптымізацыі бяспекі img_auth.php адключаная.",
        "img-auth-noread": "Удзельнік не мае доступу на чытанне да «$1».",
        "http-invalid-url": "Памылковы URL: $1",
        "http-invalid-scheme": "Не падтрымліваюцца адрасы са схемай \"$1\"",
        "nolinkstoimage": "Няма старонак, якія б спасылаліся на файл.",
        "morelinkstoimage": "Паказаць [[Special:WhatLinksHere/$1|больш спасылак]] на гэты файл.",
        "linkstoimage-redirect": "$1 (файл-перанакіраванне) $2",
-       "duplicatesoffile": "Наступн{{PLURAL:$1|ы файл з'яўляецца дублікатам|ыя $1 файлы з'яўляюцца дублікатамі}} гэтага файла ([[Special:FileDuplicateSearch/$2|падрабязна]]):",
+       "duplicatesoffile": "Наступн{{PLURAL:$1|ы файл з’яўляецца дублікатам|ыя $1 файлы з’яўляюцца дублікатамі}} гэтага файла ([[Special:FileDuplicateSearch/$2|падрабязна]]):",
        "sharedupload": "Гэты файл з $1 і можа выкарыстоўвацца іншымі праектамі.",
        "sharedupload-desc-there": "Гэты файл з $1 і можа выкарыстоўвацца ў іншых праектах.\nДадатковую інфармацыю можна знайсці на [$2 старонцы апісання файла].",
        "sharedupload-desc-here": "Гэты файл з $1 і можа выкарыстоўвацца іншымі праектамі. Апісанне на яго [$2 старонцы размоў] прыведзена ніжэй",
        "mostinterwikis": "Артыкулы з найбольш. кольк. інтэрвікі",
        "mostrevisions": "Артыкулы з найбольшай колькасцю версій",
        "prefixindex": "Старонкі з назвамі на ўзор",
-       "prefixindex-namespace": "Усе старонкі з прэфіксам ( $1 прастора імёнаў)",
+       "prefixindex-namespace": "Усе старонкі з прэфіксам (прастора назваў «{{ns:$1}}»)",
        "prefixindex-submit": "Паказаць",
        "prefixindex-strip": "Прыбраць прэфікс у пераліку",
        "shortpages": "Старонкі малога аб'ёму",
        "categoriesfrom": "Паказаць катэгорыі, пачынаючы з:",
        "deletedcontributions": "Выдалены ўклад удзельніка",
        "deletedcontributions-title": "Выдалены ўклад удзельніка",
-       "sp-deletedcontributions-contribs": "Уклад",
+       "sp-deletedcontributions-contribs": "уклад",
        "linksearch": "Пошук вонкавых спасылак",
        "linksearch-pat": "Што шукаецца:",
        "linksearch-ns": "Прастора назваў:",
        "protect-title": "Ахова «$1»",
        "protect-title-notallowed": "Прагляд узроўня аховы «$1»",
        "prot_1movedto2": "[[$1]] перанесена ў [[$2]]",
-       "protect-badnamespace-title": "Прастора імёнаў без аховы",
-       "protect-badnamespace-text": "Старонкі ў гэтай прасторы імёнаў не могуць знаходзіцца пад аховай.",
+       "protect-badnamespace-title": "Прастора назваў без аховы",
+       "protect-badnamespace-text": "Старонкі ў гэтай прасторы назваў не могуць знаходзіцца пад аховай.",
        "protect-norestrictiontypes-text": "Старонка не можа ахоўвацца, бо для яе няма даступных тыпаў абмежавання.",
        "protect-norestrictiontypes-title": "Неахоўвальная старонка",
        "protect-legend": "Пацверджанне пачатку аховы",
        "undelete-show-file-submit": "Так",
        "namespace": "Прастора назваў:",
        "invert": "Пазначыць наадварот",
-       "tooltip-invert": "Установіце гэту адзнаку, каб схаваць змены на старонках, у межах абранай прасторы імёнаў (і звязаных прастор імёнаў, калі адзначана)",
+       "tooltip-invert": "Уключыце гэту адзнаку, каб схаваць змены на старонках, у межах абранай прасторы назваў (і звязаных прастор назваў, калі адзначана)",
        "namespace_association": "Звязаная прастора",
        "tooltip-namespace_association": "Устанавіце гэтую адзнаку, каб таксама ўключыць прастору імёнаў абмеркавання (або прадметную), звязаную з абранай прасторай імёнаў",
        "blanknamespace": "(Артыкулы)",
        "sp-contributions-blocked-notice-anon": "Гэты IP-адрас у дадзены момант заблакаваны.\nНіжэй прыведзены апошні запіс з журнала блакаванняў:",
        "sp-contributions-search": "Знайсці ўклад",
        "sp-contributions-username": "Адрас IP або імя ўдзельніка:",
-       "sp-contributions-toponly": "Паказваць толькі праўкі, якія з'яўляюцца апошнімі версіямі",
+       "sp-contributions-toponly": "Паказваць толькі праўкі, якія зяўляюцца апошнімі версіямі",
        "sp-contributions-newonly": "Паказваць толькі праўкі, якімі створаны старонкі",
        "sp-contributions-hideminor": "Схаваць дробныя праўкі",
        "sp-contributions-submit": "Пошук",
        "exif-disclaimer": "Адмова ад адказнасці",
        "exif-contentwarning": "Папярэджанне пра змест",
        "exif-giffilecomment": "Заўвага да GIF-файла",
-       "exif-intellectualgenre": "Тып аб'екта",
+       "exif-intellectualgenre": "Тып элемента",
        "exif-subjectnewscode": "Код тэмы",
        "exif-scenecode": "Код сцэны IPTC",
        "exif-event": "Паказаная падзея",
        "autosumm-removed-redirect": "Выдаленае перенаправление на [[$1]]",
        "autosumm-new": "Новая старонка: '$1'",
        "autosumm-newblank": "Створана пустая старонка",
+       "size-bytes": "$1 {{PLURAL:$1|байт|байты|байтаў}}",
        "lag-warn-normal": "Змены, зробленыя менш за $1 {{PLURAL:$1|сек.|сек.}} таму назад, могуць не трапіць у гэты спіс.",
        "lag-warn-high": "З прычыны моцных затрымак на серверы баз звестак, змены, зробленыя менш за $1 {{PLURAL:$1|секунду|секунды|секунд}} назад, могуць не трапіць у гэты спіс.",
        "watchlistedit-normal-title": "Спіс назірання",
        "version-poweredby-others": "іншыя",
        "version-poweredby-translators": "перакладчыкі translatewiki.net",
        "version-credits-summary": "Мы хацелі б адзначыць наступных асоб, якія зрабілі ўнёсак у [[Special:Version|MediaWiki]].",
-       "version-license-info": "MediaWiki з'яўляецца свабодным праграмным забеспячэннем. Такім чынам, вы можаце паўторна распаўсюджваць прадукт і(або) змяняць яго на ўмовах пагаднення GNU General Public License у тым выглядзе, у якім яно публікуецца фондам Free Software Foundation; сілу мае версія (выпуск) 2 гэтага пагаднення або, на ваш выбар, навейшая версія (выпуск) пагаднення.\n\nMediaWiki распаўсюджваецца, спадзеючыся на прыдатнасць прадукта, але БЕЗ ЯКІХ-НЕБУДЗЬ ГАРАНТЫЙ, у тым ліку, без імплікаваных гарантый СПАЖЫВЕЦКАЙ ВАРТАСЦІ або ПРЫДАТНАСЦІ ДЛЯ ЯКОЙ-НЕБУДЗЬ МЭТЫ. Больш падрабязна гл. пагадненне GNU General Public License.\n\nРазам з гэтым праграмным забеспячэннем вы павінны былі атрымаць [{{SERVER}}{{SCRIPTPATH}}/COPYING копію пагаднення GNU General Public License]. Калі гэта не так, паведамце аб гэтым у фонд 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": "MediaWiki з’яўляецца свабодным праграмным забеспячэннем. Такім чынам, вы можаце паўторна распаўсюджваць прадукт і(або) змяняць яго на ўмовах пагаднення GNU General Public License у тым выглядзе, у якім яно публікуецца фондам Free Software Foundation; сілу мае версія (выпуск) 2 гэтага пагаднення або, на ваш выбар, навейшая версія (выпуск) пагаднення.\n\nMediaWiki распаўсюджваецца, спадзеючыся на прыдатнасць прадукта, але <em>БЕЗ ЯКІХ-НЕБУДЗЬ ГАРАНТЫЙ</em>, у тым ліку, без імплікаваных гарантый <strong>СПАЖЫВЕЦКАЙ ВАРТАСЦІ</strong> або <strong>ПРЫДАТНАСЦІ ДЛЯ ЯКОЙ-НЕБУДЗЬ МЭТЫ</strong>. Больш падрабязна гл. пагадненне GNU General Public License.\n\nРазам з гэтым праграмным забеспячэннем вы павінны былі атрымаць [{{SERVER}}{{SCRIPTPATH}}/COPYING копію пагаднення GNU General Public License]. Калі гэта не так, паведамце аб гэтым у фонд 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": "Версія",
        "dberr-outofdate": "Заўважце, што тамтэйшыя індэксы тутэйшага зместу могуць быць састарэлымі.",
        "dberr-cachederror": "Гэта копія старонкі, узятая з кэшу, і, магчыма, састарэлая.",
        "htmlform-invalid-input": "Праблемы з упісаным вамі",
-       "htmlform-select-badoption": "Пададзенае значэнне не з'яўляецца дапушчальным выбарам.",
-       "htmlform-int-invalid": "Пададзенае значэнне не з'яўляецца цэлым лікам.",
-       "htmlform-float-invalid": "Пададзенае значэнне не з'яўляецца лікам.",
+       "htmlform-select-badoption": "Пададзенае значэнне не зяўляецца дапушчальным выбарам.",
+       "htmlform-int-invalid": "Пададзенае значэнне не зяўляецца цэлым лікам.",
+       "htmlform-float-invalid": "Пададзенае значэнне не зяўляецца лікам.",
        "htmlform-int-toolow": "Пададзенае значэнне меншае за мінімум $1",
        "htmlform-int-toohigh": "Пададзенае значэнне большае за максімум $1",
        "htmlform-required": "Гэтае значэнне неабходнае",
        "limitreport-templateargumentsize-value": "$1/$2 {{PLURAL:$2|байт|байты|байтаў}}",
        "limitreport-expansiondepth": "Найбольшая глыбіня разгортвання",
        "limitreport-expensivefunctioncount": "Колькасць працаёмкіх зваротаў да функцый парсера",
+       "limitreport-unstrip-size-value": "$1/$2 {{PLURAL:$2|байт|байты|байтаў}}",
        "expandtemplates": "Разгортванне шаблонаў",
        "expand_templates_intro": "Гэта адмысловая старонка бярэ тэкст і разгортвае ў ім усе шаблоны рэкурсіўна.\nТаксама разгортвае падтрыманыя функцыі парсера кшталту\n<code><nowiki>{{</nowiki>#language:…}}</code> і зменныя віду\n<code><nowiki>{{</nowiki>CURRENTDAY}}</code>.\nФактычна, яна разгортвае ў пэўнай ступені ўсё ў двайных фігурных дужках.",
        "expand_templates_title": "Загаловак старонкі, для {{FULLPAGENAME}} і г.д.:",
        "mw-widgets-mediasearch-input-placeholder": "Пошук мультымедыя",
        "mw-widgets-titleinput-description-new-page": "старонка яшчэ не існуе",
        "mw-widgets-titleinput-description-redirect": "перанакіраванне на $1",
+       "date-range-from": "Ад даты:",
+       "date-range-to": "Да даты:",
        "randomrootpage": "Выпадковая карэнная старонка",
        "log-action-filter-all": "Усе",
        "log-action-filter-block-block": "заблакаваць",
        "cannotauth-not-allowed": "Вам не дазволена выкарыстоўваць гэтую старонку",
        "changecredentials": "Змяненне уліковых дадзеных",
        "changecredentials-submit": "Змяненне уліковых дадзеных",
-       "changecredentials-invalidsubpage": "$1 не з'яўляецца дапушчальным тыпам уліковых дадзеных.",
+       "changecredentials-invalidsubpage": "$1 не зяўляецца дапушчальным тыпам уліковых дадзеных.",
        "changecredentials-success": "Вашы дадзеныя былі змененыя.",
        "removecredentials": "Выдаліць ўліковыя дадзеныя",
        "removecredentials-submit": "Выдаліць ўліковыя дадзеныя",
-       "removecredentials-invalidsubpage": "$1 не з'яўляецца дапушчальным тыпам уліковых дадзеных.",
+       "removecredentials-invalidsubpage": "$1 не зяўляецца дапушчальным тыпам уліковых дадзеных.",
        "removecredentials-success": "Вашы ўліковыя дадзеныя былі выдаленыя.",
        "credentialsform-provider": "Калі ласка, увядзіце ўліковыя дадзеныя:",
        "credentialsform-account": "Імя ўліковага запісу:",
index 9385e48..520d975 100644 (file)
        "difference-multipage": "(পাতাগুলির মধ্যে পার্থক্য)",
        "lineno": "$1 নং লাইন:",
        "compareselectedversions": "নির্বাচিত সংস্করণগুলি তুলনা করুন",
-       "showhideselectedversions": "নিরà§\8dবাà¦\9aিত à¦¸à¦\82শà§\8bধনà¦\97à§\81লি à¦¦à§\87à¦\96াà¦\93/লà§\81à¦\95াà¦\93",
+       "showhideselectedversions": "নিরà§\8dবাà¦\9aিত à¦¸à¦\82শà§\8bধনà¦\97à§\81লি à¦¦à§\87à¦\96ান/লà§\81à¦\95ান",
        "editundo": "পূর্বাবস্থায় ফেরত",
        "diff-empty": "(কোন পার্থক্য নেই)",
        "diff-multi-sameuser": "(একই ব্যবহারকারী দ্বারা সম্পাদিত {{PLURAL:$1|একটি মধ্যবর্তী সংশোধন|$1টি মধ্যবর্তী সংশোধন}} দেখানো হচ্ছে না)",
        "statistics-files": "আপলোডকৃত ফাইল",
        "statistics-edits": "{{SITENAME}} চালু করার পর থেকে পাতার সম্পাদনাসমূহ",
        "statistics-edits-average": "প্রতি পাতার গড় সম্পাদনা",
-       "statistics-users": "নিবন্ধিত [[Special:ListUsers|ব্যবহারকারী]]",
+       "statistics-users": "নিবন্ধিত ব্যবহারকারী",
        "statistics-users-active": "সক্রিয় ব্যবহারকারী",
        "statistics-users-active-desc": "ব্যবহারকারী যারা বিগত {{PLURAL:$1|দিনে|$1 দিনে}} একটি কাজ করেছেন।",
        "pageswithprop": "পাতার বৈশিষ্ট্য সম্বলিত পাতাসমূহ",
        "deadendpages": "যেসব পাতা থেকে কোনো সংযোগ নেই",
        "deadendpagestext": "নিচের পাতাগুলি থেকে {{SITENAME}}-এর অন্য কোন পাতায় সংযোগ নেই।",
        "protectedpages": "সুরক্ষিত পাতাসমূহ",
+       "protectedpages-filters": "ছাঁকনিগুলি:",
        "protectedpages-indef": "শুধুমাত্র অসীম সুরক্ষা",
        "protectedpages-summary": "এই পাতাটি বর্তমানে সুরক্ষিত থাকা বিদ্যমান পাতগুলির তালিকা। সৃষ্টি করা থেকে সুরক্ষিত রয়েছে এমন পাতার তালিকার জন্য, [[{{#special:ProtectedTitles}}|{{int:protectedtitles}}]] দেখুন।",
        "protectedpages-cascade": "শুধুমাত্র প্রপাতাকার সুরক্ষা",
        "rollback-success": "{{GENDER:$3|$1}}-এর সম্পাদনাগুলি পূর্বাবস্থায় ফিরিয়ে নেওয়া হয়েছে; {{GENDER:$4|$2}}-এর করা শেষ সংস্করণে পাতাটি ফেরত নেওয়া হয়েছে।",
        "rollback-success-notify": "$1-এর সম্পাদনাগুলি বাতিল করা হয়েছে; \n$2-এর করা শেষ সংস্করণে ফেরত নেওয়া হয়েছে। [$3 পরিবর্তন দেখুন]",
        "sessionfailure-title": "সেশন পরিত্যক্ত",
-       "sessionfailure": "à¦\86পনার à¦ªà§\8dরবà§\87শ à¦¸à§\87শনà§\87 à¦\8fà¦\95à¦\9fি à¦¸à¦®à¦¸à§\8dযা à¦¹à¦¯à¦¼à§\87à¦\9bà§\87 à¦¬à¦²à§\87 à¦®à¦¨à§\87 à¦¹à¦\9aà§\8dà¦\9bà§\87;\nসà§\87শন à¦¹à¦¾à¦\87à¦\9cà§\8dযাà¦\95 à¦ªà§\8dরতিরà§\8bধà§\87র à¦\89পায় à¦¹à¦¿à¦¸à§\87বà§\87 à¦\8fà¦\87 à¦\95াà¦\9cà¦\9fি à¦¬à¦¾à¦¤à¦¿à¦² à¦\95রা à¦¹à¦¯à¦¼à§\87à¦\9bà§\87।\nà¦\85নà§\81à¦\97à§\8dরহ à¦¬à§\8dরাà¦\89à¦\9cারà§\87র \"পিà¦\9bনà§\87\" à¦¬à§\8bতাম à¦\9aাপà§\81ন à¦\8fবà¦\82 à¦¯à§\87 à¦ªà¦¾à¦¤à¦¾ à¦¥à§\87à¦\95à§\87 à¦\8fসà§\87à¦\9bিলà§\87ন, à¦¤à¦¾ à¦ªà§\81নà¦\83লà§\8bড à¦\95রà§\81ন à¦\8fবà¦\82 à¦\86বার à¦\9aà§\87ষà§\8dà¦\9fা à¦\95রà§\81ন।",
+       "sessionfailure": "à¦\86পনার à¦ªà§\8dরবà§\87শ à¦¸à§\87শনà§\87 à¦\8fà¦\95à¦\9fি à¦¸à¦®à¦¸à§\8dযা à¦¹à¦¯à¦¼à§\87à¦\9bà§\87 à¦¬à¦²à§\87 à¦®à¦¨à§\87 à¦¹à¦\9aà§\8dà¦\9bà§\87;\nসà§\87শন à¦¹à¦¾à¦\87à¦\9cà§\8dযাà¦\95 à¦ªà§\8dরতিরà§\8bধà§\87র à¦\89পায় à¦¹à¦¿à¦¸à§\87বà§\87 à¦\8fà¦\87 à¦\95াà¦\9cà¦\9fি à¦¬à¦¾à¦¤à¦¿à¦² à¦\95রা à¦¹à¦¯à¦¼à§\87à¦\9bà§\87।\nদয়া à¦\95রà§\87 à¦«à¦°à¦®à¦\9fি à¦ªà§\81নরায় à¦\9cমা à¦¦à¦¿ন।",
        "changecontentmodel": "একটি পাতার বিষয়বস্তুর রূপ পরিবর্তন",
        "changecontentmodel-legend": "বিষয়বস্তুর রূপ পরিবর্তন করুন",
        "changecontentmodel-title-label": "পাতার শিরোনাম",
        "version-specialpages": "বিশেষ পাতাসমূহ",
        "version-parserhooks": "পার্সার হুক",
        "version-variables": "চলক",
+       "version-editors": "সম্পাদকগণ",
        "version-antispam": "স্প্যাম প্রতিরোধ",
        "version-other": "অন্য",
        "version-mediahandlers": "মিডিয়া ব্যবস্থাপক",
index 12c68c2..a4fd6dc 100644 (file)
        "cannotlogoutnow-title": "Odjava trenutno nije moguća",
        "cannotlogoutnow-text": "Ne možete se odjaviti kad se koriste $1.",
        "welcomeuser": "Dobro došli, $1",
-       "welcomecreation-msg": "Vaš nalog je napravljen.\nNe zaboravite da prilagodite sebi svoja [[Special:Preferences|{{SITENAME}} podešavanja]].",
+       "welcomecreation-msg": "Vaš račun je napravljen.\nMožete promijeniti [[Special:Preferences|postavke]] ako želite.",
        "yourname": "Korisničko ime:",
        "userlogin-yourname": "Korisničko ime",
        "userlogin-yourname-ph": "Unesite Vaše korisničko ime",
        "nosuchusershort": "Ne postoji korisnik s imenom \"$1\".\nProvjerite jeste li dobro ukucali.",
        "nouserspecified": "Morate izabrati korisničko ime.",
        "login-userblocked": "Ovaj korisnik je blokiran. Prijava nije dopuštena.",
-       "wrongpassword": "Lozinka koju ste unijeli je netačna.\nPokušate ponovno.",
+       "wrongpassword": "Lozinka koju ste unijeli je netačna.\nPokušajte ponovno.",
        "wrongpasswordempty": "Niste upisali lozinku.\nPokušajte ponovo.",
        "passwordtooshort": "Lozinka mora imati najmanje {{PLURAL:$1|1 znak|$1 znaka|$1 znakova}}.",
        "passwordtoolong": "Lozinke ne mogu biti duže od {{PLURAL:$1|jednog znaka|$1 znaka|$1 znakova}}.",
        "savechanges": "Sačuvaj izmjene",
        "publishpage": "Objavi stranicu",
        "publishchanges": "Objavi izmjene",
+       "savearticle-start": "Sačuvaj stranicu…",
+       "savechanges-start": "Sačuvaj izmjene…",
+       "publishpage-start": "Objavi stranicu…",
+       "publishchanges-start": "Objavi izmjene…",
        "preview": "Pregled stranice",
        "showpreview": "Prikaži izgled",
        "showdiff": "Prikaži izmjene",
        "recentchangesdays": "Broj dana za prikaz u nedavnim izmjenama:",
        "recentchangesdays-max": "Najviše $1 {{PLURAL:$1|dan|dana}}",
        "recentchangescount": "Broj izmjena na nedavnim izmjenama:",
-       "prefs-help-recentchangescount": "Ovo uključuje nedavne izmjene, historije stranice i zapisnike.",
+       "prefs-help-recentchangescount": "Najveći broj: 1000",
        "prefs-help-watchlist-token2": "Ovo je tajni ključ sažetka vašeg spiska izmjena. Ko god da ga zna, moći će ga čitati. Ne dijelite ga ni s kim. Ako je potrebno, [[Special:ResetTokens|možete ga ponovo postaviti]].",
        "savedprefs": "Vaše postavke su sačuvane.",
        "savedrights": "Korisničke grupe {{GENDER:$1|korisnika|korisnice}} $1 su sačuvana.",
        "rcfilters-days-show-hours": "$1 {{PLURAL:$1|sat|sata|sati}}",
        "rcfilters-highlighted-filters-list": "Istaknuto: $1",
        "rcfilters-quickfilters": "Sačuvani filteri",
-       "rcfilters-quickfilters-placeholder-title": "Zasad nema sačuvanih linkova",
+       "rcfilters-quickfilters-placeholder-title": "Još nema sačuvanih filtera",
        "rcfilters-quickfilters-placeholder-description": "Da sačuvate postavke filtera da biste ih kasnije ponovo upotrijebili, kliknite na ikonu markera pod \"Aktivni filterima\" ispod.",
        "rcfilters-savedqueries-defaultlabel": "Sačuvani filteri",
        "rcfilters-savedqueries-rename": "Preimenuj",
index a1c7fc7..c14d9f5 100644 (file)
@@ -13,7 +13,8 @@
                        "Ztl8702",
                        "Macofe",
                        "GnuDoyng",
-                       "Davidzdh"
+                       "Davidzdh",
+                       "Suzukaze-c"
                ]
        },
        "tog-underline": "Â-hĕk-siáng lièng-giék",
        "recentchanges-label-newpage": "Cī siŏh bĭk siŭ-gāi cháung-gióng lāu sĭng hiĕk",
        "recentchanges-label-minor": "Cuòi sê siŏh bĭk guó-éu siŭ-gāi",
        "recentchanges-label-bot": "Cuòi sê gĭ-ké-nè̤ng siŭ-gāi gì",
+       "rcfilters-filter-humans-label": "Ìng-lôi (n̂g-sê gĭ-ké-nè̤ng)",
        "rclistfrom": "Hiēng-sê téng $3 $2 gáu dāng gì sĭng gāi-biéng",
        "rcshowhideminor": "$1 guó-éu siŭ-gāi",
        "rcshowhidebots": "$1 gĭ-ké-nè̤ng",
index 7f26366..c818b92 100644 (file)
        "tag-mw-new-redirect": "Керла дӀасахьажорг",
        "tag-mw-removed-redirect": "дӀаяьккхина дӀасхьажорг",
        "tag-mw-changed-redirect-target": "хийцаран бахьна ду дӀасахьажорг",
+       "tag-mw-blank": "цӀанъяр",
        "tag-mw-rollback": "Юхаяккха",
        "tag-mw-undo": "цаоьшу",
        "tags-title": "Билгалонаш",
index 013b8e2..44919fa 100644 (file)
        "statistics-files": "Načtené soubory",
        "statistics-edits": "Počet editací od založení wiki",
        "statistics-edits-average": "Průměrný počet editací na stránku",
-       "statistics-users": "Registrovaní [[Special:ListUsers|uživatelé]]",
+       "statistics-users": "Registrovaní uživatelé",
        "statistics-users-active": "Aktivní uživatelé",
        "statistics-users-active-desc": "Uživatelé, kteří v {{PLURAL:$1|posledním dni|posledních $1 dnech}} provedli nějakou operaci",
        "pageswithprop": "Stránky s vlastností",
        "deadendpages": "Slepé stránky",
        "deadendpagestext": "Následující stránky neodkazují na žádnou jinou stránku {{grammar:2sg|{{SITENAME}}}}.",
        "protectedpages": "Zamčené stránky",
+       "protectedpages-filters": "Filtry:",
        "protectedpages-indef": "Pouze zámky na neurčito",
        "protectedpages-summary": "Tato stránka obsahuje seznam existujících stránek, které jsou momentálně zamčeny. Seznam názvů zamčených proti založení najdete na stránce [[{{#special:ProtectedTitles}}|{{int:protectedtitles}}]].",
        "protectedpages-cascade": "Pouze kaskádové zámky",
        "version-specialpages": "Speciální stránky",
        "version-parserhooks": "Přípojné body syntaktického analyzátoru",
        "version-variables": "Proměnné",
+       "version-editors": "Editory",
        "version-antispam": "Ochrana proti spamu",
        "version-other": "Jiné",
        "version-mediahandlers": "Obsluha médií",
index 22d7192..5909c5d 100644 (file)
        "statistics-files": "Hochgeladene Dateien",
        "statistics-edits": "Seitenbearbeitungen",
        "statistics-edits-average": "Bearbeitungen pro Seite im Durchschnitt",
-       "statistics-users": "Registrierte [[Special:ListUsers|Benutzer]]",
+       "statistics-users": "Angemeldete Benutzer",
        "statistics-users-active": "Aktive Benutzer",
        "statistics-users-active-desc": "Benutzer mit Bearbeitungen {{PLURAL:$1|während der letzten 24 Stunden|während der vergangenen $1 Tage}}",
        "pageswithprop": "Seiten mit einer Seiteneigenschaft",
        "deadendpages": "Nicht verlinkende Seiten",
        "deadendpagestext": "Die folgenden Seiten verweisen nicht auf andere Seiten von {{SITENAME}}.",
        "protectedpages": "Geschützte Seiten",
+       "protectedpages-filters": "Filter:",
        "protectedpages-indef": "Nur unbeschränkt geschützte Seiten zeigen",
        "protectedpages-summary": "Diese Seite listet vorhandene Seiten auf, die derzeit geschützt sind. Für eine Liste vor Erstellung geschützter Titel, siehe „[[{{#special:ProtectedTitles}}|{{int:protectedtitles}}]]“.",
        "protectedpages-cascade": "Nur Seiten mit Kaskadenschutz",
index 1202ecc..2e187cc 100644 (file)
        "redirectedfrom": "(Tót còst al deşvîn da <b>$1</b>)",
        "redirectpagesub": "Pàgina 'd partèinsa",
        "redirectto": "Rimânda a:",
-       "lastmodifiedat": "Ûltmi mudéfichi 'dla pàgina: $2, $1.",
+       "lastmodifiedat": "Cla pàgina ché l'é stêda cambiêda l'ûltma vôlta al $1 a $2 ōr.",
        "viewcount": "Cla pàgina ché l'é stêda lişûda {{PLURAL:$1|'na vôlta|$1 vôlti}}.",
        "protectedpage": "Pàgina sòta prutesiòun",
        "jumpto": "Và a:",
        "nosuchusershort": "An gh'é mìa registrê un utèint ciamê ''$1''. Veréfica al nòm scrét.",
        "nouserspecified": "L'é necesâri precişêr un nòm utèint.",
        "login-userblocked": "Cl'utèinsa ché l'é bluchêda. An n'é pusébil fêr l'ingrès.",
-       "wrongpassword": "La cêv 'd ingrès e-scréta an n'é mìa giósta. Tōrna a pruvêr.",
+       "wrongpassword": "Nòm utèint e cêva 'd ingrès în şbaliêdi. Tōrna a pruvêr.",
        "wrongpasswordempty": "An n'é mìa stê scrét nisóna cêva 'd ingrès. Tōrna pruvêr.",
        "passwordtooshort": "La cêva 'd ingrès la dēv avèir almēno {{PLURAL:$1|1 carâter|$1 carâter}}",
        "passwordtoolong": "La cêva 'd ingrès la 'n pōl mìa avèir pió 'd {{PLURAL:$1|1 carâter|$1 carâter}}",
        "password-login-forbidden": "L'ûş de sté nòm e cêva 'd ingrès l'é stê pruibî.",
        "mailmypassword": "Tōrna mèter la cêva 'd ingrès",
        "passwordremindertitle": "Nōva cêva 'd ingrès pruvişôria per {{SITENAME}}",
-       "passwordremindertext": "Quelchiûn (prubabilmèit té, cun l'indirés IP $1) l'à dmandê de spidîregh 'na nōva cêva 'd ingrès a {{SITENAME}} ($4). 'Na nōva cêva 'd ingrès pruvişôria per l'utèint \"$2\" l'é stêda impustêda a \"$3\". L'é necesâri fêr un ingrès al pió prèst e cambiêr la cêva 'd ingrès subét. La cêva 'd ingrès pruvişôria la scadrà dôp {{PLURAL:$5un dé|$5 dé}}. S' an t'é mia stê té a fêr la dmânda, opór t'é turnê a catêr la vècia cêva 'd ingrès e an 't vō pió cambiêrla, ét pō trascurêr cól mesâg ché e cuntinvêr a druvêr la vècia cêva 'd ingrès.",
+       "passwordremindertext": "Quelchiûn (da l'indirés IP $1) l'à dmandê de spidîregh 'na nōva cêva 'd ingrès a {{SITENAME}} ($4). 'Na nōva cêva 'd ingrès pruvişôria per l'utèint \"$2\" l'é stêda impustêda a \"$3\". L'é necesâri fêr un ingrès al pió prèst e cambiêr la cêva 'd ingrès subét. La cêva 'd ingrès pruvişôria la scadrà dôp {{PLURAL:$5un dé|$5 dé}}. S' an t'é mia stê té a fêr la dmânda, opór t'é turnê a catêr la vècia cêva 'd ingrès e an 't vō pió cambiêrla, ét pō trascurêr cól mesâg ché e cuntinvêr a druvêr la vècia cêva 'd ingrès.",
        "noemail": "Nisûn indirés ed pôsta eletrônica registrê per l'utèint $1.",
        "noemailcreate": "L'é necesâri dêr un 'indirés ed pôsta eletrônica vâlid.",
        "passwordsent": "'Na nōva cêva 'd ingrès l'é stêda spidîda a l'indiré ed pôsta eletrônica per l'utèint \"$1\". Per piaşèir, fà un ingrès apèina 't la ricēv.",
        "preview": "Guêrda préma",
        "showpreview": "Guêrda préma 'd salvêr",
        "showdiff": "Guêrda i cambiamèint",
-       "blankarticle": "<strong>Atèinti:</strong>la pàgina che t'é drē fêr la gh'à gnînto dèinter. S' ét tōren a schisêr in sém a \"$1\", la pàgina la srà fât sèinsa gnînto dèinter.",
+       "blankarticle": "<strong>Atèinti:</strong>la pàgina che t'é drē fêr l'é vōda. S' ét tōren a schisêr in sém a \"$1\", la pàgina la srà fât sèinsa gnînto dèinter.",
        "anoneditwarning": "<strong>Atèinti:</strong> An n'é mìa stê fât l'ingrès. S' ét farê dal mudéfichi al tó indirés IP al srà vést da tót. Se <strong>[$1 và dèinter]</strong> o <strong>[$2 fà 'n' utèinsa]</strong>, al tô mudéfichi a srân sgnêdi al tó nòm utèint, insèm a êter benefési.",
        "anonpreviewwarning": "\"An n'é mìa stê fât l'ingrès. Mèinter es sêlva la pàgina, l'indirés IP al srà sgnê int la stòria 'd la pàgina.\"",
        "missingsummary": "'''Atensiòun:''' an n'é mìa stê precişê al mutîv de sté mudéfica. S'es tōrna a clichêr insém a \"$1\" la mudéfica la gnirà salvêda cun al mutîv vōd.",
        "selfredirect": "<strong>Ateinti:</strong>t'é drē fêr un rinvéi a l'istèsa pàgina. Ét prés avèir şbaliê sgnêr al pôst dal rinvéi o t'é drē mudifichêr la pàgina şbaliêda. S'ét fê cléch incòra in sém a \"$1\", al rinvéi al gnirà fât in tót' al manēri.",
        "missingcommenttext": "Scréver un cumèint ché sòta.",
        "missingcommentheader": "<strong>Atensiòun:<strong> an n'é mìa stê precişê l'argumèint de sté mudéfica. S'es tōrna a clichêr insém a \"$1\" la mudéfica la gnirà salvêda sèinsa.",
-       "summary-preview": "Guêrda préma sûnt:",
+       "summary-preview": "Guêrda la mudéfica che t'é fât:",
        "subject-preview": "Guêrda préma l'argumèint:",
        "previewerrortext": "A gh'é stê 'n erōr mèinter a s'é serchê ed guardêr al lavōr préma 'd salvêrel.",
        "blockedtitle": "Utèint bluchê",
index ca4eed2..8c92710 100644 (file)
        "deadendpages": "Αδιέξοδες σελίδες",
        "deadendpagestext": "Οι σελίδες που ακολουθούν δεν συνδέονται με άλλες σελίδες στο {{SITENAME}}.",
        "protectedpages": "Προστατευμένες σελίδες",
+       "protectedpages-filters": "Φίλτρα",
        "protectedpages-indef": "Προστασίες επαόριστον μόνο",
        "protectedpages-summary": "Αυτή η σελίδα περιέχει υπάρχουσες σελίδες που τώρα είναι προστατευμένες. Για μία λίστα τίτλων που προστατεύονται από τη δημιουργία των σελίδων, δείτε τους [[{{#special:ProtectedTitles}}|Προστατευμένους τίτλους]].",
        "protectedpages-cascade": "Μόνο διαδοχικές προστασίες",
index 350c348..331e00d 100644 (file)
        "deadendpages-summary": "",
        "deadendpagestext": "The following pages do not link to other pages in {{SITENAME}}.",
        "protectedpages": "Protected pages",
+       "protectedpages-filters": "Filters:",
        "protectedpages-indef": "Indefinite protections only",
        "protectedpages-summary": "This page lists existing pages that are currently protected. For a list of titles that are protected from creation, see [[{{#special:ProtectedTitles}}|{{int:protectedtitles}}]].",
        "protectedpages-cascade": "Cascading protections only",
index b7cf815..4e6f188 100644 (file)
        "deadendpages": "Páginas sin salida",
        "deadendpagestext": "Las siguientes páginas no enlazan a otras páginas de {{SITENAME}}.",
        "protectedpages": "Páginas protegidas",
+       "protectedpages-filters": "Filtros:",
        "protectedpages-indef": "Solo protecciones indefinidas",
        "protectedpages-summary": "Esta página enumera las páginas existentes que actualmente están protegidas. Para obtener una lista de títulos que están protegidos desde su creación, véase [[{{#special:ProtectedTitles}}|{{int:protectedtitles}}]].",
        "protectedpages-cascade": "Solo protecciones en cascada",
index 3705666..f985b80 100644 (file)
@@ -29,7 +29,8 @@
                        "Macofe",
                        "Adeliine",
                        "Metsavend",
-                       "Cumbril"
+                       "Cumbril",
+                       "Ilmarine"
                ]
        },
        "tog-underline": "Linkide allakriipsutus:",
@@ -38,7 +39,7 @@
        "tog-newpageshidepatrolled": "Peida uute lehtede loendis kontrollitud leheküljed",
        "tog-hidecategorization": "Peida lehekülgede kategoriseerimine",
        "tog-extendwatchlist": "Laienda jälgimisloendit, et näha kõiki muudatusi, mitte vaid kõige värskemaid",
-       "tog-usenewrc": "Rühmita viimased muudatused ja muudatused jälgimisloendis lehekülje järgi",
+       "tog-usenewrc": "Rühmita viimased muudatused ja muudatuste jälgimisloend lehekülje järgi",
        "tog-numberheadings": "Pealkirjade automaatnummerdus",
        "tog-showtoolbar": "Näita redigeerimise tööriistariba",
        "tog-editondblclick": "Redigeeri lehekülgi topeltklõpsu peale",
index 521f98e..470c675 100644 (file)
        "autosumm-replace": "Orriaren edukiaren ordez, «$1» jarri da",
        "autoredircomment": "«[[$1]]» orrira birzuzendua",
        "autosumm-removed-redirect": "[[$1]]-ra birbideraketa ezabatua",
-       "autosumm-changed-redirect-target": "Birbideraketa helburua [[$1]]-tik [[$2]]-ra aldatu da",
+       "autosumm-changed-redirect-target": "Birbideraketaren helburua «[[$1]]» orritik «[[$2]]» orrira aldatu da",
        "autosumm-new": "Orria sortu da. Edukia: $1",
        "autosumm-newblank": "Orrialde zuria sortu da",
        "lag-warn-normal": "{{PLURAL:$1|segundu $1|$1 segundu}} baino berriagoak diren aldaketak ez dira zerrenda honetan agertuko.",
        "tag-mw-new-redirect-description": "Birbideratze berri bat sortzen duten aldaketak edo birbidaltzeko orrialdea aldatzen dutenak",
        "tag-mw-removed-redirect": "Birbideraketa ezabatua",
        "tag-mw-removed-redirect-description": "Existitzen den birbidaltze bati ez birbidaltzeko bihurtzen duten aldaketak",
-       "tag-mw-changed-redirect-target": "Birbideraketa helburua aldatu egin da",
+       "tag-mw-changed-redirect-target": "Birbideraketaren helburua aldatu da",
        "tag-mw-changed-redirect-target-description": "Birbideraketa baten helburua eraldatzen duten aldaketak",
        "tag-mw-blank": "Husten",
        "tag-mw-blank-description": "Orria zuriz jartzen duten aldaketak",
index 7ccb363..092695e 100644 (file)
        "statistics-files": "Tallennettuja tiedostoja",
        "statistics-edits": "Muokkauksia {{GRAMMAR:genitive|{{SITENAME}}}} perustamisen jälkeen",
        "statistics-edits-average": "Muokkausten keskiarvo yhdellä sivulla",
-       "statistics-users": "Rekisteröityneitä [[Special:ListUsers|käyttäjiä]]",
+       "statistics-users": "Rekisteröityneitä käyttäjiä",
        "statistics-users-active": "Aktiivisia käyttäjiä",
        "statistics-users-active-desc": "Käyttäjät, jotka ovat suorittaneet jonkin toiminnon {{PLURAL:$1|edellisen päivän|edellisten $1 päivän}} aikana.",
        "pageswithprop": "Sivut sivun ominaisuuden mukaan",
        "deadendpages": "Sivut, joilla ei ole linkkejä",
        "deadendpagestext": "Seuraavat sivut eivät linkitä muihin sivuihin wikissä.",
        "protectedpages": "Suojatut sivut",
+       "protectedpages-filters": "Suodattimet:",
        "protectedpages-indef": "Vain ikuisesti suojatut",
        "protectedpages-summary": "Tällä sivulla on lueteltu tällä hetkellä suojatut sivut. Nähdäksesi luettelon sivuista, jotka on suojattu uudelleenluonnilta, katso [[{{#special:ProtectedTitles}}|{{int:protectedtitles}}]].",
        "protectedpages-cascade": "Vain tarttuvasti suojatut",
        "limitreport-templateargumentsize-value": "$1/$2 {{PLURAL:$2|tavu|tavua}}",
        "limitreport-expansiondepth": "Suurin laajennussyvyys",
        "limitreport-expensivefunctioncount": "Vaativien jäsenninfunktioiden lukumäärä",
+       "limitreport-unstrip-depth": "Unstrip-rekursion syvyys",
+       "limitreport-unstrip-size": "Unstrip laajennuksen jälkeinen koko",
        "limitreport-unstrip-size-value": "$1/$2 {{PLURAL:$2|tavu|tavua}}",
        "expandtemplates": "Laajenna mallineet",
        "expand_templates_intro": "Tämä toimintosivu ottaa syötteeksi wikitekstiä ja laajentaa kaikki siinä olevat mallineet rekursiivisesti.\nSe myös laajentaa tuetut parserifunktiot kuten\n<code><nowiki>{{</nowiki>#language:...}}</code> ja -muuttujat kuten\n<code><nowiki>{{</nowiki>CURRENTDAY}}</code>.\nKäytännössä se laajentaa melkein kaiken, joka on kaksoisaaltosulkeiden sisällä.",
index 2c38e61..fea4aa5 100644 (file)
        "userjsonyoucanpreview": "<strong>Conseil :</strong> Utiliser le bouton « {{int:showpreview}} » pour tester votre nouveau JSON avant enregistrement.",
        "userjsyoucanpreview": "<strong>Astuce :</strong> utilisez le bouton « {{int:showpreview}} » pour tester votre nouvelle feuille JavaScript avant de l’enregistrer.",
        "usercsspreview": "<strong>Rappelez-vous que vous ne faites que prévisualiser votre propre feuille CSS. \nElle n’a pas encore été enregistrée !</strong>",
-       "userjsonpreview": "<strong>Rappelez-vous que vous êtes seulement en train de tester/faire un aperçu de votre configuration utilisateur JSON.\nElle n’a pas encore été enregistrée !</strong>",
+       "userjsonpreview": "<strong>Rappelez-vous que vous êtes seulement en train de tester/voir un aperçu de votre configuration utilisateur JSON.\nElle n’a pas encore été enregistrée !</strong>",
        "userjspreview": "<strong>Rappelez-vous que vous ne faites que visualiser ou tester votre code JavaScript.\nIl n’a pas encore été enregistré !</strong>",
        "sitecsspreview": "<strong>Rappelez-vous que vous ne faites que prévisualiser cette feuille de style. \nElle n’a pas encore été enregistrée !</strong>",
        "sitejsonpreview": "<strong>Souvenez-vous que vous ne faites que regarder un aperçu de cette configuration JSON.\nElle n’a pas encore été enregistrée !</strong>",
        "rcfilters-filter-reviewstatus-unpatrolled-label": "Non patrouillé",
        "rcfilters-filter-reviewstatus-manual-description": "Modifications manuellement marquées comme patrouillées.",
        "rcfilters-filter-reviewstatus-manual-label": "Patrouillé manuellement",
-       "rcfilters-filter-reviewstatus-auto-description": "Modifications par des utilisateurs avancés dont le travail est marqué comme patrouillé automatiquement",
+       "rcfilters-filter-reviewstatus-auto-description": "Modifications par des utilisateurs avancés dont le travail est marqué comme patrouillé automatiquement.",
        "rcfilters-filter-reviewstatus-auto-label": "Patrouillé automatiquement",
        "rcfilters-filtergroup-significance": "Signification",
        "rcfilters-filter-minor-label": "Modifications mineures",
        "statistics-files": "Fichiers importés",
        "statistics-edits": "Modifications de pages depuis l'installation de {{SITENAME}}",
        "statistics-edits-average": "Nombre moyen de modifications par page",
-       "statistics-users": "[[Special:ListUsers|Utilisateurs]] enregistrés",
+       "statistics-users": "Utilisateurs inscrits",
        "statistics-users-active": "Utilisateurs actifs",
        "statistics-users-active-desc": "Utilisateurs ayant fait au moins une action {{PLURAL:$1|il y a un jour|pendant les $1 derniers jours}}",
        "pageswithprop": "Pages avec une propriété de page",
        "deadendpages": "Pages en impasse",
        "deadendpagestext": "Les pages suivantes ne contiennent aucun lien vers d'autres pages dans le wiki {{SITENAME}}.",
        "protectedpages": "Pages protégées",
+       "protectedpages-filters": "Filtres :",
        "protectedpages-indef": "Uniquement les protections indéfinies",
        "protectedpages-summary": "Cette page liste les pages existantes actuellement protégées. Pour une liste des titres protégés contre la création, voir [[{{#special:ProtectedTitles}}|{{int:protectedtitles}}]].",
        "protectedpages-cascade": "Uniquement les protections en cascade",
index 8fd4712..1c65c40 100644 (file)
        "deadendpages": "Páxinas sen ligazóns cara a outras",
        "deadendpagestext": "Estas páxinas non ligan con ningunha outra páxina de {{SITENAME}}.",
        "protectedpages": "Páxinas protexidas",
+       "protectedpages-filters": "Filtros:",
        "protectedpages-indef": "Só as proteccións indefinidas",
        "protectedpages-summary": "Esta páxina lista as páxinas existentes que están protexidas actualmente. Para obter unha lista de páxinas cuxa creación está prohibida, consulte [[{{#special:ProtectedTitles}}|{{int:protectedtitles}}]].",
        "protectedpages-cascade": "Só as proteccións en serie",
        "version-specialpages": "Páxinas especiais",
        "version-parserhooks": "Asociadores analíticos",
        "version-variables": "Variables",
+       "version-editors": "Editores",
        "version-antispam": "Prevención contra spam",
        "version-other": "Outros",
        "version-mediahandlers": "Manipuladores de ficheiros multimedia",
index f854dce..f12a6af 100644 (file)
        "missing-article": "בסיס הנתונים לא מצא את הטקסט של הדף שהוא היה אמור למצוא, בשם \"$1\" $2.\n\nזה נגרם בדרך־כלל עקב לחיצה על קישור ישן לגרסה של דף שנמחק.\n\nאם זה אינו המקרה, זהו כנראה באג בתוכנה.\nנא לדווח על כך ל[[Special:ListUsers/sysop|מפעיל מערכת]], תוך שמירת פרטי כתובת ה־URL.",
        "missingarticle-rev": "(מספר גרסה: $1)",
        "missingarticle-diff": "(השוואת הגרסאות: $1, $2)",
-       "readonly_lag": "בסיס הנתונים ננעל אוטומטית כדי לאפשר לבסיסי הנתונים המשניים להתעדכן מהבסיס הראשי.",
+       "readonly_lag": "בסיס הנתונים ננעל אוטומטית כדי לאפשר לבסיסי הנתונים המשניים להתעדכן מהבסיס הראשי",
        "nonwrite-api-promise-error": "כותרת ה־HTTP‏ 'Promise-Non-Write-API-Action' נשלחה, אבל הבקשה הייתה למודול כתיבה של API.",
        "internalerror": "שגיאה פנימית",
        "internalerror_info": "שגיאה פנימית: $1",
        "badtitle": "כותרת שגויה",
        "badtitletext": "כותרת הדף המבוקש הייתה בלתי־תקינה, ריקה, או קישור שגוי לשפה אחרת או למיזם אחר.\nייתכן שהיא מכילה תו אחד או יותר שאינו יכול לשמש בכותרות.",
        "title-invalid-empty": "כותרת הדף המבוקש ריקה או מכילה רק שם של מרחב שם.",
-       "title-invalid-utf8": "כותרת הדף המבוקש מכילה רצף UTF-8 בלתי תקין.",
+       "title-invalid-utf8": "כותרת הדף המבוקש מכילה רצף UTF-8 בלתי־תקין.",
        "title-invalid-interwiki": "כותרת הדף המבוקש מכילה קישור בינוויקי, שלא ניתן להשתמש בו בכותרות.",
        "title-invalid-talk-namespace": "כותרת הדף המבוקש מפנה לדף שיחה שאינו יכול להתקיים.",
        "title-invalid-characters": "כותרת הדף המבוקש מכילה תווים בלתי־תקינים: \"$1\".",
        "exception-nologin-text-manual": "נדרשת $1 כדי לראות את הדף הזה או לבצע את הפעולה הזאת.",
        "virus-badscanner": "הגדרות שגויות: סורק הווירוסים אינו ידוע: <em>$1</em>",
        "virus-scanfailed": "הסריקה נכשלה (קוד: $1)",
-       "virus-unknownscanner": "אנטי־וירוס בלתי ידוע:",
+       "virus-unknownscanner": "אנטי־וירוס בלתי־ידוע:",
        "logouttext": "<strong>יצאתם מהחשבון.</strong>\n\nשימו לב שייתכן שדפים מסוימים ימשיכו להיות מוצגים כאילו אתם עדיין מחוברים לחשבון, עד שתנקו את המטמון של הדפדפן שלכם.",
        "cannotlogoutnow-title": "לא ניתן לצאת מהחשבון עכשיו",
        "cannotlogoutnow-text": "היציאה מהחשבון אינה אפשרית בעת שימוש ב{{GRAMMAR:תחילית|$1}}.",
        "resetpass_forbidden": "לא ניתן לשנות סיסמאות",
        "resetpass_forbidden-reason": "לא ניתן לשנות את הסיסמאות: $1",
        "resetpass-no-info": "נדרשת כניסה לחשבון כדי לגשת לדף זה באופן ישיר.",
-       "resetpass-submit-loggedin": "שינוי סיסמה",
+       "resetpass-submit-loggedin": "ש×\99× ×\95×\99 ×\94ס×\99ס×\9e×\94",
        "resetpass-submit-cancel": "ביטול",
        "resetpass-wrong-oldpass": "הסיסמה הזמנית או הנוכחית אינה תקינה.\nייתכן שכבר שינית את סיסמתך או שכבר ביקשת סיסמה זמנית חדשה.",
        "resetpass-recycled": "יש לאפס את הסיסמה לסיסמה השונה מסימסתך הנוכחית.",
        "diff-multi-sameuser": "({{PLURAL:$1|גרסת ביניים אחת|$1 גרסאות ביניים}} של אותו משתמש {{PLURAL:$1|אינה מוצגת|אינן מוצגות}})",
        "diff-multi-otherusers": "({{PLURAL:$1|גרסת ביניים אחת|$1 גרסאות ביניים}} של {{PLURAL:$2|משתמש אחר אחד|$2 משתמשים}} {{PLURAL:$1|אינה מוצגת|אינן מוצגות}})",
        "diff-multi-manyusers": "({{PLURAL:$1|גרסת ביניים אחת|$1 גרסאות ביניים}} של יותר {{PLURAL:$2|ממשתמש אחד|מ־$2 משתמשים}} {{PLURAL:$1|אינה מוצגת|אינן מוצגות}})",
-       "diff-paragraph-moved-tonew": "×\94פ×\99סק×\94 ×\94×\95×¢×\91ר×\94. × ×\99ת×\9f ×\9c×\9c×\97×\95×¥ ×\9b×\90×\9f ×\9b×\93×\99 ×\9c×¢×\91×\95ר ×\9c×\9e×\99ק×\95×\9e×\94 ×\94×\97×\93ש.",
-       "diff-paragraph-moved-toold": "×\94פ×\99סק×\94 ×\94×\95×¢×\91ר×\94. × ×\99ת×\9f ×\9c×\9c×\97×\95×¥ ×\9b×\90×\9f ×\9b×\93×\99 ×\9c×¢×\91×\95ר ×\9c×\9e×\99ק×\95×\9e×\94 ×\94×\99ש×\9f.",
+       "diff-paragraph-moved-tonew": "הפסקה הועברה. ניתן ללחוץ כאן כדי לעבור למיקומה החדש.",
+       "diff-paragraph-moved-toold": "הפסקה הועברה. ניתן ללחוץ כאן כדי לעבור למיקומה הישן.",
        "difference-missing-revision": "{{PLURAL:$2|גרסה אחת|$2 גרסאות}} מתוך הגרסאות שביקשת להשוות ($1) {{PLURAL:$2|לא נמצאה|לא נמצאו}}.\n\nזה נגרם בדרך־כלל עקב לחיצה על קישור ישן להבדלים בין גרסאות של דף שנמחק.\nאפשר למצוא פרטים ב[{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} יומן המחיקות].",
        "searchresults": "תוצאות החיפוש",
        "searchresults-title": "תוצאות החיפוש \"$1\"",
        "powersearch-togglenone": "אף לא אחד",
        "powersearch-remember": "שמירת הבחירה עבור חיפושים עתידיים",
        "search-external": "חיפוש חיצוני",
-       "searchdisabled": "×\97×\99פ×\95ש ×\91{{grammar:ת×\97×\99×\9c×\99ת|{{SITENAME}}}} ×\90×\99× ×\95 ×\9e×\95פע×\9c ×\9bעת.\n×\91×\99נת×\99×\99×\9d ×\90פשר ×\9c×\97פש ×\91×\90×\9eצע×\95ת ×\92×\95×\92×\9c.\nש×\99×\9e×\95 ×\9c×\91 שייתכן שהמידע של {{SITENAME}} שם אינו מעודכן.",
+       "searchdisabled": "×\97×\99פ×\95ש ×\91{{grammar:ת×\97×\99×\9c×\99ת|{{SITENAME}}}} ×\90×\99× ×\95 ×\9e×\95פע×\9c ×\9bעת.\n×\91×\99נת×\99×\99×\9d ×\90פשר ×\9c×\97פש ×\91×\90×\9eצע×\95ת ×\92×\95×\92×\9c.\n×\99ש ×\9cש×\99×\9d ×\9c×\91 ×\9c×\9b×\9a שייתכן שהמידע של {{SITENAME}} שם אינו מעודכן.",
        "search-error": "אירעה שגיאה במהלך החיפוש: $1",
        "search-warning": "אירעה אזהרה במהלך החיפוש: $1",
        "preferences": "העדפות",
        "statistics-files": "קבצים שהועלו",
        "statistics-edits": "עריכות של דפים מאז התקנת {{SITENAME}}",
        "statistics-edits-average": "מספר העריכות הממוצע לדף",
-       "statistics-users": "ה[[Special:ListUsers|משתמשים]] הרשומים",
+       "statistics-users": "המשתמשים הרשומים",
        "statistics-users-active": "המשתמשים הפעילים",
        "statistics-users-active-desc": "משתמשים שביצעו פעולה כלשהי {{PLURAL:$1|ביום האחרון|ביומיים האחרונים|ב־$1 הימים האחרונים}}",
        "pageswithprop": "דפים עם מאפיין דף",
        "deadendpages": "דפים ללא קישורים",
        "deadendpagestext": "הדפים הבאים אינם מקשרים לדפים אחרים באתר {{SITENAME}}.",
        "protectedpages": "דפים מוגנים",
+       "protectedpages-filters": "מסננים:",
        "protectedpages-indef": "הגנות ללא הגבלת זמן בלבד",
        "protectedpages-summary": "בדף זה רשומים הדפים הקיימים שמוגנים כרגע. לרשימת הכותרות שמוגנות מפני יצירה, ראו [[{{#special:ProtectedTitles}}|{{int:protectedtitles}}]].",
        "protectedpages-cascade": "הגנות מדורגות בלבד",
        "unlinkaccounts": "ביטול הקישור של החשבונות",
        "unlinkaccounts-success": "קישור החשבון בוטל.",
        "authenticationdatachange-ignored": "השינוי בנתוני האימות לא הצליח. ייתכן שלא הוגדר ספק.",
-       "userjsispublic": "ש×\99×\9e×\95 ×\9c×\91: ×\9eשת×\9eש×\99×\9d ×\90×\97ר×\99×\9d ×\99×\9b×\95×\9c×\99×\9d ×\9cצפ×\95ת ×\91×\93פ×\99 ×\94Ö¾JavaScript ×©×\9c×\9b×\9d, ולכן אין לכלול בהם מידע סודי.",
-       "userjsonispublic": "ש×\99×\9e×\95 ×\9c×\91: ×\9eשת×\9eש×\99×\9d ×\90×\97ר×\99×\9d ×\99×\9b×\95×\9c×\99×\9d ×\9cצפ×\95ת ×\91×\93פ×\99 ×\94Ö¾JSON ×©×\9c×\9b×\9d, ולכן אין לכלול בהם מידע סודי.",
-       "usercssispublic": "ש×\99×\9e×\95 ×\9c×\91: ×\9eשת×\9eש×\99×\9d ×\90×\97ר×\99×\9d ×\99×\9b×\95×\9c×\99×\9d ×\9cצפ×\95ת ×\91×\93פ×\99 ×\94Ö¾CSS ×©×\9c×\9b×\9d, ולכן אין לכלול בהם מידע סודי.",
+       "userjsispublic": "×\9cתש×\95×\9eת ×\9c×\91×\9a: ×\9eשת×\9eש×\99×\9d ×\90×\97ר×\99×\9d ×\99×\9b×\95×\9c×\99×\9d ×\9cצפ×\95ת ×\91×\93פ×\99 ×\94Ö¾JavaScript ×©×\9c×\9a, ולכן אין לכלול בהם מידע סודי.",
+       "userjsonispublic": "×\9cתש×\95×\9eת ×\9c×\91×\9a: ×\9eשת×\9eש×\99×\9d ×\90×\97ר×\99×\9d ×\99×\9b×\95×\9c×\99×\9d ×\9cצפ×\95ת ×\91×\93פ×\99 ×\94Ö¾JSON ×©×\9c×\9a, ולכן אין לכלול בהם מידע סודי.",
+       "usercssispublic": "×\9cתש×\95×\9eת ×\9c×\91×\9a: ×\9eשת×\9eש×\99×\9d ×\90×\97ר×\99×\9d ×\99×\9b×\95×\9c×\99×\9d ×\9cצפ×\95ת ×\91×\93פ×\99 ×\94Ö¾CSS ×©×\9c×\9a, ולכן אין לכלול בהם מידע סודי.",
        "restrictionsfield-badip": "כתובת או טווח כתובות IP בלתי תקין: $1",
        "restrictionsfield-label": "טווחי כתובות IP מותרים:",
        "restrictionsfield-help": "כתובת IP אחת או טווח CIDR אחד בשורה. כדי לאפשר את הכול, ניתן להשתמש ב:<pre>0.0.0.0/0\n::/0</pre>",
index f18a583..16d7b20 100644 (file)
        "cascadeprotected": "Daytoy a panid ket nasalaknibanen manipud iti panagurnos gapu ta nailak-am {{PLURAL:$1|iti sumaganad a panid|kadagiti sumaganad a panid}} a nasalakniban iti nalukatan a pagpilian ti \"sariap\":\n$2",
        "namespaceprotected": "Awan ti pammalubosmo nga agurnos kadagiti panid iti nagan ti espasio ti <strong>$1</strong>.",
        "customcssprotected": "Awan ti pammalubosmo nga agurnos iti daytoy panid ti CSS, ngamin ket naglaon ti personal a pannakaisaad iti sabali agar-aramat.",
+       "customjsonprotected": "Awan ti pammalubosmo nga agurnos iti daytoy panid ti JSON ngamin ket naglaon ti personal a pannakaisaad iti sabali agar-aramat.",
        "customjsprotected": "Awan ti pammalubosmo nga agurnos iti daytoy a panid ti JavaScript, ngamin ket naglaon ti personal a pannakaisaad iti sabali agar-aramat.",
        "mycustomcssprotected": "Awan pammalubosmo nga agurnos iti daytoy a panid ti CSS.",
+       "mycustomjsonprotected": "Awan pammalubosmo nga agurnos iti daytoy a panid ti JSON.",
        "mycustomjsprotected": "Awan pammalubosmo nga agurnos iti daytoy a panid ti JavaScript.",
        "myprivateinfoprotected": "Awan pammalubosmo nga agurnos iti pribado a pakaammom.",
        "mypreferencesprotected": "Awan pammalubosmo nga agurnos kadagiti kakaykayatam.",
        "nosuchusershort": "Awan ti agar-aramat nga agnagan iti \"$1\".\nKitaem ti panangiletram.",
        "nouserspecified": "Nasken nga inaganam ti nagan ti agar-aramat.",
        "login-userblocked": "Naserraan daytoy nga agar-aramat. Saan a mapalubosan ti sumrek.",
-       "wrongpassword": "Saan a husto ti naikabil a kontrasenias. \nPangngaasi a padasen manen.",
+       "wrongpassword": "Saan a husto ti naikabil a nagan ti agar-aramat wenno kontrasenias. \nPangngaasi a padasen manen.",
        "wrongpasswordempty": "Blanko ti naikabil a kontrasenias. \nPangngaasi a padasen manen.",
        "passwordtooshort": "Dagiti kontrasenias ket nasken a saan a basbasit ngem {{PLURAL:$1|1 a karakter|$1 a karkarakter}}.",
        "passwordtoolong": "Dagiti kontrasenias ket nasken a saan nga at-atiddog ngem {{PLURAL:$1|1 a karakter|$1 a karkarakter}}.",
-       "passwordtoopopular": "Saan a mabalin a mausar dagiti kadawyan a mapilpili a kontrasenias. Pangngaasi nga agpili iti naisangsangayan a kontrasenias.",
+       "passwordtoopopular": "Saan a mabalin a mausar dagiti kadawyan a mapilpili a kontrasenias. Pangngaasi nga agpili iti kontrasenias a narigrigat a mapugtuan.",
        "password-name-match": "Nasken a ti kontrasenias ket maigiddiat manipud iti naganmo.",
        "password-login-forbidden": "Naipariten ti panagusar iti daytoy a nagan ti agar-aramat ken kontrasenias.",
        "mailmypassword": "Isaad manen ti kontrasenias",
        "passwordremindertitle": "Baro a temporario a kontrasenias para iti {{SITENAME}}",
-       "passwordremindertext": "Adda maysa a tao (mabalin a sika met laeng, manipud iti adres ti IP ti $1) ket nagkiddaw iti baro a kontrasenias para iti {{SITENAME}} ($4). Ti temporario a kontrasenias para kenni agar-aramat \"$2\" ket napartuaten ken naisaad iti \"$3\". No kastan ti kinayatmo, nasken itan a sumrekka ken agpili iti baro a kontrasenias.\nTi temporario a kontraseniasmo ket agpaso {{PLURAL:$5|iti maysa nga aldaw|kadagiti $5 nga aldaw}}.\n\nNo sabali ti nagkiddaw, wenno nalagipmon ti kontraseniasmo,\nken dimo kayaten a sukatan daytoy, mabalinmo a di ikaskaso daytoy a mensahe ken agtuloy nga usaren ti daan a kontraseniasmo.",
+       "passwordremindertext": "Adda maysa a tao (manipud iti adres ti IP iti $1) ket nagkiddaw iti baro a kontrasenias para iti {{SITENAME}} ($4). Ti temporario a kontrasenias para kenni agar-aramat \"$2\" ket napartuaten ken naisaad iti \"$3\". No kastan ti kinayatmo, nasken itan a sumrekka ken agpili iti baro a kontrasenias.\nTi temporario a kontraseniasmo ket agpaso {{PLURAL:$5|iti maysa nga aldaw|kadagiti $5 nga aldaw}}.\n\nNo sabali ti nagkiddaw, wenno nalagipmon ti kontraseniasmo,\nken dimo kayaten a sukatan daytoy, mabalinmo a di ikaskaso daytoy a mensahe ken agtuloy nga usaren ti daan a kontraseniasmo.",
        "noemail": "Awan ti adres ti esurat a nairehistro para kenni agar-aramat \"$1\".",
        "noemailcreate": "Nasken a mangitedka iti umiso nga adres ti esurat.",
        "passwordsent": "Naipatuloden ti baro a kontrasenias iti adres ti esurat a nairehistro kenni \"$1\".\nPangngaasi a sumrekka manen kalpasan iti pannakaawatmo.",
        "botpasswords-insert-failed": "Napaay iti pananginayon ti nagan ti bot iti \"$1\". Nainayon kadi idin?",
        "botpasswords-update-failed": "Napaay iti panagpabaro ti nagan ti bot iti \"$1\". Naikkat kadi idin?",
        "botpasswords-created-title": "Napartuat ti kontrasenias ti bot",
-       "botpasswords-created-body": "Napartuat ti kontrasenias ti bot para iti nagan ti bot iti \"$1\" ni agar-aramat \"$2\".",
+       "botpasswords-created-body": "Napartuat ti kontrasenias ti bot para iti nagan ti bot iti \"$1\" ni {{GENDER:$2|agar-aramat}} \"$2\".",
        "botpasswords-updated-title": "Napabaro ti kontrasenias ti bot",
-       "botpasswords-updated-body": "Napabaro ti kontrasenias ti bot para iti nagan ti bot iti \"$1\" ni agar-aramat \"$2\".",
+       "botpasswords-updated-body": "Napabaro ti kontrasenias ti bot para iti nagan ti bot iti \"$1\" ni {{GENDER:$2|agar-aramat}} \"$2\".",
        "botpasswords-deleted-title": "Naikkat ti kontrasenias ti bot",
-       "botpasswords-deleted-body": "Naikkat ti kontrasenias ti bot para iti nagan ti bot iti \"$1\" ni agar-aramat \"$2\".",
+       "botpasswords-deleted-body": "Naikkat ti kontrasenias ti bot para iti nagan ti bot iti \"$1\" ni {{GENDER:$2|agar-aramat}} \"$2\".",
        "botpasswords-newpassword": "Ti baro a kontrasenias iti panagserrek iti <strong>$1</strong> ket <strong>$2</strong>. <em>Pangngaasi nga irekord daytoy para iti masakbayan a reperensia.</em> <br> (Para kadagiti daan a bot a makasapul iti nagan iti panagserrek a kapada koma ti kanungpalan a nagan ti agar-aramat, mabalinmo pay ti agusar ti <strong>$3</strong> a kas nagan ti <strong>$4</strong> a kas kontrasenias.)",
        "botpasswords-no-provider": "Saan a magun-od ti BotPasswordsSessionProvider.",
        "botpasswords-restriction-failed": "Ti panangigawid ti kontrasenias ti bot ket nangpawil iti daytoy a panagserrek.",
        "savechanges": "Idulin dagiti binaliwan",
        "publishpage": "Ipablaak ti panid",
        "publishchanges": "Ipablaak dagiti binaliwan",
+       "savearticle-start": "Idulin ti panid...",
+       "savechanges-start": "Idulin dagiti binaliwan...",
+       "publishpage-start": "Ipablaak ti panid...",
+       "publishchanges-start": "Ipablaak dagiti binaliwan...",
        "preview": "Ipadas",
        "showpreview": "Ipakita ti ipadas",
        "showdiff": "Ipakita dagiti binaliwan",
        "anonpreviewwarning": "<em>Saanka a nakastrek. Ti panagidulin ket agirehistro ti IP a pagtaengam kadagitoy a pakasaritaan ti panagurnos iti daytoy a panid.</em>",
        "missingsummary": "<strong>Palagip:</strong> Saanka a nakaited iti pakabuklan ti panagurnos.\nNo pindutem manen ti \"$1\", maidulin ti inurnosmo nga awan ti pakabuklanna.",
        "selfredirect": "<strong>Ballaag:</strong> Ibawbaw-ingmo daytoy a panid iti isu met laeng a panid.\nMabalinmo nga innaganan ti kamali a puntaan para iti baw-ing, wenno mabalin nga ur-urnosem ti kamali a panid.\nNo pindutem manen ti \"$1\" , mapartuatto lattan ti baw-ing.",
-       "missingcommenttext": "Pangngaasi nga agikabil ti komentario dita baba.",
+       "missingcommenttext": "Pangngaasi nga agikabil iti komentario.",
        "missingcommentheader": "<strong>Palagip:</strong> Saanka pay a nakaited iti suheto para iti daytoy a komentario.\nNo pindutem manen ti \"$1\", maidulinto ti inurnosmo nga awan ti pakabuklanna.",
        "summary-preview": "Panangipadas ti pakabuklan ti panagurnos:",
        "subject-preview": "Panangipadas ti suheto:",
        "userjspreview": "<strong>Laglagipem a subsubokam/ipadpadasmo ti bukodmo a JavaScript ti agar-aramat.\nSaan pay a naidulin!</strong>",
        "sitecsspreview": "<strong>Laglagipem nga ipadpadasmo laeng daytoy a CSS.\nSaan pay a naidulin!</strong>",
        "sitejspreview": "<strong>Laglagipem nga ipadpadasmo laeng daytoy a kodigo ti JavaScript.\nSaan pay nga naidulin!</strong>",
-       "userinvalidconfigtitle": "<strong>Ballaag:</strong> Awan ti kudil a \"$1\".\nDagiti panid ti naiduma a .css ken .js ket agus-usar iti titulo ti bassit a letra, kas ti {{ns:user}}:Foo/vector.css saan a kas ti {{ns:user}}:Foo/Vector.css.",
+       "userinvalidconfigtitle": "<strong>Ballaag:</strong> Awan ti kudil a \"$1\".\nDagiti panid ti naiduma a .css, .json, ken .js  ket agus-usar iti titulo ti bassit a letra, kas ti {{ns:user}}:Foo/vector.css saan a kas ti {{ns:user}}:Foo/Vector.css.",
        "updated": "(Napabaro)",
        "note": "<strong>Nota:</strong>",
        "previewnote": "<strong>Laglagipem a daytoy ket panagipadas laeng.</strong>\nDagiti sinukatam ket saan pay a naidulin!",
        "longpageerror": "<strong>Biddut: Ti teksto nga intedmo ket {{PLURAL:$1|maysa a kilobyte|$1 kilkilobyte}} ti katiddogna, nga at-atiddog ngem ti kangatuan iti  {{PLURAL:$2|maysa a kilobyte|$2 kilkilobyte}}.</strong>\nSaan a mabalin a maidulin.",
        "readonlywarning": "<strong>Ballaag: Narikepan ti database tapno mataripato, isu a saanmo a mabalin nga idulin dagita inurnosmo tattan.</strong>\nMabalinmo ti agkopia ken agipegket ti tekstom iti papeles ti teksto ken idulinmo daytoy intono madamdama.\n\nTi administrador ti sistema a nangrikep ket nangited iti daytoy a palawag: $1",
        "protectedpagewarning": "<strong>Ballaag: Daytoy a panid ket nasalakniban tapno dagiti laeng agar-aramat nga addaan iti gundaway nga administrador ti makaurnos ditoy.</strong>\nTi naudi a naikabil iti listaan ket naited dita baba para iti reperensia:",
-       "semiprotectedpagewarning": "<strong>Nota:</strong> Nasalakniban daytoy a panid tapno dagiti laeng nakarehistro nga agar-aramat ti makaurnos ditoy.\nTi naudi a naikabil iti listaan ket naited dita baba para iti reperensia:",
+       "semiprotectedpagewarning": "<strong>Nota:</strong> Nasalakniban daytoy a panid tapno dagiti laeng automatiko a napasingkedan nga agar-aramat ti makaurnos ditoy.\nTi naudi a naikabil iti listaan ket naited dita baba para iti reperensia:",
        "cascadeprotectedwarning": "<strong>Ballaag:</strong> Daytoy a panid ket nasalakniban tapno dagiti laeng agar-aramat nga addaan kadagiti [[Special:ListGroupRights|naisangayan a karbengan]] ti makaurnos gapu ta nailak-am {{PLURAL:$1|iti sumaganad a panid|kadagiti sumaganad a panid}} a nasalakniban iti sariap:",
        "titleprotectedwarning": "<strong>Ballaag:  Nasalakniban daytoy a panid tapno [[Special:ListGroupRights|dagiti naisangayan ti karbengan]] ket nasken a makapartuat iti daytoy.</strong>\nTi naudi a naikabil iti listaan ket naited dita baba para iti reperensia:",
        "templatesused": "{{PLURAL:$1|Ti plantilia|Dagiti plantilia}} a naaramat iti daytoy a panid:",
        "postedit-confirmation-created": "Napartuaten ti panid.",
        "postedit-confirmation-restored": "Naipulangen ti panid.",
        "postedit-confirmation-saved": "Naidulinen ti inurnosmo.",
+       "postedit-confirmation-published": "Naipablaaken ti inurnosmo.",
        "edit-already-exists": "Saan a makapartuat iti baro a panid.\nAdda met daytoyen.",
        "defaultmessagetext": "Kasisigud a teksto ti mensahe",
        "content-failed-to-parse": "Napaay a mawaswas ti $2 a linaon para iti $1 a modelo: $3",
        "stub-threshold-disabled": "Nabaldado",
        "recentchangesdays": "Al-aldaw nga ipakita iti kaudian a balbaliw:",
        "recentchangesdays-max": "Kapaut nga $1 {{PLURAL:$1|nga aldaw|nga al-aldaw}}",
-       "recentchangescount": "Bilang dagiti inurnos nga ipakita babaen ti kasisigud:",
-       "prefs-help-recentchangescount": "Daytoy ket mangiraman iti kaudian a balbaliw, dagiti pakasaritaan ti panid, ken dagiti listaan.",
+       "recentchangescount": "Bilang dagiti inurnos nga ipakita kadagiti kaudian a balbaliw, dagiti pakasaritaan ti panid, ken kadagiti listaan, babaen iti kasisigud:",
+       "prefs-help-recentchangescount": "Kaaduan a bilang: 1000",
        "prefs-help-watchlist-token2": "Daytoy ti sekreto a tulbek iti pakan ti web iti listaan ti bambantayam.\nTi sinoman a makaammo daytoy ket mabalinda a basaen ti listaan ti bambantayam, isu a saanmo nga ipabingay.\nNo masapulmo, [[Special:ResetTokens|mabalinmo nga isaad manen]].",
        "savedprefs": "Naidulinen dagiti kakaykayatam.",
        "savedrights": "Naidulinen dagiti grupo ti agar-aramat ni {{GENDER:$1|$1}}.",
        "timezoneregion-europe": "Europa",
        "timezoneregion-indian": "Taaw Indiano",
        "timezoneregion-pacific": "Taaw Pasipiko",
-       "allowemail": "Pakabaelam ti esurat a naggapo kadagiti sabali nga agar-aramat",
+       "allowemail": "Pakabaelan dagiti sabali nga agar-aramt a mangi-esurat kaniak",
+       "email-allow-new-users-label": "Palubosan dagiti esurat manipud kadagiti agdadamo nga agar-aramat",
        "prefs-searchoptions": "Agbiruk",
        "prefs-namespaces": "Dagiti nagan ti espasio",
        "default": "kasisigud",
        "prefs-files": "Dagiti papeles",
        "prefs-custom-css": "Naiduma a CSS",
+       "prefs-custom-json": "Naiduma a JSON",
        "prefs-custom-js": "Naiduma a JavaScript",
-       "prefs-common-config": "Bingay a CSS/JavaScript para kadagiti amin a kudil:",
+       "prefs-common-config": "Bingay a CSS/JSON/JavaScript para kadagiti amin a kudil:",
        "prefs-reset-intro": "Mabalinmo nga usaren daytoy a panid tapno maisublim dagita kakaykayatam iti kasisigud iti daytoy a wiki.\nNgem saanto a mabalinen nga ipasubli.",
        "prefs-emailconfirm-label": "Pammasingked ti esurat:",
        "youremail": "Esurat:",
        "right-editcontentmodel": "Urnosen ti modelo ti linaon iti panid",
        "right-editinterface": "Agurnos iti interface ti agar-aramat",
        "right-editusercss": "Agurnos kadagiti papeles ti CSS dagiti sabali nga agar-aramat",
+       "right-edituserjson": "Agurnos kadagiti papeles ti JSON dagiti sabali nga agar-aramat",
        "right-edituserjs": "Agurnos kadagiti papales ti JavaScript dagiti sabali nga agar-aramat",
        "right-editmyusercss": "Agurnos kadagiti bukodmo a papeles ti CSS ti agar-aramat",
+       "right-editmyuserjson": "Agurnos kadagiti bukodmo a papeles ti JSON ti agar-aramat",
        "right-editmyuserjs": "Agurnos kadagiti bukodmo a papeles ti JavaScript ti agar-aramat",
        "right-viewmywatchlist": "Agkita iti bukodmo a listaan ti bambantayan",
        "right-editmywatchlist": "Agurnos iti bukodmo a listaan ti bambantayan. Laglagipen nga adda dagiti tignay a mangnayonto pay laeng ti pampanid urayno awan daytoy a karbengan.",
        "grant-createaccount": "Agpartuat kadagiti pakabilangan",
        "grant-createeditmovepage": "Agpartuat, agurnos, ken agiyalis kadagiti panid",
        "grant-delete": "Agikkat kadagiti panid, dagiti rebision, ken dagiti naikabil iti listaan",
-       "grant-editinterface": "Urnosen ti nagan ti espasio ti MediaWiki ken ti CSS/JavaScript ti agar-aramat",
-       "grant-editmycssjs": "Urnosen ti bukodmo a CSS/JavaScript ti agar-aramat",
+       "grant-editinterface": "Urnosen ti nagan ti espasio ti MediaWiki ken ti CSS/JSON/JavaScript ti agar-aramat",
+       "grant-editmycssjs": "Urnosen ti bukodmo a CSS/JSON/JavaScript ti agar-aramat",
        "grant-editmyoptions": "Urnosem ti bukodmo a kakaykayatan ti agar-aramat",
        "grant-editmywatchlist": "Urnosen ti bukodmo listaan ti bambantayan",
        "grant-editpage": "Agurnos kadagiti adda a panid",
        "recentchanges-legend": "Pagpilian iti kaudian a balbaliw",
        "recentchanges-summary": "Siputen ti kaudian a balbaliw iti wiki iti daytoy a panid.",
        "recentchanges-noresult": "Awan ti nasuksukatan iti las-ud ti naited a paset ti panawen a kapada dagitoy a kriteria.",
+       "recentchanges-notargetpage": "Mangikabil iti nagan ti panid dita ngato tapno makita dagiti binaliwan a mainaig iti dayta a panid.",
        "recentchanges-feed-description": "Siputen ti kaudian a balbaliw iti wiki iti daytoy a pakan.",
        "recentchanges-label-newpage": "Daytoy a panagurnos ket nakapartuat iti baro a panid",
        "recentchanges-label-minor": "Daytoy ket bassit a panagurnos",
        "recentchanges-legend-heading": "<strong>Leyenda:</strong>",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (kitaen pay ti [[Special:NewPages|listaan ti baro a pampanid]])",
        "recentchanges-submit": "Ipakita",
+       "rcfilters-tag-remove": "Ikkaten ti '$1'",
        "rcfilters-legend-heading": "<strong>Listaan dagiti pangyababaan:</strong>",
        "rcfilters-other-review-tools": "Dagiti sabali pay a pangrepaso a ramit",
        "rcfilters-group-results-by-page": "Igrupo dagiti resulta babaen ti panid",
        "rcfilters-activefilters": "Dagiti aktibo a sagat",
        "rcfilters-advancedfilters": "Dagiti napasayaat a sagat",
-       "rcfilters-limit-title": "Dagiti ipakita a binaliwan",
+       "rcfilters-limit-title": "Dagiti ipakita a resulta",
+       "rcfilters-limit-and-date-label": "$1 {{PLURAL:$1|a binaliwan|a binalbaliwan}}, $2",
+       "rcfilters-date-popup-title": "Paset ti panawen a panagbiruk",
        "rcfilters-days-title": "Kaudian nga al-aldaw",
        "rcfilters-hours-title": "Kaudian nga or-oras",
        "rcfilters-days-show-days": "$1 nga {{PLURAL:$1|aldaw|al-aldaw}}",
        "rcfilters-days-show-hours": "$1 nga {{PLURAL:$1|oras|or-oras}}",
+       "rcfilters-highlighted-filters-list": "Naparaigidan: $1",
        "rcfilters-quickfilters": "Dagiti naidulin a sagat",
-       "rcfilters-quickfilters-placeholder-title": "Awan pay dagiti naidulin a silpo",
+       "rcfilters-quickfilters-placeholder-title": "Awan pay dagiti naidulin a sagat",
        "rcfilters-savedqueries-defaultlabel": "Dagiti naidulin a sagat",
        "rcfilters-savedqueries-rename": "Naganan manen",
        "rcfilters-savedqueries-setdefault": "Isaad a kas kasisigud",
        "rcfilters-restore-default-filters": "Isubli dagiti kasisigud a sagat",
        "rcfilters-clear-all-filters": "Dalusan amin dagiti sagat",
        "rcfilters-show-new-changes": "Kitaen dagiti kabaruan a binaliwan",
-       "rcfilters-search-placeholder": "Sagaten ti kaudian a balbaliw (agbasabasa wenno mangrugi nga agmakinilia)",
+       "rcfilters-search-placeholder": "Sagaten dagiti binaliwan (agusar iti menu wenno agbiruk para iti nagan ti sagat)",
        "rcfilters-invalid-filter": "Imbalido a sagat",
        "rcfilters-empty-filter": "Awan dagiti aktibo a sagat. Naipakita amin dagiti kontribusion.",
        "rcfilters-filterlist-title": "Dagiti sagat",
        "rcfilters-filterlist-whatsthis": "Kasano dagitoy nga agobra?",
-       "rcfilters-filterlist-feedbacklink": "Mangited ti feedback kadagiti baro a (beta) sagat",
+       "rcfilters-filterlist-feedbacklink": "Ibagam kaniami no ania ti mapanunotmo a maipanggep kadagitoy a (baro) pangsagat a ramramit",
        "rcfilters-highlightbutton-title": "Paraigidan dagiti resulta",
        "rcfilters-highlightmenu-title": "Agpili iti maris",
        "rcfilters-highlightmenu-help": "Agpili iti maris a mangparaigid daytoy a tagikua",
        "rcfilters-filter-user-experience-level-unregistered-label": "Saan a nakarehistro",
        "rcfilters-filter-user-experience-level-unregistered-description": "Dagiti editor a saan a nakastrek.",
        "rcfilters-filter-user-experience-level-newcomer-label": "Dagiti agdadamo",
-       "rcfilters-filter-user-experience-level-newcomer-description": "Dagiti nakarehistro nga editor nga addaan iti basbassit ngem 10 nga inur-urnos ken 4 nga aldaw iti aktibidad.",
+       "rcfilters-filter-user-experience-level-newcomer-description": "Dagiti nakarehistro nga editor nga addaan kadagiti basbassit ngem 10 nga inur-urnos wenno 4 nga aldaw iti aktibidad.",
        "rcfilters-filter-user-experience-level-learner-label": "Dagiti agad-adal",
        "rcfilters-filter-user-experience-level-learner-description": "Dagiti nakarehistro nga editor a ti panagsanayda ket maikabil iti pagbaetan ti \"Dagiti agdadamo\" ken \"Dagiti nasanay nga agar-aramat\".",
        "rcfilters-filter-user-experience-level-experienced-label": "Dagiti nasanay nga agar-aramat",
        "rcfilters-filter-humans-description": "Dagiti inurnos nga inaramid babaen dagiti editor a tao.",
        "rcfilters-filtergroup-reviewstatus": "Irepaso ti kasasaad",
        "rcfilters-filter-reviewstatus-unpatrolled-label": "Di napatruliaan",
+       "rcfilters-filter-reviewstatus-manual-description": "Dagiti inurnos a manual a namarkaan a kas napatruliaan.",
+       "rcfilters-filter-reviewstatus-manual-label": "Manual a napatruliaan",
+       "rcfilters-filter-reviewstatus-auto-label": "Automatiko a napatruliaan",
        "rcfilters-filtergroup-significance": "Kaimudingan",
        "rcfilters-filter-minor-label": "Dagiti bassit a panagurnos",
        "rcfilters-filter-minor-description": "Dagiti panagurnos a minarkaan ti mannurat a kas bassit.",
        "rcfilters-liveupdates-button-title-on": "Iddepen dagiti agdama a panagpabaro",
        "rcfilters-liveupdates-button-title-off": "Ipakita dgaiti baro a sinuksukatan bayatda a mapaspasamak",
        "rcfilters-watchlist-markseen-button": "Markaan amin a sinuksukatan a kas nakitan",
+       "rcfilters-target-page-placeholder": "Mangikabil iti nagan ti panid (wenno kategoria)",
        "rcnotefrom": "Dita baba ket {{PLURAL:$5|ti sinukatan|dagiti sinukatan}} manipud idi <strong>$3, $4</strong> (aginggana iti <strong>$1</strong> a naipakita).",
        "rclistfromreset": "Isaad manen ti panagpili ti petsa",
        "rclistfrom": "Ipakita dagiti kabarbaro a sinukatan a mangrugi manipud idi $2, $3",
        "recentchangeslinked-feed": "Mainaig a sinukatan",
        "recentchangeslinked-toolbox": "Mainaig a sinuksukatan",
        "recentchangeslinked-title": "Sinukatan a mainaig iti \"$1\"",
-       "recentchangeslinked-summary": "Daytoy ket listaan dagiti kaudian a sinukatan kadagiti pampanid a nakasilpo manipud iti naisangayan a panid (wenno kadagiti kameng ti maysa a nainaganan a kategoria).\nDagiti panid iti [[Special:Watchlist|listaan ti bambantayam]] ket dagiti <strong>napuskol</strong>.",
+       "recentchangeslinked-summary": "Mangikabil iti maysa a nagan ti panid tapno makita dagiti panagbaliw kadagiti naisilpo a panid wenno iti dayta a panid. (Tapno makita dagiti kameng iti maysa a kategoria, ikabil ti Kategoria:Nagan ti kategoria). Dagiti panagbaliw kadagiti panid iti [[Special:Watchlist|Listaan ti bambantayam]] ket addada iti <strong>napuskol</strong>.",
        "recentchangeslinked-page": "Nagan ti panid:",
        "recentchangeslinked-to": "Ipakita dagiti sinukatan kadagiti panid nga imbes a naisilpo iti naited a panid",
        "recentchanges-page-added-to-category": "nainayon ti [[:$1]] iti kategoria",
        "uploadstash-refresh": "Pasadiwaen dagiti listaan ti papeles",
        "uploadstash-thumbnail": "kitaen ti bassit a ladawan",
        "uploadstash-exception": "Saan a naidulin ti panangikarga iti stash ($1): \"$2\".",
+       "uploadstash-bad-path-invalid": "Saan nga umiso ti dalan.",
+       "uploadstash-bad-path-unknown-type": "Di ammo a kita ti \"$1\".",
+       "uploadstash-bad-path-unrecognized-thumb-name": "Saan a mabigbig a nagan ti bassit a ladawan.",
+       "uploadstash-bad-path-no-handler": "Awan ti mabirukan a mangtengngel para iti mime ti $1 iti papeles ti $2.",
+       "uploadstash-bad-path-bad-format": "Ti tekla ti \"$1\" ket saan nga adda iti maitutop a pormat.",
+       "uploadstash-file-not-found": "Ti tekla ti \"$1\" ket saan a mabirukan iti stash.",
+       "uploadstash-file-not-found-no-thumb": "Saan a makaala iti bassit a ladawan.",
+       "uploadstash-file-not-found-no-local-path": "Awan ti lokal a dalan para iti nagantingan a banag.",
+       "uploadstash-file-not-found-no-object": "Saan a makapartuat iti banag ti lokal a papeles para iti bassit a ladawan.",
+       "uploadstash-file-not-found-no-remote-thumb": "Napaay ti panagala iti bassit a ladawan: $1\nURL = $2",
+       "uploadstash-no-such-key": "Awan ti kasta a tekla ($1), saan a maikkat.",
+       "uploadstash-no-extension": "Awan ti pagpaatiddog.",
+       "uploadstash-zero-length": "Ti papeles ket sero ti kaatiddog.",
        "invalid-chunk-offset": "Imbalido a pirgis ti timbengan",
        "img-auth-accessdenied": "Nalibak ti iseserrek",
        "img-auth-nopathinfo": "Ti servermo ket saan a naisaad nga agipasa iti daytoy a pakaammo.\nMabalin a naibatay iti CGI ken saan a makasuporta ti img_auth.\nKitaen ti https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Image_Authorization .",
        "listfiles_size": "Kadakkel",
        "listfiles_description": "Deskripsion",
        "listfiles_count": "Dagiti bersion",
-       "listfiles-show-all": "Iraman dagiti daan a bersion dagiti ladawan",
+       "listfiles-show-all": "Iraman dagiti daan a bersion dagiti papeles",
        "listfiles-latestversion": "Agdama a bersion",
        "listfiles-latestversion-yes": "Wen",
        "listfiles-latestversion-no": "Saan",
        "statistics-files": "Dagiti naikarga a papeles",
        "statistics-edits": "Dagiti naurnos a panid manipud idi nairugi ti {{SITENAME}}",
        "statistics-edits-average": "Dagiti pagtengngaan nga inurnos iti tunggal maysa a panid",
-       "statistics-users": "Dagiti nakarehistro nga [[Special:ListUsers|agar-aramat]]",
+       "statistics-users": "Dagiti nakarehistro nga agar-aramat",
        "statistics-users-active": "Dagiti aktibo nga agar-aramat",
        "statistics-users-active-desc": "Dagiti agar-aramat a nagtungpal ti aramid iti napalabas nga {{PLURAL:$1|aldaw|$1 nga al-aldaw}}",
        "pageswithprop": "Pampanid nga adda tagikua ti panid",
        "doubleredirects": "Dagiti namindua a naibaw-ing",
        "doubleredirectstext": "Daytoy a panid ket ilistana dagiti panid nga agbaw-ing kadagiti sabali a baw-ing a pampanid.\nIti tunggal maysa nga aray ket aglaon kadagiti silpo iti umuna ken maikadua a baw-ing, ken ti pay puntaan ti maikadua a baw-ing, nga isu ti \"pudno\" a puntaan ti panid, nga ti umuna a baw-ing ket isu koma ti pakaituduanna.\nNasolbaren dagiti <del>nakurosan</del> a naikabil.",
        "double-redirect-fixed-move": "Naiyalisen ti [[$1]].\nAutomatiko idi a napabaro ken naibaw-ing tattan iti [[$2]].",
-       "double-redirect-fixed-maintenance": "Automatiko nga agsimsimpa ti doble a baw-ing manipud iti [[$1]] iti [[$2]] iti panagtaripato nga obra.",
+       "double-redirect-fixed-maintenance": "Automatiko nga agsimsimpa iti doble a baw-ing manipud iti [[$1]] iti [[$2]] iti panagtaripato nga obra",
        "double-redirect-fixer": "Panagsimpa ti baw-ing",
        "brokenredirects": "Dagiti naputed a baw-ing",
        "brokenredirectstext": "Dagiti sumaganad a baw-ing ket nakasilpo kadagiti awan a panid:",
        "deadendpages": "Dagiti ngudo a panid",
        "deadendpagestext": "Dagiti sumaganad a panid ket saan a nakasilpo kadagiti sabali a panid iti {{SITENAME}}.",
        "protectedpages": "Dagiti nasalakniban a panid",
+       "protectedpages-filters": "Dagiti sagat:",
        "protectedpages-indef": "Dagiti inggat ingana a salaknib laeng",
        "protectedpages-summary": "Daytoy a panid ket ilistana dagiti panid nga agdama a nasalakniban. Para iti listaan dagiti titulo a nasalakniban manipud ti pannakapartuat, kitaen ti [[{{#special:ProtectedTitles}}|{{int:protectedtitles}}]].",
        "protectedpages-cascade": "Dagiti sariap a salaknib laeng",
        "apisandbox-dynamic-error-exists": "Addan iti parametro nga agnagan iti \"$1\".",
        "apisandbox-deprecated-parameters": "Dagiti nasukatanen a parametro",
        "apisandbox-fetch-token": "Automatiko a punnuen ti tangdan",
+       "apisandbox-add-multi": "Inayon",
        "apisandbox-submit-invalid-fields-title": "Adda dagiti imbalido a pagikabilan",
        "apisandbox-submit-invalid-fields-message": "Pangngaasi a simpaen dagiti namarkaan a pagikabilan ken padasen manen.",
        "apisandbox-results": "Dagiti resulta",
        "unwatchthispage": "Isardeng a bantayan daytoy a panid",
        "notanarticle": "Saan a naglaon a panid",
        "notvisiblerev": "Ti naudi a rebision babaen ti sabali nga agar-aramat ket naikkaten",
-       "watchlist-details": "{{PLURAL:$1|$1 a panid|$1 a pampanid}} iti listaan ti bambantayam, a saan a naisina a mairaman dagiti panid ti tungtungan.",
+       "watchlist-details": "{{PLURAL:$1|$1 a panid|$1 a pampanid}} iti Listaan ti bambantayam (mairaman dagiti panid ti tungtungan).",
        "wlheader-enotif": "Napakabaelan ti panangipakaammo ti esurat.",
        "wlheader-showupdated": "Dagiti panid a nasukatanen manipud ti kinaudi a panagsarungkarmo ket naipakita iti <strong>napuskol</strong>.",
        "wlnote": "Dita baba ket {{PLURAL:$1|naudi a sinukatan|dagiti naudi a <strong>$1</strong> a sinukatan}} iti napalabas {{PLURAL:$2|nga oras|a <strong>$2</strong> nga or-oras}}, manipud idi $3, $4.",
        "import-mapping-namespace": "Agala a mangipan iti nagan ti espasio:",
        "import-mapping-subpage": "Alaen a kas dagiti subpanid ti sumaganad a panid:",
        "import-upload-filename": "Nagan ti papeles:",
+       "import-upload-username-prefix": "Pasakbay ti interwiki:",
        "import-comment": "Komentario:",
        "importtext": "Pangngaasi nga ipanmo ti papeles manipud iti nagtaudan a wiki nga agusar ti [[Special:Export|ramit ti panagipan]].\nIdulinmo iti bukodmo a kompiuter ken ikarga ditoy.",
        "importstart": "Agal-ala kadagiti panid...",
        "imported-log-entries": "Naala ti $1 {{PLURAL:$1|a nailista|kadagiti nailista}}.",
        "importfailed": "Napaay ti panagala: <nowiki>$1</nowiki>",
        "importunknownsource": "Di ammmo a kita ti taudan ti innala",
+       "importnoprefix": "Awan ti naited a pasakbay ti interwiki",
        "importcantopen": "Saan a maluktan ti innala a papeles",
        "importbadinterwiki": "Saan a nasayaat a silpo ti interwiki",
        "importsuccess": "Nalpasen ti panagala!",
        "tooltip-undo": "\"Ibabawi\" isubli daytoy nga urnos ken lukatanna ti porma ti pagurnosan iti moda ti panagpadas. Mangipalubos daytoy ti agikabil ti rason iti pakabuklan.",
        "tooltip-preferences-save": "Idulin dagiti kakaykayatam",
        "tooltip-summary": "Agikabil ti bassit a pakabuklan",
+       "common.json": "/* Iti ania man a JSON ditoy ket maikarganto para kadagiti amin nga agar-aramat iti tunggal maysa a panangikarga iti panid. */",
        "anonymous": "Di ammo {{PLURAL:$1|nga agar-aramat|kadagiti agar-aramat}} iti {{SITENAME}}",
        "siteuser": "{{SITENAME}} nga agar-aramat $1",
        "anonuser": "{{SITENAME}} di ammo nga agar-aramat $1",
        "pageinfo-category-subcats": "Bilang dagiti subkategoria",
        "pageinfo-category-files": "Bilang dagiti papeles",
        "pageinfo-user-id": "ID ti agar-aramat",
+       "pageinfo-file-hash": "Pateg ti hash",
        "markaspatrolleddiff": "Markaan a kas napatruliaan",
        "markaspatrolledtext": "Markaan daytoy a panid a kas napatruliaan",
        "markaspatrolledtext-file": "Markaan daytoy a bersion ti papeles a kas napatruliaan",
        "autosumm-blank": "Naikkat amin ti linaon ti panid",
        "autosumm-replace": "Sinukatan ti linaon iti \"$1\"",
        "autoredircomment": "Naibaw-ing ti panid iti [[$1]]",
+       "autosumm-removed-redirect": "Inikkat ti baw-ing iti [[$1]]",
+       "autosumm-changed-redirect-target": "Binaliwan ti puntaan ti bawing manipud iti [[$1]] iti [[$2]]",
        "autosumm-new": "Pinartuat ti panid iti \"$1\"",
        "autosumm-newblank": "Nagpartuat ti blanko a panid",
        "lag-warn-normal": "Dagiti panangbalbaliw a nabarbaro ngem $1 {{PLURAL:$1|a segundo|a segsegundo}} ket mabalin a saan a maiparang iti daytoy a listaan.",
        "watchlistedit-clear-titles": "Dagiti titulo:",
        "watchlistedit-clear-submit": "Dalusan ti listaan ti bambantayan (Daytoy ket permanente!)",
        "watchlistedit-clear-done": "Nadalusanen ti bambantayam.",
+       "watchlistedit-clear-jobqueue": "Madaldalusanen ti listaan ti bambantayam. Mabalin a nabayag daytoy!",
        "watchlistedit-clear-removed": "{{PLURAL:$1|1 a titulo|$1 kadagiti titulo}} ti naikkat:",
        "watchlistedit-too-many": "Adu unay a pampanid ti maiparang ditoy.",
        "watchlisttools-clear": "Dalusan ti listaan ti bambantayan",
        "version-specialpages": "Espesial a pampanid",
        "version-parserhooks": "Dagiti parser a kawit",
        "version-variables": "Nadumaduma a kita",
+       "version-editors": "Dagiti editor",
        "version-antispam": "Panagpawil iti spam",
        "version-other": "Sabali",
        "version-mediahandlers": "Panagtengngel kadagiti midia",
        "version-poweredby-others": "dadduma pay",
        "version-poweredby-translators": "dagiti agipatpatarus iti translatewiki.net",
        "version-credits-summary": "Kayatmi koma a pammadayawan dagiti sumaganad a tao para kadagiti kontribusonda iti [[Special:Version|MediaWiki]].",
-       "version-license-info": "Ti MediaWiki ket nawaya a sopwer; mabalinmo nga iwaras ken/wenno baliwan babaen kadagiti termino ti GNU General Public License a naipablaak babaen ti Free Software Foundation; wenno bersion 2 iti Lisensia, wenno (ti panagpilim) ti  ania man a naudi a bersion.\n\nTi MediaWiki ket naiwarwaras iti namnama a makatulongto, ngem AWAN TI ANIA MAN A GARANTIA; nga awan pay ti naibagbaga a PANNAKAILAKO wenno KALAINGANNA ITI DAYTOY A PANGGEP. Kitaen ti GNU General Public License para kadagiti adu pay a salaysay.\n\nNaka-awatka koman ti [{{SERVER}}{{SCRIPTPATH}}/COPYING kopia iti GNU General Public License] a nairaman iti daytoy a programa; no saan, agsuratka idiay Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA wenno [//www.gnu.org/licenses/old-licenses/gpl-2.0.html basaem iti online].",
+       "version-license-info": "Ti MediaWiki ket nawaya a sopwer; mabalinmo nga iwaras ken/wenno baliwan babaen kadagiti termino ti GNU General Public License a naipablaak babaen ti Free Software Foundation; wenno bersion 2 iti Lisensia, wenno (ti panagpilim) ti  ania man a naudi a bersion.\n\nTi MediaWiki ket naiwarwaras iti namnama a makatulongto, ngem <em>AWAN TI ANIA MAN A GARANTIA</em>; nga awan pay ti naibagbaga a <strong> PANNAKAILAKO</strong>  wenno <strong> KALAINGANNA ITI DAYTOY A PANGGEP</strong> . Kitaen ti GNU General Public License para kadagiti adu pay a salaysay.\n\nNakaawatka koman iti [{{SERVER}}{{SCRIPTPATH}}/COPYING kopia iti GNU General Public License] a nairaman iti daytoy a programa; no saan, agsuratka idiay Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA wenno [//www.gnu.org/licenses/old-licenses/gpl-2.0.html basaem iti online].",
        "version-software": "Naisaad a sopwer",
        "version-software-product": "Produkto",
        "version-software-version": "Bersion",
        "fileduplicatesearch-noresults": "Awan ti nabirukan a papeles a nanaganan ti \"$1\".",
        "specialpages": "Espesial a pampanid",
        "specialpages-note-top": "Leyenda",
+       "specialpages-note-restricted": "* Kadawyan nga espesial a pampanid.\n* <span class=\"mw-specialpagerestricted\">Nagawidan nga espesial a pampanid.</span>",
        "specialpages-group-maintenance": "Dagiti reporta ti panagtaripato",
        "specialpages-group-other": "Sabali nga espesial a pampanid",
        "specialpages-group-login": "Sumrek / agpartuat ti pakabilangan",
        "tag-list-wrapper": "([[Special:Tags|{{PLURAL:$1|Etiketa|Et-etiketa}}]]: $2)",
        "tag-mw-contentmodelchange": "panagbaliw ti modelo ti linaon",
        "tag-mw-contentmodelchange-description": "Dagiti panagurnos a [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:ChangeContentModel mangbaliw ti modelo ti linaon] ti panid",
+       "tag-mw-new-redirect": "Baro a baw-ing",
+       "tag-mw-new-redirect-description": "Dagiti inurnos a nagpartuat iti baro a baw-ing wenno binaliwan ti maysa a panid iti maysa a baw-ing",
+       "tag-mw-removed-redirect": "Inikkat ti baw-ing",
+       "tag-mw-removed-redirect-description": "Dagiti inurnos a nangbaliw iti maysa nga adda a baw-ing iti maysa a saan a baw-ing",
+       "tag-mw-changed-redirect-target": "Nabaliwan ti puntaan ti baw-ing",
+       "tag-mw-changed-redirect-target-description": "Dagiti inurnos a nangbaliw iti puntaan ti maysa a baw-ing",
+       "tag-mw-blank": "Panagblanko",
+       "tag-mw-blank-description": "Dagiti inurnos a mangblanko iti maysa a panid",
+       "tag-mw-replace": "Sinukatan",
+       "tag-mw-replace-description": "Dagiti inurnos a mangikkat iti ad-adu ngem 90% iti linaon iti maysa a panid",
        "tags-title": "Dagiti etiketa",
        "tags-intro": "Daytoy a panid ket ilistana dagiti etiketa a mablin nga usaren ti sopwer a mangmarka iti inurnos, ken dagiti kaibuksilanda.",
        "tags-tag": "Nagan ti etiketa",
        "expandtemplates": "Palawaen dagiti plantilia",
        "expand_templates_intro": "Daytoy nga espesial a panid ket agala ti teksto ken palawaenna amin dagiti plantilia iti unegna a mainaig iti daytoy.\nPalawaenna pay dagiti nasuportaran a parser a pamay-an a kas ti\n<code><nowiki>{{</nowiki>#language:…}}</code> ken dagiti nadumaduma a kita a kas ti\n<code><nowiki>{{</nowiki>CURRENTDAY}}</code>. \nIti kinapudno, palawaenna amin dagiti addaan iti doble a pangrikep.",
        "expand_templates_title": "Titulo ti konteksto, para iti {{FULLPAGENAME}} kdpy.:",
-       "expand_templates_input": "Maikabil a teksto:",
+       "expand_templates_input": "Maikabil a teksto ti wiki:",
        "expand_templates_output": "Nagbanagan",
        "expand_templates_xml_output": "Maiparuar a XML",
        "expand_templates_html_output": "Naata a maiparuar a HTML",
        "expand_templates_generate_xml": "Iparang ti pangwaswas a kayo ti XML",
        "expand_templates_generate_rawhtml": "Ipakita ti naata a HTML",
        "expand_templates_preview": "Ipadas",
-       "expand_templates_input_missing": "Nasken a mangitedka iti maikabil a teksto.",
+       "expand_templates_input_missing": "Nasken a mangitedka iti maikabil a teksto ti wiki.",
        "pagelanguage": "Baliwan ti pagsasao ti panid",
        "pagelang-name": "Panid",
        "pagelang-language": "Pagsasao",
        "special-characters-group-thai": "Thai",
        "special-characters-group-lao": "Lao",
        "special-characters-group-khmer": "Khmer",
+       "special-characters-group-canadianaboriginal": "Aborihinal a Kanadiano",
        "special-characters-title-endash": "en dash",
        "special-characters-title-emdash": "em dash",
        "special-characters-title-minus": "senial a panagkissay",
        "restrictionsfield-badip": "Imbalido nga adres ti IP wenno sakup: $1",
        "restrictionsfield-label": "Dagiti mapalubosan a sakup ti IP:",
        "restrictionsfield-help": "Maysa nga adres ti IP wenno sakup ti CIDR kada linia. Tapno mapakabaelan amin, usaren ti:<pre>0.0.0.0/0\n::/0</pre>",
+       "edit-error-short": "Biddut: $1",
+       "edit-error-long": "Dagiti biddut:\n\n$1",
        "revid": "rebision $1",
        "pageid": "ID ti panid $1",
        "rawhtml-notallowed": "Saan a mabalin a mausar dagiti etiketa ti &lt;html&gt; iti ruar dagiti kadawyan a panid.",
index 731baad..eb259f4 100644 (file)
@@ -44,7 +44,7 @@
        "tog-enotifrevealaddr": "Montrez mea e-posto adreso en notifiko e-posti",
        "tog-shownumberswatching": "Montrez nombro di surveyanta uzanti",
        "tog-oldsig": "Vua existanta signaturo:",
-       "tog-fancysig": "Traktez signaturo kom wikikodo (sen automata ligilo)",
+       "tog-fancysig": "Traktez signaturo kom kodexo Wiki (sen automata ligilo)",
        "tog-uselivepreview": "Permisas previdar sen richarjar la pagino",
        "tog-forceeditsummary": "Notifikez me kande skribanta vakua redakto-rezumo",
        "tog-watchlisthideown": "Celez mea redaktaji de la surveyaji",
        "recentchanges-label-plusminus": "La pagino modifikesis segun ica quanto di *bicoki",
        "recentchanges-legend-heading": "<strong>Noto:</strong>",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (videz anke la [[Special:NewPages|listo di nova pagini]])",
+       "recentchanges-submit": "Montrez",
        "rcfilters-legend-heading": "<strong>Listo di abreviuri:</strong>",
        "rcfilters-other-review-tools": "Altra instrumenti por revizo",
        "rcfilters-group-results-by-page": "Grupigar la rezulti segun pagino",
        "rcfilters-activefilters": "Agiva filtrili",
        "rcfilters-advancedfilters": "Rafinita filtrili",
        "rcfilters-limit-title": "Rezulti por montrar",
+       "rcfilters-date-popup-title": "Quanto di tempo por serchar",
        "rcfilters-days-title": "Recenta dii",
+       "rcfilters-hours-title": "Recenta hori",
        "rcfilters-days-show-days": "$1 {{PLURAL:$1|dio|dii}}",
        "rcfilters-quickfilters": "Konservita filtrili",
        "rcfilters-quickfilters-placeholder-title": "Nula filtrilo konservesis til nun",
        "rcfilters-filter-newpages-label": "Kreado di pagini",
        "rcfilters-filter-categorization-label": "Modifiki di la kategorio",
        "rcfilters-filter-logactions-label": "Agadi enrejistrata",
+       "rcfilters-liveupdates-button": "Quika aktualigi",
        "rcnotefrom": "Infre {{PLURAL:$5|esas la chanjo|esas la chanji}} de <strong>$3, $4</strong> (montrata til <strong>$1</strong>).",
        "rclistfrom": "Montrar nova chanji startante de $3 $2",
        "rcshowhideminor": "$1 mikra redakturi",
        "rcshowhidemine": "$1 mea redakti",
        "rcshowhidemine-show": "Montrar",
        "rcshowhidemine-hide": "Celar",
+       "rcshowhidecategorization-show": "Montrez",
        "rclinks": "Montrar la lasta $1 chanji dum la lasta $2 dii",
        "diff": "dif",
        "hist": "vers",
        "nolinkstoimage": "Nula pagino ligas a ca pagino.",
        "linkstoimage-redirect": "$1 (arkivo ridirektita) $2",
        "sharedupload": "Ca arkivo esas de $1 e posible esas uzata da altra projekti.",
-       "sharedupload-desc-here": "Ca arkivo jacas en $1, e povas uzesar en altra projeti.\nLa deskriptado en lua [$2 pagino di deskriptado] montresas infre.",
+       "sharedupload-desc-here": "Ca arkivo jacas en $1, e povas uzesar en altra projeti.\nLa deskriptado en lua [$2 pagino di deskriptado] montresas adinfre.",
        "filepage-nofile": "Nula arkivo kun ica nomo existas.",
        "uploadnewversion-linktext": "Adkargez nova versiono dil arkivo",
        "shared-repo-from": "ek $1",
        "unusedtemplates": "Neuzata shabloni",
        "unusedtemplateswlh": "altra ligili",
        "randompage": "Hazarda pagino",
+       "randomincategory-submit": "Irez",
        "randomredirect": "Hazarda ridirektilo",
        "statistics": "Statistiko",
        "statistics-header-pages": "Statistiki di la pagini",
        "wantedfiles": "Dezirata arkivi",
        "wantedtemplates": "Dezirata shabloni",
        "prefixindex": "Omna pagini kun prefixo",
+       "prefixindex-submit": "Montrez",
        "shortpages": "Kurta pagini",
        "longpages": "Longa pagini",
        "deadendpages": "Pagini sen ekiraji",
        "usereditcount": "$1 {{PLURAL:$1|redakto|redakti}}",
        "usercreated": "{{GENDER:$3|Kreita}} ye $1 $2",
        "newpages": "Nova pagini",
+       "newpages-submit": "Montrez",
        "newpages-username": "Nomo dil uzero:",
        "ancientpages": "Maxim anciena artikli",
        "move": "Movar",
        "specialloguserlabel": "Agero:",
        "speciallogtitlelabel": "Skopo (titulo od {{ns:user}}:uzernomo por uzero):",
        "log": "Registrari",
+       "logeventslist-submit": "Montrez",
        "all-logs-page": "Omna publika registrari",
        "alllogstext": "Kombinata montro di omna 'log'-i di {{SITENAME}} disponebla.\nVu povas stretigar la vidado per la selekto di la tipo di protoloko (log type), l'uzantonomo (case-sensitive), o la pagino afektita (also case-sensitive).",
        "logempty": "Nula kombinuri trovesis en la protokolo.",
        "allpages-bad-ns": "{{SITENAME}} ne havas nomaro \"$1\".",
        "allpages-hide-redirects": "Celar ridirekti",
        "categories": "Kategorii",
+       "categories-submit": "Montrez",
+       "categoriesfrom": "Montrez kategorii komencante en:",
        "deletedcontributions": "Efacita uzero-kontributaji",
        "deletedcontributions-title": "Efacita uzero-kontributaji",
        "linksearch": "Sercho di extera ligili",
        "wlheader-showupdated": "Pagini qui modifikesis pos vua lasta vizito montresas en <strong>dika literi</strong>.",
        "wlnote": "Yen la maxim recenta {{PLURAL:$1|chanjo|<strong>$1</strong> chanji}} dum la lasta {{PLURAL:$2|horo|<strong>$2</strong> hori}}, de $3,$4.",
        "wlshowlast": "Montrez la lasta $1 hori $2 dii",
+       "watchlist-submit": "Montrez",
        "wlshowhideminor": "mikra redakturi",
        "wlshowhidebots": "Roboti (bots)",
        "wlshowhideliu": "Uzeri enrejistrita",
        "protect_expiry_old": "Expirotempo es in pasinta.",
        "protect-default": "Permisar omna uzanti",
        "protect-fallback": "Permisez nur uzeri kun permiso \"$1\"",
-       "protect-level-sysop": "Permisez nur administreri",
+       "protect-level-autoconfirmed": "Permisar nur uzeri automatale konfirmata",
+       "protect-level-sysop": "Permisar nur administreri",
        "protect-summary-cascade": "kaskade",
        "protect-expiring": "expiras ye $1 (UTC)",
+       "protect-expiring-local": "la protekto finos ye $1",
        "protect-expiry-indefinite": "nefinita",
+       "protect-cascade": "Protektar pagini inkluzita en ica pagino (protekto en sequo)",
        "protect-othertime": "Altra tempo:",
        "protect-othertime-op": "altra tempo",
        "protect-otherreason": "Altra/suplementala motivo:",
        "protect-otherreason-op": "Altra motivo",
-       "protect-expiry-options": "1 horo:1 hour,1 dio:1 day,1 semano:1 week,2 semani:2 weeks,1 monato:1 month,3 monati:3 months,6 monati:6 months,1 yaro:1 year,infinita:infinite",
+       "protect-expiry-options": "1 horo:1 hour,1 dio:1 day,1 semano:1 week,2 semani:2 weeks,1 monato:1 month,3 monati:3 months,6 monati:6 months,1 yaro:1 year,nefinita:infinite",
        "restriction-type": "Permiso:",
        "pagesize": "(bicoki)",
        "restriction-edit": "Redaktar",
        "ipbemailban": "Impedar l'uzero sendar e-posto",
        "ipbsubmit": "Blokusar ica uzero",
        "ipbother": "Altra tempo:",
-       "ipboptions": "2 horo:2 hours,1 dio:1 day,3 dii:3 days,1 semano:1 week,2 semani:2 weeks,1 monato:1 month,3 monati:3 months,6 monati:6 months,1 yaro:1 year,infinita:infinite",
+       "ipboptions": "2 hori:2 hours,1 dio:1 day,3 dii:3 days,1 semano:1 week,2 semani:2 weeks,1 monato:1 month,3 monati:3 months,6 monati:6 months,1 yaro:1 year,nefinita:infinite",
        "ipbwatchuser": "Vigilar la pagino di prizentado e la pagino di diskuto de ica uzero",
        "ipb-disableusertalk": "Impedar l'uzero redaktar en lua propra diskutopagino dum la blokuso",
        "badipaddress": "IP-adreso ne esas valida",
        "movepage-moved-noredirect": "La kreado di ridirekto nuligesis.",
        "articleexists": "Pagino kun sama nomo ja existas od la nomo\nqua vu selektis ne esas valida.\nVoluntez selektar altra nomo.",
        "movetalk": "Rinomizar la debato-pagino se to esas aplikebla.",
+       "move-subpages": "Movar subpagini (til admaxime $1)",
+       "movepage-page-moved": "La pagino $1 movesis a $2.",
+       "movepage-page-unmoved": "La pagino $1 ne povis rinomizesar \"$2\".",
        "movelogpage": "Movo-registraro",
        "movereason": "Motivo:",
        "revertmove": "rekuperar",
        "tooltip-n-mainpage": "Vizitez la Chefpagino",
        "tooltip-n-mainpage-description": "Vizitez la chefpagino",
        "tooltip-n-portal": "Pri la projeto, quon vu facus, ube trovus utilaji",
-       "tooltip-n-currentevents": "Trovez informeco pri aktuala eventi",
+       "tooltip-n-currentevents": "Trovez informi pri nuna eventi",
        "tooltip-n-recentchanges": "Listo di recenta chanji en la wiki.",
        "tooltip-n-randompage": "Vizitez hazarda pagino",
        "tooltip-n-help": "La loko por trovar ulo.",
        "svg-long-desc": "arkivo SVG, nominale $1 x $2 \"pixels\", kun $3",
        "show-big-image": "Arkivo originala",
        "show-big-image-preview": "Grandeso de ica previdado: $1.",
+       "show-big-image-preview-differ": "Grandezo di la previdado $3 de ica arkivo $2: $1.",
        "show-big-image-other": "Altra {{PLURAL:$2|qualeso dil imajo|qualeso, en pixel-i}}: $1.",
        "show-big-image-size": "$1 x $2 pixels",
        "newimages": "Galerio di nova arkivi",
        "confirmrecreate-noreason": "Uzero [[User:$1|$1]] ([[User talk:$1|mesaji]]) {{GENDER:$1|efacis}} la pagino quon vu komencis redaktar. Voluntez konfirmar se vu fakte deziras rikrear ica pagino.",
        "recreate": "Rikrear",
        "confirm_purge_button": "O.K.",
+       "confirm-unwatch-button": "O.K.",
        "imgmultipageprev": "← antea pagino",
        "imgmultipagenext": "sequanta pagino →",
        "imgmultigo": "Irez!",
        "autosumm-replace": "Kontenajo remplasigesis kun '$1'",
        "autoredircomment": "Ridirektas a [[$1]]",
        "autosumm-new": "Pagino kreesis kun '$1'",
+       "autosumm-newblank": "Kreita vakua pagino",
        "watchlistedit-normal-title": "Modifikez surveyo-listo",
        "watchlistedit-normal-legend": "Removar tituli de surveyo-listo",
        "watchlistedit-normal-explain": "La tituli de vua surveyo-listo montresas adinfre.\nPor removar ula titulo, markizez la buxo proxim ol, e kliktez \"{{int:Watchlistedit-normal-submit}}\".\nVu anke povas [[Special:EditWatchlist/raw|redaktar direkte la 'kruda' listo]].",
        "tag-filter": "[[Special:Tags|etiketo]] filtrilo:",
        "tag-filter-submit": "Filtrez",
        "tag-list-wrapper": "([[Special:Tags|{{PLURAL:$1|Etikedo|Etikedi}}]]: $2)",
+       "tags-title": "Etiketi",
        "tags-description-header": "Kompleta deskripto dil senco",
        "tags-active-yes": "Yes",
        "tags-active-no": "No",
index e1b89d8..fe24680 100644 (file)
        "statistics-files": "File caricati",
        "statistics-edits": "Modifiche a partire dall'installazione di {{SITENAME}}",
        "statistics-edits-average": "Media delle modifiche per pagina",
-       "statistics-users": "[[Special:ListUsers|Utenti]] registrati",
+       "statistics-users": "Utenti registrati",
        "statistics-users-active": "Utenti attivi",
        "statistics-users-active-desc": "Utenti che hanno effettuato un'azione {{PLURAL:$1|nell'ultimo giorno|negli ultimi $1 giorni}}",
        "pageswithprop": "Pagine con una proprietà di pagina",
        "deadendpages": "Pagine senza uscita",
        "deadendpagestext": "Le pagine indicate di seguito sono prive di collegamenti verso altre pagine di {{SITENAME}}.",
        "protectedpages": "Pagine protette",
+       "protectedpages-filters": "Filtri:",
        "protectedpages-indef": "Solo protezioni infinite",
        "protectedpages-summary": "Questa pagina elenca le pagine esistenti che sono attualmente protette. Per un elenco di titoli protetti dalla creazione, vedi [[{{#special:ProtectedTitles}}|{{int:protectedtitles}}]].",
        "protectedpages-cascade": "Solo protezioni ricorsive",
index 6e2bac9..90bf708 100644 (file)
        "statistics-files": "アップロードされたファイル数",
        "statistics-edits": "{{SITENAME}}の開設以降の編集回数の総計",
        "statistics-edits-average": "1ページあたりの編集回数",
-       "statistics-users": "[[Special:ListUsers|利用者]]",
+       "statistics-users": "登録利用者",
        "statistics-users-active": "活動中の利用者",
        "statistics-users-active-desc": "過去 {{PLURAL:$1|$1 日間}}に何らかの操作をした利用者",
        "pageswithprop": "ページプロパティがあるページ",
        "deadendpages": "行き止まりページ",
        "deadendpagestext": "以下のページは、{{SITENAME}}の他のページにリンクしていません。",
        "protectedpages": "保護されているページ",
+       "protectedpages-filters": "フィルター:",
        "protectedpages-indef": "無期限保護のみ",
        "protectedpages-summary": "このページでは、現時点で保護されている既存のページを列挙します。新規作成が禁止されているページ名の一覧は、[[{{#special:ProtectedTitles}}|{{int:protectedtitles}}]] を参照してください。",
        "protectedpages-cascade": "カスケード保護のみ",
        "version-specialpages": "特別ページ",
        "version-parserhooks": "構文解析フック",
        "version-variables": "変数",
+       "version-editors": "エディター",
        "version-antispam": "スパム対策",
        "version-api": "API",
        "version-other": "その他",
index 83d1338..36b772b 100644 (file)
        "rcfilters-group-results-by-page": "ដាក់លទ្ធផលជាក្រុមតាមទំព័រ",
        "rcfilters-activefilters": "តម្រងកំពុងប្រើ",
        "rcfilters-advancedfilters": "តម្រងពិសេស",
-       "rcfilters-limit-title": "លទ្ធផលត្រូវបង្ហាញ",
+       "rcfilters-limit-title": "á\9e\85á\9f\86á\9e\93á\9e½á\9e\93á\9e\9bá\9e\91á\9f\92á\9e\92á\9e\95á\9e\9bá\9e\8fá\9f\92á\9e\9aá\9e¼á\9e\9cá\9e\94á\9e\84á\9f\92á\9e á\9e¶á\9e\89",
        "rcfilters-limit-and-date-label": "{{PLURAL:$1|បន្លាស់ប្ដូរ|បន្លាស់ប្ដូរ}}ចំនួន$1 ក្នុងរយៈពេល $2 នេះ",
        "rcfilters-date-popup-title": "រយៈពេលដែលត្រូវស្វែងរក",
        "rcfilters-days-title": "ចំនួនថ្ងៃមុននេះ",
        "statistics-files": "ឯកសារបានផ្ទុកឡើង",
        "statistics-edits": "ការកែប្រែទំព័រចាប់តាំងពី{{SITENAME}}ត្រូវបានដំឡើង",
        "statistics-edits-average": "កំណែប្រែជាមធ្យមក្នុងមួយទំព័រ",
-       "statistics-users": "[[Special:ListUsers|អ្នកប្រើប្រាស់]]ដែលបានចុះឈ្មោះ",
+       "statistics-users": "អ្នកប្រើប្រាស់ដែលបានចុះឈ្មោះ",
        "statistics-users-active": "អ្នកប្រើប្រាស់សកម្ម",
        "statistics-users-active-desc": "អ្នក​ប្រើប្រាស់​ដែល​បាន​អនុវត្ត​សកម្មភាព​ក្នុង​{{PLURAL:$1|ថ្ងៃ​}}ចុង​ក្រោយ​",
        "pageswithprop-submit": "ទៅ",
        "doubleredirects": "ទំព័របញ្ជូនបន្តទ្វេដង",
        "doubleredirectstext": "ទំព័រនេះរាយឈ្មោះទំព័រដែលបញ្ជូនបន្តទៅទំព័របញ្ជូនបន្ដផ្សេងទៀត។\n\nជួរនីមួយៗមានតំនភ្ជាប់ទៅកាន់ទំព័របញ្ជូនបន្តទី១និងទី២ ព្រមជាមួយទំព័រគោលដៅរបស់ទំព័របញ្ជូនបន្តទី២(ដែលជាធម្មតានេះក៏ជាទំព័រគោលដៅ\"ពិត\"របស់ទំព័របញ្ជូនបន្តទី១ដែរ)។",
        "double-redirect-fixed-move": "[[$1]] ត្រូវបានប្ដូរទីតាំង។\nវាត្រូវបានបន្ទាន់សម័យនិងត្រូវបានបញ្ជូនបន្តទៅ [[$2]]។",
-       "double-redirect-fixed-maintenance": "កំពុងជួសជុលការបញ្ជូនបន្តផ្ទួនគ្នាពី [[$1]] ទៅ [[$2]]ដោយស្វ័យប្រវត្តិ ក្រោមកិច្ចថែទាំជាប្រចាំ ។",
+       "double-redirect-fixed-maintenance": "កំពុងជួសជុលការបញ្ជូនបន្តផ្ទួនគ្នាពី [[$1]] ទៅ [[$2]]ដោយស្វ័យប្រវត្តិ ក្រោមកិច្ចថែទាំជាប្រចាំ",
        "double-redirect-fixer": "អ្នកជួសជុលការបញ្ជូនបន្ត",
        "brokenredirects": "ការបញ្ជូនបន្តដែលខូច",
        "brokenredirectstext": "ការបញ្ជូនបន្ដដូចតទៅនេះ​សំដៅទៅ​ទំព័រដែលមិនមាន៖",
        "apisandbox-submit": "ដាក់សំណើ",
        "apisandbox-reset": "ជម្រះ",
        "apisandbox-examples": "ឧទាហរណ៍",
-       "apisandbox-request-time": "រយៈពេលធ្វើសំណើ៖ $1",
+       "apisandbox-request-time": "រយៈពេលធ្វើសំណើ៖ {{PLURAL:$1|$1 មីលីវិនាទី}}",
        "booksources": "ប្រភពសៀវភៅ",
        "booksources-search-legend": "ស្វែងរកប្រភពសៀវភៅ",
        "booksources-isbn": "លេខ​កូដ​សៀវ​ភៅ​ ISBN ៖",
        "booksources-text": "ខាងក្រោមនេះជាបញ្ជីនៃតំណភ្ជាប់ទៅវិបសាយនានាដែលលក់​សៀវភៅថ្មីនិងជជុះ ហើយអាចផ្ដល់ព័ត៌មានបន្ថែមផ្សេងទៀតអំពីសៀវភៅដែលអ្នកកំពុងស្វែងរក៖",
        "booksources-invalid-isbn": "លេខISBNដែលអ្នកផ្ដល់អោយហាក់ដូចជាមិនត្រឹមត្រូវទេ។ សូមពិនិត្យក្រែងលោមានកំហុសក្នុងការចម្លងចេញពីប្រភពដើម។",
        "specialloguserlabel": "អ្នកប្រព្រឹត្តិ៖",
-       "speciallogtitlelabel": "គោលដៅ (ចំណងជើងអត្ថបទឬអត្តនាមអ្នកប្រើប្រាស់)៖",
+       "speciallogtitlelabel": "គោលដៅ (ចំណងជើងអត្ថបទឬ {{ns:user}}៖អត្តនាមអ្នកប្រើប្រាស់)៖",
        "log": "កំណត់ហេតុ",
        "logeventslist-submit": "បង្ហាញ",
        "all-logs-page": "កំណត់ហេតុសាធារណៈទាំងអស់",
        "undeletepagetext": "{{PLURAL:$1|ទំព័រខាងក្រោម|ទំព័រទាំងឡាយខាងក្រោម}}ត្រូវបានលុបចោលហើយ ប៉ុន្តែវានៅមានរក្សាទុកក្នុងឃ្លាំងសំងាត់ដែលអាចអោយធ្វើការស្ដារទំព័រនោះឡើងវិញបា។\n\nឃ្លាំងសំងាត់អាចនឹងត្រូវបានបោសសម្អាតជាប្រចាំ។",
        "undelete-fieldset-title": "ស្តារកំណែឡើងវិញ",
        "undeleteextrahelp": "ដើម្បីស្ដារប្រវត្តិទាំងមូលរបស់ទំព័រនេះឡើងវិញ សូមទុកប្រអប់គូសទាំងអោយនៅទំនេររួចចុចលើប៊ូតុង '''''{{int:undeletebtn}}'''''។\n\nដើម្បីស្ដារប្រវត្តិដោយផ្នែក សូមគូសក្នុងប្រអប់ខាងមុខកំណែដែលចង់ស្ដារ រួចចុចលើប៊ូតុង '''''{{int:undeletebtn}}'''''។",
-       "undeleterevisions": "$1 {{PLURAL:$1|á\9e\80á\9f\86á\9e\8eá\9f\82â\80\8bâ\80\8b}} á\9e\94á\9e¶á\9e\93â\80\8bá\9e\8aá\9e¶á\9e\80á\9f\8bâ\80\8bá\9e\85á\9e¼á\9e\9bá\9e\80á\9f\92á\9e\93á\9e»á\9e\84á\9e\83á\9f\92á\9e\9bá\9e¶á\9f\86á\9e\84á\9e\9fá\9f\86á\9e\84á\9e¶á\9e\8fá\9f\8b",
+       "undeleterevisions": "$1 {{PLURAL:$1|á\9e\80á\9f\86á\9e\8eá\9f\82â\80\8bâ\80\8b}} á\9e\8fá\9f\92á\9e\9aá\9e¼á\9e\9cá\9e\94á\9e¶á\9e\93á\9e\9bá\9e»á\9e\94á\9e\85á\9f\84á\9e\9b",
        "undeletehistory": "ប្រសិនបើអ្នកស្ដារទំព័រនេះឡើងវិញ រាល់កំណែទាំងអស់នឹងត្រូវបានស្ដារឡើងវិញក្នុងប្រវត្តិ។\n\nប្រសិនបើទំព័រថ្មីមួយដែលមានឈ្មោះដូចគ្នាត្រូវបានបង្កើតបន្ទាប់ពីការលុបចោល នោះកំណែដែលបានស្ដារនឹងត្រូវបង្ហាញក្នុងប្រវត្តិមុនៗ។",
        "undeletehistorynoadmin": "ទំព័រនេះត្រូវបានលុបចោលហើយ។\nមូលហេតុចំពោះការលុបចេញ​គឺត្រូវបានបង្ហាញនៅក្នុង​ចំណារពន្យល់ខាងក្រោម ជាមួយគ្នានឹងសេចក្តីលំអិតនៃ​អ្នកប្រើប្រាស់​ដែលបានធ្វើការកែប្រែ​ទំព័រនេះ​មុនពេលវាត្រូវបាន​លុបចោល។\nឃ្លាពិតនៃ​កំណែ​​ដែលត្រូវបានលុបចោលអាចមើលបានសំរាប់តែ​អ្នកអភិបាលប៉ុណ្ណោះ។",
        "undelete-revision": "កំណែប្រែដែលបាន​លុបចោល​នៃ $1 (នៅថ្ងៃ​ $4, នៅម៉ោង​ $5) ដោយ​ $3៖",
        "undeleteviewlink": "មើល",
        "undeleteinvert": "ក្រៅពីនោះ",
        "undeletecomment": "មូលហេតុ៖",
-       "cannotundelete": "á\9e\88á\9e\94á\9f\8bá\9e\9bá\9e»á\9e\94á\9e\98á\9e·á\9e\93á\9e\9fá\9e\98á\9f\92á\9e\9aá\9f\81á\9e\85á\9f\96​$1",
+       "cannotundelete": "á\9e\80á\9e¶á\9e\9aá\9e\88á\9e\94á\9f\8bá\9e\9bá\9e»á\9e\94á\9e\98á\9e½á\9e\99á\9e\85á\9f\86á\9e\93á\9e½á\9e\93á\9e¬á\9e\91á\9e¶á\9f\86á\9e\84á\9e¢á\9e\9fá\9f\8bá\9e\92á\9f\92á\9e\9cá\9e¾á\9e\98á\9e·á\9e\93á\9e\94á\9e¶á\9e\93á\9e\9fá\9e\98á\9f\92á\9e\9aá\9f\81á\9e\85á\9f\96 ​$1",
        "undeletedpage": "'''$1 ត្រូវបានស្តារឡើងវិញហើយ'''\n\nសូម​ចូល​ទៅ [[Special:Log/delete|កំណត់ហេតុ​នៃ​ការលុប]] ដើម្បី​ពិនិត្យ​មើល​កំណត់ត្រា​នៃ​ការលុប​និង​ការ​ស្ដារ​ឡើង​វិញ​។",
        "undelete-header": "មើលទំព័រដែលត្រូវបានលុបចោលថ្មីៗក្នុង[[Special:Log/delete|កំណត់ហេតុនៃការលុបចោល]]។",
        "undelete-search-title": "ស្វែងរកទំព័រដែលត្រូវបានលុបចោល",
        "sp-contributions-newbies-sub": "ចំពោះគណនីថ្មីៗ",
        "sp-contributions-newbies-title": "ការរួមចំណែករបស់អ្នកប្រើប្រាស់ចំពោះគណនីថ្មី",
        "sp-contributions-blocklog": "កំណត់ហេតុនៃការហាមឃាត់",
-       "sp-contributions-deleted": "á\9e\80á\9e¶á\9e\9aá\9e\9aá\9e½á\9e\98á\9e\85á\9f\86á\9e\8eá\9f\82á\9e\80á\9e\8aá\9f\82á\9e\9bá\9e\8fá\9f\92á\9e\9aá\9e¼á\9e\9cá\9e\94á\9e¶á\9e\93á\9e\9bá\9e»á\9e\94",
+       "sp-contributions-deleted": "á\9e\80á\9e¶á\9e\9aá\9e\9aá\9e½á\9e\98á\9e\85á\9f\86á\9e\8eá\9f\82á\9e\80á\9e\9aá\9e\94á\9e\9fá\9f\8b{{GENDER:$1|á\9e¢á\9f\92á\9e\93á\9e\80á\9e\94á\9f\92á\9e\9aá\9e¾á\9e\94á\9f\92á\9e\9aá\9e¶á\9e\9fá\9f\8b}}á\9e\8aá\9f\82á\9e\9bá\9e\8fá\9f\92á\9e\9aá\9e¼á\9e\9cá\9e\94á\9e¶á\9e\93á\9e\9bá\9e»á\9e\94á\9e\85á\9f\84á\9e\9b",
        "sp-contributions-uploads": "ឯកសារផ្ទុកឡើង",
        "sp-contributions-logs": "កំណត់​ហេតុ​",
        "sp-contributions-talk": "ការពិភាក្សា",
-       "sp-contributions-userrights": "ការគ្រប់គ្រងសិទ្ធិអ្នកប្រើប្រាស់",
+       "sp-contributions-userrights": "ការគ្រប់គ្រងសិទ្ធិ{{GENDER:$1|អ្នកប្រើប្រាស់}}",
        "sp-contributions-blocked-notice": "អ្នកប្រើប្រាស់នេះត្រូវបានហាមឃាត់ហើយនាពេលនេះ។\nកំណត់ត្រាស្ដីពីការហាមឃាត់ចុងក្រោយមានបង្ហាញដូចខាងក្រោមនេះ៖",
        "sp-contributions-blocked-notice-anon": "អាសយដ្ឋានIPនេះត្រូវបានហាមឃាត់ហើយនាពេលនេះ។\nកំណត់ត្រាស្ដីពីការហាមឃាត់ចុងក្រោយមានបង្ហាញដូចខាងក្រោមនេះ៖",
        "sp-contributions-search": "ស្វែងរកការរួមចំណែក",
        "delete_and_move_text": "==ការលុបជាចាំបាច់==\n\"[[:$1]]\"ដែលជាទីតាំងទំព័រត្រូវបញ្ជូនទៅ មានរួចជាស្រេចហើយ។\nតើអ្នកចង់លុបវាដើម្បីជាវិធីសម្រាប់ប្តូរទីតាំងទេ?",
        "delete_and_move_confirm": "យល់ព្រម​លុប​ទំព័រ​នេះ",
        "delete_and_move_reason": "ត្រូវបានលុបដើម្បីផ្លាស់ប្តូរទីតាំងពី \"[[$1]]\"",
-       "selfmove": "á\9e\85á\9f\86á\9e\8eá\9e\84á\9e\87á\9e¾á\9e\84á\9e\94á\9f\92á\9e\9aá\9e\97á\9e\96á\9e\93á\9e·á\9e\84á\9e\85á\9f\86á\9e\8eá\9e\84á\9e\87á\9e¾á\9e\84á\9e\82á\9f\84á\9e\9bá\9e\8aá\9f\85á\9e\82á\9eºá\9e\8fá\9f\82á\9e\98á\9e½á\9e\99á\9f\94\n\nមិនអាចប្ដូរទីតាំងទំព័រមួយទៅលើខ្លួនវាបានទេ។",
+       "selfmove": "á\9e\85á\9f\86á\9e\8eá\9e\84á\9e\87á\9e¾á\9e\84á\9e\8aá\9e¼á\9e\85á\9e\82á\9f\92á\9e\93á\9e¶á\9f\94 មិនអាចប្ដូរទីតាំងទំព័រមួយទៅលើខ្លួនវាបានទេ។",
        "immobile-source-namespace": "មិនអាចប្តូរទីតាំងទំព័រក្នុងលំហឈ្មោះ \"$1\" បានទេ",
        "immobile-target-namespace": "មិនអាចប្តូរទីតាំងទំព័រទៅលំហឈ្មោះ \"$1\" បានទេ",
        "immobile-target-namespace-iw": "តំណភ្ជាប់អន្តរវិគីមិនអាចប្រើជាទំព័រគោលដៅសំរាប់ធ្វើការប្ដូរទីតាំងទំព័រទេ។",
        "fix-double-redirects": "បន្ទាន់សម័យនូវរាល់ការបញ្ជូនបន្តដែលសំដៅទៅរកចំណងជើងដើម",
        "move-leave-redirect": "បន្សល់ទុកតំនបញ្ជូនបន្តនៅទំព័រចាស់",
        "protectedpagemovewarning": "'''ប្រយ័ត្ន៖''' ទំព័រនេះ​ត្រូវបានការពារ។ ដូច្នេះ​មានតែ​អ្នកប្រើប្រាស់​ដែល​មាន​អភ័យឯកសិទ្ឋិជាអភិបាលប៉ុណ្ណោះដែលអាចប្តូរទីតាំងវា។\n\nកំណត់ត្រាស្ដីពីការរាំងការពារចុងក្រោយមានបង្ហាញដូចខាងក្រោមនេះ៖",
-       "semiprotectedpagemovewarning": "'''សំគាល់៖''' ទំព័រនេះ​បានត្រូវ​ចាក់សោ។ ដូច្នេះ​មានតែអ្នកប្រើប្រាស់​ដែលបានចុះឈ្មោះ​ប៉ុណ្ណោះដែលអាចប្ដូរទីតាំងវាបាន។\n\nកំណត់ត្រាស្ដីពីការចាក់សោចុងក្រោយមានបង្ហាញដូចខាងក្រោមនេះ៖",
-       "move-over-sharedrepo": "== ឯកសារមានហើយ ==\n[[:$1]] មានរួចហើយនៅលើថតឯកសាររួម។ ការប្ដូរទីតាំងឯកសារមួយទៅកាន់ចំណងជើងនេះ នឹងត្រូវសរសេរជាន់ពីលើឯកសារដែលមានហើយ។",
+       "semiprotectedpagemovewarning": "<strong>សំគាល់៖</strong> ទំព័រនេះត្រូវបានការពារ ហេតុនេះមានតែអ្នកប្រើប្រាស់ដែលបានបញ្ជាក់ទទួលស្គាល់ស្វ័យប្រវត្តិប៉ុណ្ណោះដែលបាចប្ដូរទីតាំងវា។ \n\nកំណត់ហេតុចុងក្រោយត្រូវបានផ្ដល់ដូចខាងក្រោមសម្រាប់ជាព័ត៌មាន៖",
+       "move-over-sharedrepo": "[[:$1]] មានរួចហើយនៅលើថតឯកសាររួម។ ការប្ដូរទីតាំងឯកសារមួយទៅកាន់ចំណងជើងនេះ នឹងសរសេរជាន់ពីលើឯកសារដែលមានហើយ។",
        "file-exists-sharedrepo": "ឈ្មោះឯកសារដែលអ្នកបានជ្រើសរើសមានប្រើរួចហើយនៅក្នុងថតឯកសាររួម។\n\nសូមជ្រើសរើសឈ្មោះថ្មីមួយទៀត។",
        "export": "នាំទំព័រចេញ",
        "exporttext": "អ្នកអាចនាំចេញ អត្ថបទ និង ប្រវត្តិកែប្រែ នៃ​ មួយទំព័រ ឬ នៃ មួយសំណុំទំព័រ ទៅ ក្នុង ឯកសារ XML ។ ឯកសារ​ទាំងនេះ អាចត្រូវបាន នាំចេញទៅ វិគី ផ្សេង ដែលមានប្រើប្រាស់ មីឌាវិគី តាម រយះ [[Special:Import|នាំចូល ទំព័រ]]។\n\nដើម្បី នាំចេញ ទំព័រ, អ្នកត្រូវ បញ្ចូលចំណងជើង ក្នុងប្រអប់អត្ថបទ ខាងក្រោម, មួយចំណងជើង ក្នុងមួយបន្ទាត់, និង ជ្រើសយក កំណែ តាមបំណង របស់អ្នក (កំណែចាស់ ឬ កំណែថ្មី), រួមនឹង ប្រវត្តិ នៃ​ទំព័រ, ឬ ត្រឹមតែ កំណែបច្ចុប្បន្ន ដែលមានព័ត៌មាន អំពី កំណែប្រែ ចុងក្រោយ។\n\nក្នុងករណី បន្ទាប់ អ្នកអាចប្រើប្រាស់ តំណភ្ជាប់, ដូចជា [[{{#Special:Export}}/{{MediaWiki:Mainpage}}]] ចំពោះ ទំព័រ \"[[{{MediaWiki:Mainpage}}]]\"។",
        "import-upload": "ផ្ទុកឡើងទិន្នន័យ XML",
        "import-invalid-interwiki": "មិន​អាច​នាំ​ចូល​ពី​វិគី​ដែល​បាន​បញ្ជាក់​។",
        "importlogpage": "កំណត់ហេតុនៃការនាំចូល",
-       "import-logentry-upload-detail": "$1 {{PLURAL:$1|កំណែ}}",
-       "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|កំណែ}} ពី $2",
+       "import-logentry-upload-detail": "$1 {{PLURAL:$1|កំណែ|កំណែ}} ត្រូវបាននាំចូល",
+       "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|កំណែ|កំណែ}} ត្រូវបាននាំចូលពី $2",
        "tooltip-pt-userpage": "ទំព័រ​{{GENDER:|អ្នកប្រើប្រាស់​របស់អ្នក}}",
        "tooltip-pt-mytalk": "ទំព័រពិភាក្សា​​{{GENDER:|របស់អ្នក}}",
        "tooltip-pt-anontalk": "ការពិភាក្សាអំពីកំណែប្រែដែល​ធ្វើ​ឡើង​ចេញ​ពីអាសយដ្ឋាន IP នេះ",
        "lastmodifiedatby": "ទំព័រនេះត្រូវបានកែប្រែចុងក្រោយដោយ $3 នៅវេលា $2 $1។",
        "othercontribs": "ផ្អែកលើការងាររបស់$1។",
        "others": "ផ្សេងៗទៀត",
-       "siteusers": "{{PLURAL:$2|អ្នកប្រើប្រាស់|អ្នកប្រើប្រាស់}} {{SITENAME}} $1",
+       "siteusers": "{{PLURAL:$2|{{GENDER:$1|អ្នកប្រើប្រាស់}}|អ្នកប្រើប្រាស់}}{{SITENAME}} $1",
        "anonusers": "{{PLURAL:$2|អ្នកប្រើប្រាស់|អ្នកប្រើប្រាស់}} {{SITENAME}} ជាអនាមិក $1",
        "creditspage": "ក្រេឌិតទំព័រ",
        "nocredits": "គ្មានព័ត៌មានក្រេឌីតសំរាប់ទំព័រនេះទេ។",
        "scarytranscludetoolong": "[URL វែងជ្រុល]",
        "deletedwhileediting": "'''ប្រយ័ត្ន''' ៖ ទំព័រនេះបានត្រូវលុបចោល បន្ទាប់ពីអ្នកបានចាប់ផ្តើមកែប្រែ!",
        "confirmrecreate": "អ្នកប្រើប្រាស់ [[User:$1|$1]] ([[User talk:$1|ការពិភាក្សា]]) {{GENDER:$1|បានលុប}} ទំព័រនេះចោលបន្ទាប់ពីអ្នកចាប់ផ្ដើមកែប្រែវា ដោយមានហេតុផលថា៖\n\n៖ <em>$2</em>\n\nសូមអះអាងថាអ្នកពិតជាចង់បង្កើតទំព័រនេះឡើងវិញពិតប្រាកដមែន។",
-       "confirmrecreate-noreason": "អ្នកប្រើប្រាស់ [[User:$1|$1]] ([[User talk:$1|talk]]) បានលុបទំព័រនេះចោលបន្ទាប់ពីអ្នកចាប់ផ្ដើមកែប្រែវា។ សូមអះអាងថាអ្នកពិតជាចង់បង្កើតទំព័រនេះឡើងវិញមែន។\n\nសូមអះអាងថាអ្នកពិតជាចង់បង្កើតទំព័រនេះឡើងវិញពិតប្រាកដមែន។",
+       "confirmrecreate-noreason": "អ្នកប្រើប្រាស់ [[User:$1|$1]] ([[User talk:$1|talk]]) {{GENDER:$1|បានលុប}}ទំព័រនេះចោលបន្ទាប់ពីអ្នកចាប់ផ្ដើមកែប្រែវា។ សូមអះអាងថាអ្នកពិតជាចង់បង្កើតទំព័រនេះឡើងវិញមែន។",
        "recreate": "បង្កើតឡើងវិញ",
        "confirm_purge_button": "យល់ព្រម",
        "confirm-purge-top": "សំអាតឃ្លាំងសំងាត់(cache)នៃទំព័រនេះ?",
        "signature": "[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1|ការពិភាក្សា]])",
        "version": "កំណែ",
        "version-extensions": "ផ្នែកបន្ថែមដែលបានដំឡើង",
-       "version-skins": "សំបក",
+       "version-skins": "សំបកដំឡើងរួច",
        "version-specialpages": "ទំព័រពិសេសៗ",
        "version-variables": "អថេរ",
        "version-antispam": "ការបង្ការស្ប៉ាម",
        "logentry-newusers-create2": "គណនីអ្នកប្រើប្រាស់ $3 {{GENDER:$2|ត្រូវបានបង្កើត}} ដោយ $1",
        "logentry-newusers-byemail": "គណនីអ្នកប្រើប្រាស់ $3 ត្រូវបាន {{GENDER:$2|បង្កើត}} ដោយ $1 ហើយពាក្យសម្ងាត់ត្រូវបានផ្ញើរតាមអ៊ីមែល",
        "logentry-newusers-autocreate": "គណនីអ្នកប្រើប្រាស់ $1 {{GENDER:$2|ត្រូវបានបង្កើត}} ដោយស្វ័យប្រវត្តិ",
-       "logentry-rights-rights": "$1 {{GENDER:$2|បានផ្លាស់ប្ដូរ}}សមាជិកភាពរបស់ $3 ពី $4 ទៅជា $5",
+       "logentry-rights-rights": "$1 {{GENDER:$2|បានផ្លាស់ប្ដូរ}}សមាជិកភាពរបស់ {{GENDER:$6|$3}} ពី $4 ទៅជា $5",
        "logentry-rights-rights-legacy": "$1 {{GENDER:$2|បានផ្លាស់ប្ដូរ}}សមាជិកភាពរបស់ $3",
        "logentry-rights-autopromote": "$1 {{GENDER:$2|ត្រូវបានតំឡើង}}សមាជិកភាពពី $4 ជា $5 ដោយស្វ័យប្រវត្តិ",
        "logentry-upload-upload": "$1 {{GENDER:$2|បានផ្ទុកឡើង}} $3",
index 14c1709..f1f0df1 100644 (file)
@@ -69,7 +69,8 @@
                        "Garam",
                        "렌즈",
                        "CYAN",
-                       "Nuevo Paso"
+                       "Nuevo Paso",
+                       "Doyoon1995"
                ]
        },
        "tog-underline": "링크에 밑줄 긋기:",
        "accmailtext": "[[User talk:$1|$1]]님의 비밀번호를 임의로 만들어 $2(으)로 보냈습니다. 로그인하고 나서 <em>[[Special:ChangePassword|비밀번호를 바꿀]]</em> 수 있습니다.",
        "newarticle": "(새 문서)",
        "newarticletext": "아직 없는 문서의 링크를 따라왔습니다.\n새 문서를 만들려면 아래 상자에 내용을 입력하면 됩니다. (자세한 내용은 [$1 도움말 문서]를 참조하세요)\n만약 잘못 찾아왔다면, 브라우저의 '''뒤로''' 버튼을 눌러 주세요.",
-       "anontalkpagetext": "----\n여기는 계정을 만들지 않았거나 사용하고 있지 않은 익명 사용자를 위한 토론 문서입니다.\n익명 사용자를 구별하기 위해서는 숫자로 된 IP 주소를 사용해야만 합니다.\nIP 주소는 여러 사용자가 공유할 수 있습니다.\n자신과 관계없는 의견이 자신에게 남겨져 있어 불쾌하다고 생각하는 익명 사용자는 [[Special:CreateAccount|계정을 만들고]] [[Special:UserLogin|로그인해서]] 나중에 다른 익명 사용자에게 줄 혼란을 줄일 수 있습니다.",
+       "anontalkpagetext": "----\n여기는 계정을 만들지 않았거나 사용하고 있지 않은 익명 사용자를 위한 토론 문서입니다. 익명 사용자를 구별하기 위해서는 숫자로 된 IP 주소를 사용해야만 합니다. IP 주소는 여러 사람이 공유할 수 있습니다. 자신과 관계없는 의견이 남겨져 있어 불쾌하다는 생각이 든다면 [[Special:CreateAccount|계정을 만들고]] [[Special:UserLogin|로그인해서]] 다른 사용자들에게 줄 혼란을 줄일 수 있습니다.",
        "noarticletext": "이 문서가 현재 존재하지 않습니다.\n이 문서와 제목이 비슷한 문서가 있는지 [[Special:Search/{{PAGENAME}}|검색하거나]],\n이 문서에 관련된 <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} 기록]을 확인하거나,\n문서를 직접 [{{fullurl:{{FULLPAGENAME}}|action=edit}} 생성]</span>할 수 있습니다.",
        "noarticletext-nopermission": "이 문서가 현재 존재하지 않습니다.\n이 문서와 제목이 비슷한 문서가 있는지 [[Special:Search/{{PAGENAME}}|검색하거나]], 이 문서에 관련된 <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} 기록]을 확인할 수 있습니다.</span> 그러나 이 문서를 만들 수 있는 권한은 없습니다.",
        "missing-revision": "\"{{FULLPAGENAME}}\"이라는 문서의 #$1판이 존재하지 않습니다.\n\n이 문제는 주로 삭제된 문서를 가리키는 오래된 문서 역사 링크로 인해 발생합니다.\n자세한 내용은 [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} 삭제 기록]에서 확인할 수 있습니다.",
        "rcfilters-filter-humans-label": "사람 (봇이 아님)",
        "rcfilters-filter-humans-description": "사람이 한 편집.",
        "rcfilters-filtergroup-reviewstatus": "검토 상태",
+       "rcfilters-filter-reviewstatus-unpatrolled-description": "점검한 것으로 수동·자동으로 표시하지 않은 편집.",
        "rcfilters-filter-reviewstatus-unpatrolled-label": "점검 안 됨",
        "rcfilters-filter-reviewstatus-manual-description": "수동으로 검토된 편집들.",
        "rcfilters-filter-reviewstatus-manual-label": "수동으로 검토됨",
+       "rcfilters-filter-reviewstatus-auto-description": "작업을 점검한 것으로 자동으로 표시한 고급 사용자의 편집.",
        "rcfilters-filter-reviewstatus-auto-label": "점검 면제자",
        "rcfilters-filtergroup-significance": "의미",
        "rcfilters-filter-minor-label": "사소한 편집",
        "statistics-files": "올려져 있는 파일",
        "statistics-edits": "{{SITENAME}} 설치 이후 문서의 전체 편집 수",
        "statistics-edits-average": "문서당 평균 편집 수",
-       "statistics-users": "등록된 [[Special:ListUsers|사용자]]",
+       "statistics-users": "등록된 사용자",
        "statistics-users-active": "활동적인 사용자",
        "statistics-users-active-desc": "최근 {{PLURAL:$1|$1일}} 동안 활동한 사용자",
        "pageswithprop": "문서 속성이 있는 문서",
        "deadendpages": "막다른 문서 목록",
        "deadendpagestext": "{{SITENAME}} 내의 다른 문서로 나가는 링크가 없는 문서의 목록입니다.",
        "protectedpages": "보호된 문서 목록",
+       "protectedpages-filters": "필터",
        "protectedpages-indef": "오른쪽 조건에 맞는 보호만 보기",
        "protectedpages-summary": "이 페이지는 현재 보호된 기존 문서를 나열합니다. 만들기 보호된 문서 제목 목록을 보려면 [[{{#special:ProtectedTitles}}|{{int:protectedtitles}}]]를 보세요.",
        "protectedpages-cascade": "연쇄적 보호만 보기",
index b41ab45..b3b45cf 100644 (file)
        "lineno": "Linn $1:",
        "compareselectedversions": "Ausgewielt Versioune vergläichen",
        "showhideselectedversions": "Erausgesicht Versioune weisen/verstoppen",
-       "editundo": "zréck",
+       "editundo": "réckgängeg maachen",
        "diff-empty": "(Keen Ënnerscheed)",
        "diff-multi-sameuser": "({{PLURAL:$1|Eng Tëscheversioun|$1 Tëscheversioune}} vun deemselwechte Benotzer net gewisen)",
        "diff-multi-otherusers": "({{PLURAL:$1|Eng Tëscheversioun|$1 Tëscheversioune}} vun {{PLURAL:$2|engem anere|$2}} Benotzer {{PLURAL:$1|gëtt|ginn}} net gewisen)",
        "deadendpages": "Sakgaasse-Säiten",
        "deadendpagestext": "Dës Säite si mat kenger anerer Säit op {{SITENAME}} verlinkt.",
        "protectedpages": "Gespaart Säiten",
+       "protectedpages-filters": "Filteren:",
        "protectedpages-indef": "Nëmme onbegrenzt-gespaarte Säite weisen",
        "protectedpages-summary": "Op dëser Säit stinn all déi Säiten déi elo protegéiert sinn. Fir d'Lëscht vun de Säiten déi fir d'Uleeë gespaart sinn, kuckt [[{{#special:ProtectedTitles}}|{{int:protectedtitles}}]].",
        "protectedpages-cascade": "Nëmme Säiten déi duerch Kaskade gespaart sinn",
index f713b72..498590d 100644 (file)
@@ -55,7 +55,7 @@
        "tog-watchlisthideminor": "Klein bewirkinge op mien volglies verberge",
        "tog-watchlisthideliu": "Bewirkinge van aangemelde gebroekers op mien volglies versjtaeke",
        "tog-watchlistreloadautomatically": "Herlaaj de volglies autematis es 'n filter is verangerd (JavaScript vereis)",
-       "tog-watchlistunwatchlinks": "Veug direkte (neet) betrachte-links toe aan pagina's die op de wachlies staon (JavaScript vereis)",
+       "tog-watchlistunwatchlinks": "Veug direkte (neet) betrachte-links ({{int:Watchlist-unwatch}}/{{int:Watchlist-unwatch-undo}}) toe aan pagina's die op de wachlies staon (JavaScript vereis)",
        "tog-watchlisthideanons": "Bewirkinge van anonieme gebroekers op mien volglies versjtaeke",
        "tog-watchlisthidepatrolled": "Gemarkeerde verangeringe op mien volglies verberge",
        "tog-watchlisthidecategorization": "Verberg categorisatie  van  pagina's",
        "password-login-forbidden": "'t Gebroek van deze gebroekersnaam mit dit wachwoord is neet toegesjtange.",
        "mailmypassword": "Mail mich e nuuj wachwaord",
        "passwordremindertitle": "Nuuj tiedelik wachwaord van {{SITENAME}}",
-       "passwordremindertext": "Emes (waorsjienlik dich zelf) haet vanaaf IP-adres $1 'n nuuj wachwoord veur {{SITENAME}} ($4) verzoch. 't Nuuj wachwoord veur gebroeker \"$2\" is \"$3\". Es dat dien bedoeling waor, mèl diech daan noe aan en kees 'n nuuj wachwoord. 't Tiedelik wachwoord verluip euver {{PLURAL:$5|$5 daag|$5 daag}}.\n\nEs emes anders dit verzeuk heet gedoon, of wens te diech dien wachwoord weer herinners en 't neet mie wèls wiezige, negeer dan dit berich en blief dien aud wachwoord gebroeke.",
+       "passwordremindertext": "Emes haet vanaaf IP-adres $1 'n nuuj wachwoord veur {{SITENAME}} ($4) verzoch. 't Nuuj wachwaord veur gebroeker \"$2\" is \"$3\". Es det dien bedoeling woor, melj dich den noe aan en kees e nuuj wachwaord. 't Tiedelik wachwaord verluip euver {{PLURAL:$5|einen daag|$5 daag}}.\n\nEs emes anges dit verzeuk haet gedaon, of wens se dich die wachwaord weer herinjers en 't neet mie wils verangere, negeer den dit besjeid en blief dien aad wachwaord gebroeke.",
        "noemail": "D'r is gein geregistreerd e-mailadres veur \"$1\".",
        "noemailcreate": "Doe mós e geljig e-mailadres ópgaeve.",
        "passwordsent": "D'r is 'n nuui wachwaord verzonde nao 't e-mailadres dat geregistreerd sjtit veur \"$1\".\nGelieve na ontvangst opnieuw aan te melden.",
        "blocked-notice-logextract": "Deze gebroeker is noe geblok.\nDe leste bloklogregel wuuertj hiejónger t'r raodpleging gegaeve:",
        "clearyourcache": "<strong>Lèt op:</strong> Nao 't opsjlaon mós te diene browsercache wisse óm de verangeringe te zeen:\n* <strong>Firefox / Safari:</strong> hauw <em>Shift</em> ingedrök terwiels te op <em>Vernuuj</em> kliks of duujs op <em>Ctrl-F5</em> of <em>Ctrl-R</em> (<em>⌘-R</em> op 'ne Mac)\n* <strong>Google Chrome:</strong> duuj op <em>Ctrl-Shift-R</em> (<em>⌘-Shift-R</em> op 'ne Mac)\n* <strong>Internet Explorer:</strong> hauw <em>Ctrl</em> ingeduujt terwiels te op <em>Vernuuj</em> kliks of duujs op <em>Ctrl-F5</em>\n* <strong>Opera:</strong> gank nao <em>Menu → Instèllinge</em> (<em>Opera → Veurkäöre</em> op 'ne Mac) en den nao <em>Privaatheid & beveiliging → Wis browsergegaeves → Tiejelike aafbiljinge en bestenj</em>.",
        "usercssyoucanpreview": "'''Tip:''' Gebroek de knóp '{{int:showpreview}}' om dien nuuj CSS te teste veurdets te opsjleis.",
+       "userjsonyoucanpreview": "'''Tip:''' Gebroek de knóp '{{int:showpreview}}' om dien nuuj JSON te teste veurdets te opsjleis.",
        "userjsyoucanpreview": "'''Tip:''' Gebroek de knóp '{{int:showpreview}}' om dien nuuj JS te teste veurdets te opsjleis.",
        "usercsspreview": "<strong>Dit is allein 'n veurvertuining van dien perseunlike css, deze is neet opgeslage!</strong>",
+       "userjsonpreview": "<strong>'''Lèt op: doe tes noe dien persuunlik JSON.\nDe pagina is neet opgesjlage!</strong>",
        "userjspreview": "<strong>'''Lèt op: doe tes noe dien persuunlik JavaScript.\nDe pagina is neet opgesjlage!</strong>",
        "sitecsspreview": "'''Dit is allein 'n veurvertuin van de CSS.'''\n'''Deze is nog neet opgesjlage!'''",
+       "sitejsonpreview": "<strong>Dit is allein 'n veurvertuin van de JSON.\nDeze is nog neet opgesjlage!</strong>",
        "sitejspreview": "<strong>Dit is allein 'n veurvertuin van de JavaScriptcode.\nDe code is nog neet opgesjlage!</strong>",
-       "userinvalidconfigtitle": "'''Waarsjoewing:''' d'r is gein skin \"$1\". \nLèt op: dien eige .css- en .js-pagina's beginne mèt  'ne klein lètter, beveurbeeld {{ns:user}}:Naam/vector.css in plaats van {{ns:user}}:Naam/Vector.css.",
+       "userinvalidconfigtitle": "<strong>Waarsjoewing:</strong> d'r is gein skin \"$1\". \nLèt op: dien eige .css-, .json- en .js-pagina's beginne mèt  'ne klein lètter, beveurbeeld {{ns:user}}:Naam/vector.css in plaats van {{ns:user}}:Naam/Vector.css.",
        "updated": "(Biegewèrk)",
        "note": "'''Opmirking:'''",
        "previewnote": "<strong>Lèt op: dit is 'n controlepazjena; dien teks is nog neet opgesjlage!</strong>",
        "longpageerror": "Fout: De teks diese höbs toegevoegd haet is {{PLURAL:$1|'ne kilobyte|$1 kilobyte}} groet, wat groeter is es 't maximum van {{PLURAL:$2|'ne kilobyte|$2 kilobyte}}. Opslaon is neet meugelik.'''",
        "readonlywarning": "WAARSJUWING: De database is vasgezat veur óngerhawd, dus op 't mement kins se dien verangeringe neet opsjlaon.</strong>\n\nDe kins dien tèks 't biste opsjlaon in 'n tèksbesjtand om 't later hie nog es te prebere.\n\nt Is geslaote door de systeembehieërder waenger: $1",
        "protectedpagewarning": "'''WAARSJOEWING: Dees pagina is besjirmp zoedet ze allein door gebroekers mit administratorrechte kint waere verangerd.'''\nDe lèste logbookregel sjteit hiejónger:",
-       "semiprotectedpagewarning": "'''Lèt op:''' Dees pagina is beveilig en kin allein door geregistreerde gebroekers bewirk waere.\nDe lèste logbookregel steit hiejónger:",
+       "semiprotectedpagewarning": "<strong>Lèt op:</strong> Dees pagina is beveilig en kin allein door autobevestigde geregistreerde gebroekers bewirk waere.\nDe lèste logbookregel steit hiejónger:",
        "cascadeprotectedwarning": "<strong>Waarschuwing:</strong> Dees pagina is beveilig en kin allein door beheerders mit [[Special:ListGroupRights|specefieke rechte]] bewirk waere, omdet dees is opgenaome in de volgende {{PLURAL:$1|pagina|pagina's}} {{PLURAL:$1|dae|die}} beveilig {{PLURAL:$1|is|zeen}} mit de cascade-optie:",
        "titleprotectedwarning": "'''WAORSJUWING: Deze pagina is beveilig zodet allein inkele gebroekers 'm kinne aanmake. De beneuds [[Special:ListGroupRights|speciale rechte]].'''\nDe lèste logbookregel vólg hier:",
        "templatesused": "Op dees pagina {{PLURAL:$1|gebroek sjabloon|gebroekde sjablone}}:",
        "rcfilters-filter-humans-label": "Minsjelik (geine bot)",
        "rcfilters-filter-humans-description": "Bewirkinge door miensjelike gebroekers.",
        "rcfilters-filtergroup-reviewstatus": "Beoeardeilingsstaot",
+       "rcfilters-filter-reviewstatus-unpatrolled-description": "Bewirkinge die neet handjmaesig of autematis zint gecontroleerd.",
        "rcfilters-filter-reviewstatus-unpatrolled-label": "Óngecontroleerd",
+       "rcfilters-filter-reviewstatus-manual-description": "Bewirkinge die handjmaesig zint gecontroleerd.",
+       "rcfilters-filter-reviewstatus-manual-label": "Handjmaesig gecontroleerd",
+       "rcfilters-filter-reviewstatus-auto-description": "Bewirkinge door gevörderde gebroekers van waem 't werk autematis weurt gecontroleerd.",
+       "rcfilters-filter-reviewstatus-auto-label": "Autematis gecontroleerd",
        "rcfilters-filtergroup-significance": "Wichtigheid",
        "rcfilters-filter-minor-label": "Klein bewirkinge",
        "rcfilters-filter-minor-description": "Bewirkinge die zeen gelabeld door de gebroeker es klein.",
        "statistics-files": "Bestenj",
        "statistics-edits": "Paginabewerkinge sins t begin van {{SITENAME}}",
        "statistics-edits-average": "Gemiddeld aantal bewerkinge per pagina",
-       "statistics-users": "Geregistreerde [[Special:ListUsers|gebroekers]]",
+       "statistics-users": "Geregistreerde gebroekers",
        "statistics-users-active": "Actieve gebroekers",
        "statistics-users-active-desc": "Gebroekers die in de aafgeloupe {{PLURAL:$1|daag|$1 daag}} 'ne hanjeling höbbe oetgevoerd",
        "pageswithprop": "Pagina's mit pagina-eigensjap",
        "deadendpages": "Doedloupende pazjena's",
        "deadendpagestext": "De ongerstäönde pagina's verwieze neet nao anger pagina's in {{SITENAME}}.",
        "protectedpages": "Besjörmde pagina's",
+       "protectedpages-filters": "Filters:",
        "protectedpages-indef": "Allein blokkades zonger verloupdatum",
        "protectedpages-summary": "Dees pagina bevat 'n lies met beveiligde pagina's. Zuuch [[{{#special:ProtectedTitles}}|{{int:protectedtitles}}]] veur 'n lies van pagina's die neet moge waere aangemaak.",
        "protectedpages-cascade": "Allein beveiliginge mit de cascade-optie",
        "fix-double-redirects": "Alle doorverwiezinge biewerke die verwieze nao de originele paginanaam",
        "move-leave-redirect": "'n Doorverwiezing achterlaote",
        "protectedpagemovewarning": "'''Waorsjoewing: Dees pazjena is besjermp zoedat ze allein doer gebroekers mit administratorrechte kint weure verplaats.'''\nDe lèste logbookregel steit hierónger:",
-       "semiprotectedpagemovewarning": "'''Let op:''' Dees pazjena is beveilig en kin allein door geregistreerde gebroekers verplaats waere.\nDe lèste logbookregel steit hiejónger:",
+       "semiprotectedpagemovewarning": "<strong>Let op:</strong> Dees pazjena is beveilig en kin allein door geregistreerde gebroekers verplaats waere.\nDe lèste logbookregel steit hiejónger:",
        "move-over-sharedrepo": "[[:$1]] besteit al in 'ne gedeildje mediadatabank.\nE bestandj hiehaer verplaatse euversjrief 't gedeildj bestandj.",
        "file-exists-sharedrepo": "Deze bestandjsnaam besteit al in 'ne gedeildje mediadatabank.\nKees 'nen angere bestandjsnaam.",
        "export": "Exporteer pagina's",
        "file-info-png-looped": "herhaolendj",
        "file-info-png-repeat": "$1 {{PLURAL:$1|kieër|kieër}} aafgespeelj",
        "file-info-png-frames": "$1 {{PLURAL:$1|kader|kadere}}",
+       "file-no-thumb-animation": "<strong>Lit op: óm technische bepirkinge kónne gein miniature waere gemaak vwur dit bestandj.</strong>",
+       "file-no-thumb-animation-gif": "<strong>Lit op: óm technische bepirkinge kónne gein hoge-resoluusje GIF-plaetjes wie dit waere gemaak.</strong>",
        "newimages": "Nuuj plaetjes",
        "imagelisttext": "Hie volg 'n lies mit $1 {{PLURAL:$1|aafbeilding|aafbeildinge}} geordend $2.",
        "newimages-summary": "Op dees speciaal pazjena waere de meis recènt toegevoogde bestenj weergegaeve.",
        "invalidateemail": "E-mailbevestiging annulere",
        "notificationemail_subject_changed": "geregistreerd e-mailadres van {{SITENAME}} is verangerd",
        "notificationemail_subject_removed": "geregistreerd e-mailadres van {{SITENAME}} is eweggehaold",
+       "notificationemail_body_changed": "Emes, wersjienlik doe, haet vanaaf IP-adres $1, 't e-mailadres van de konto \"$2\" op {{SITENAME}} verangerd nao \"$3\". \n\nEs det neet van dich kump, num den drek kóntak op mit de sitebehieërder.",
+       "notificationemail_body_removed": "Emes, wersjienlik doe, haet vanaaf IP-adres $1, 't e-mailadres van de konto \"$2\" op {{SITENAME}} eweggehaold. \n\nEs det neet van dich kump, num den drek kóntak op mit de sitebehieërder.",
        "scarytranscludedisabled": "[Interwikitransclusie is oetgesjakeld]",
        "scarytranscludefailed": "[Sjabloon $1 kós neet opgehaold waer]",
        "scarytranscludefailed-httpstatus": "[Sjabloon $1 kós neet waere opgehaold: HTTP $2]",
        "scarytranscludetoolong": "[URL is te lank]",
        "deletedwhileediting": "'''Waorsjoewing''': Dees pazjena is gewis naodats doe bis begós mit bewirke!",
-       "confirmrecreate": "Gebroeker [[User:$1|$1]] ([[User talk:$1|euverlèk]]) heet dees pagina eweggesjaf naodats doe mèt bewirke begós mèt de rae:\n: ''$2''\nBevesteg estebleef dats te dees pazjena ech obbenuujts wils aanmake.",
-       "confirmrecreate-noreason": "Naodes se begós bös mit 't verangere haet [[User:$1|$1]] ([[User talk:$1|euverlègk]]) dees pagina gewösj.\nBevestig des se dees pagina óbbenuits wils aanmake.",
+       "confirmrecreate": "Gebroeker [[User:$1|$1]] ([[User talk:$1|euverlèk]]) {{GENDER:$1|haet}} dees pagina eweggesjaf naodes doe begós mit bewirke mit de raeje:\n: <em>$2</em>\nBevestig estebleef des se dees pazjena ech obbenuujts wils aanmake.",
+       "confirmrecreate-noreason": "Naodes se begós bös mit 't verangere {{GENDER:$1|haet}} [[User:$1|$1]] ([[User talk:$1|euverlègk]]) dees pagina gewösj.\nBevestig des se dees pagina óbbenuits wils aanmake.",
        "recreate": "Pazjena obbenuujts make",
        "confirm-purge-title": "Vernuuj dees pagina",
        "confirm_purge_button": "ok",
        "signature": "[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1|euverlègk]])",
        "timezone-local": "Lokalen tied",
        "duplicate-defaultsort": "Waarsjuwing: De standaardsortering \"$2\" krieg veurrang veur de sortering \"$1\".",
+       "duplicate-displaytitle": "<strong>Waorsjoewing:</strong>Titelwaergaaf \"$2\" euversjrief ieëre titelwaergaaf \"$1\".",
+       "restricted-displaytitle": "<strong>Waorsjoewing:</strong> Titelwaergaaf \"$1\" woort genegeerd ómdet dees neet euvereinkump mit de wirkelike paginatitel.",
+       "invalid-indicator-name": "<strong>Fout:</strong> de eigesjap <code>name</code> van de paginastatusindicatore kan neet laeg zeen.",
        "version": "Versie",
        "version-extensions": "Geïnstalleerde oetbreijinge",
        "version-skins": "Geïnstalleerde uterlike",
        "version-ext-colheader-description": "Besjrieving",
        "version-ext-colheader-credits": "Sjrievers",
        "version-license-title": "Licentie veur $1",
+       "version-license-not-found": "Gein gedetailleerde infermasie is aangetroffe veur dees oetbreijing.",
        "version-credits-title": "Vermeljinge veur $1",
        "version-credits-not-found": "Gein gedetailleerde meljinge zint aangetroffe veur dees oetbreijing.",
        "version-poweredby-credits": "Deze wiki weurt aangedreve door '''[https://www.mediawiki.org/ MediaWiki]''', copyright © 2001-$1 $2.",
        "version-poweredby-others": "anger",
        "version-poweredby-translators": "translatewiki.net-euverzètters",
-       "version-license-info": "MediaWiki is vrieje sofware; de kins MediaWiki verspreien en/of aanpassen onger de veurwaerde van de GNU General Public License wie gepubliceerd door de Free Software Foundation; ofwaal versie 2 van de Licentie, of - nao diene wönsj - innig later versie.\n\nMediaWiki weurd verspreid in de haop det 't nuttig is, mer ZONGER INNIG GARANTIE; zonger zelfs de implicitiete garantie van VERKOUPBAARHEID of GESJIKHEID VEUR INNIG DOEL IN 'T BIEZÖNJER. Zuuch de GNU General Public License veur mier informatie.\n\nSame mit dit programma heurs se 'n [{{SERVER}}{{SCRIPTPATH}}/COPYING kopie van de GNU General Public License] te höbben ontvange; zo neet, sjrief den nao de Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA of [//www.gnu.org/licenses/old-licenses/gpl-2.0.html laes de licentie online].",
+       "version-credits-summary": "V'r erkènne gaer de volgende persone veur häör biedraag aan [[Special:Version|MediaWiki]].",
+       "version-license-info": "MediaWiki is vrieje sofware; de kins MediaWiki verspreien en/of aanpassen onger de veurwaerde van de GNU General Public License wie gepubliceerd door de Free Software Foundation; ofwaal versie 2 van de Licentie, of - nao diene wönsj - innig later versie.\n\nMediaWiki weurd verspreid in de haop det 't nuttig is, mer <em>ZONGER INNIG GARANTIE</em>; zonger zelfs de implicitiete garantie van <strong>VERKOUPBAARHEID</strong> of <strong>GESJIKHEID VEUR INNIG DOEL IN 'T BIEZÖNJER</strong>. Zuuch de GNU General Public License veur mier informatie.\n\nSame mit dit programma heurs se 'n [{{SERVER}}{{SCRIPTPATH}}/COPYING kopie van de GNU General Public License] te höbben ontvange; zo neet, sjrief den nao de Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA of [//www.gnu.org/licenses/old-licenses/gpl-2.0.html laes de licentie online].",
        "version-software": "Geïnstallieërde sofwaer",
        "version-software-product": "Perduk",
        "version-software-version": "Versie",
        "tags-create-warnings-below": "Wils se wiejergaon mit 't aanmake van 't label?",
        "tags-delete-title": "Haol label eweg",
        "tags-delete-explanation-initial": "Doe bös 't label \"$1\" eweg 'nt haole oete databank.",
+       "tags-delete-explanation-in-use": "'t Weurt eweggehaold van {{PLURAL:$2|ein versie of eine logbookregel|alle $2 versies en/of logbookregels}} worin 't weurt gebroek.",
+       "tags-delete-explanation-warning": "Dees hanjeling is <strong>neet trök te drejje</strong> en <strong>kan neet óngedaon waere gemaak</strong>, zelfs neet door databankbehierders. Doe mós zeker weite det se deze label wils eweghaole.",
+       "tags-delete-explanation-active": "<strong>'t Label \"$1\" is nag ummer actief en weurt in de toekóms gebroek.</strong> Veur te verhinjere det dit gebeurt, geis se nao de plaats(e) wo is ingestèld det 't label weurt toegeveug en pas se dao de instèllinge aan.",
        "tags-delete-reason": "Raeje:",
        "tags-delete-submit": "Haol dit label eweg zónger det 't kan waere trögkgedrejd",
        "tags-delete-not-allowed": "Labeles die waere bepaoldj door 'n oetbreijing kónne neet waeren eweggehaold, behauve wen de oetbreijing dit specefiek tousteit.",
        "tags-delete-not-found": "'t Label \"$1\" besteit neet.",
+       "tags-delete-too-many-uses": "'t Label \"$1\" is toegepas op mier es $2 {{PLURAL:$2|versies}}. Daodoor kan 't neet waere eweggehaold.",
+       "tags-delete-warnings-after-delete": "'t Label \"$1\" is eweggehaold, meh de volgende {{PLURAL:$2|waorsjoewing is|waorsjoewinge zint}} opgetraoje:",
        "tags-delete-no-permission": "Doe höbs gein rechte veur verangeringslabels eweg te haole.",
        "tags-activate-title": "Aktiveer label",
        "tags-activate-question": "Doe geis zo 't label \"$1\" aktivere.",
        "tags-deactivate-not-allowed": "'t Is neet meugelik 't label \"$1\" te deaktivere.",
        "tags-deactivate-submit": "Deaktiveer",
        "tags-apply-no-permission": "Doe höbs gein rechte veur verangeringslabels tou te veuge aan dien verangeringe.",
+       "tags-apply-blocked": "Doe kans gein labels toeveuge aan dien verangeringe wens {{GENDER:$1|se}} bös geblokkeerd.",
+       "tags-apply-not-allowed-one": "'t Label \"$1\" maag neet handjmaesig waere tougeveug.",
+       "tags-apply-not-allowed-multi": "{{PLURAL:$2|'t Volgend label maag|De volgende labels moge}} neet handjmaesig waere toegeveug: $1",
+       "tags-update-no-permission": "Doe höbs gein rechte verangeringslabels toe te veuge aan of eweg te haole van versies of logbookregele.",
+       "tags-update-blocked": "Doe kans gein labels toeveuge of eweghaole wen {{GENDER:$1|se}} bös geblokkeerd.",
+       "tags-update-add-not-allowed-one": "'t Label \"$1\" maag neet handjmaesig waere tougeveug.",
+       "tags-update-add-not-allowed-multi": "{{PLURAL:$2|'t Volgend label maag|De volgende labels moge}} neet handjmaesig waere toegeveug: $1",
+       "tags-update-remove-not-allowed-one": "'t Label \"$1\" maag neet waere eweggehaold.",
+       "tags-update-remove-not-allowed-multi": "{{PLURAL:$2|'t Volgend label maag|De volgende labels moge}} neet handjmaesig waere eweggehaold: $1",
+       "tags-edit-title": "Bewirk labels",
+       "tags-edit-manage-link": "Behier labels",
+       "tags-edit-revision-selected": "{{PLURAL:$1|Geselecteerde versie|Geselecteerde versies}} van [[:$2]]:",
+       "tags-edit-logentry-selected": "{{PLURAL:$1|Geselecteerde log gebeurtenis|Geselecteerde log gebeurtenisse}}:",
+       "tags-edit-revision-legend": "Veug labels toe aan {{PLURAL:$1|dees versie| alle $1 versies}} of haole die juus eweg",
+       "tags-edit-logentry-legend": "Veug labels toe aan {{PLURAL:$1|deze logbookregel| alle $1 logbookregele}} of haole die juus eweg",
+       "tags-edit-existing-tags": "Bestäönde labels:",
+       "tags-edit-existing-tags-none": "<em>Gein</em>",
+       "tags-edit-new-tags": "Nuuj labels:",
+       "tags-edit-add": "Veug dees labels toe:",
+       "tags-edit-remove": "Haol dees labels eweg:",
+       "tags-edit-remove-all-tags": "(haol alle labels eweg)",
+       "tags-edit-chosen-placeholder": "Vink 'n aantal labels aan",
+       "tags-edit-chosen-no-results": "Gein euvereinkómmende labels gevónje",
+       "tags-edit-reason": "Raeje:",
+       "tags-edit-revision-submit": "Pas verangeringe toe op {{PLURAL:$1|dees versie|$1 versies}}",
+       "tags-edit-logentry-submit": "Pas verangeringe toe op {{PLURAL:$1|deze logbookregel|$1 logbookregele}}",
+       "tags-edit-success": "De verangeringe zint tougepas wore.",
+       "tags-edit-failure": "De verangeringe kóste neet waere toegepas op: $1",
+       "tags-edit-nooldid-title": "Óngeljige doelversie",
+       "tags-edit-nooldid-text": "Doe höbs gein doelversie aangegaove worop dees hanjeling mót waere oetgeveurd of de aangegaove versie besteit neet.",
+       "tags-edit-none-selected": "Vink mindestes ei label aan veur toe te veuge of eweg te haole.",
        "comparepages": "Vergeliek pazjena's",
        "compare-page1": "Paasj 1",
        "compare-page2": "Paasj 2",
        "compare-title-not-exists": "Aangegaeve titel besteit neet.",
        "compare-revision-not-exists": "Aangegaeve versie besteit neet.",
        "diff-form": "Verangeringe",
+       "diff-form-oldid": "Aad versienómmer (keusvrie)",
+       "diff-form-revid": "Versienómmer van de verangering",
+       "diff-form-submit": "Tuin versjille",
+       "permanentlink": "Permanente link",
+       "permanentlink-revid": "Versienómmer",
+       "permanentlink-submit": "Gank nao versie",
        "dberr-problems": "Os excuses. Deze site ongervindj op t moment technische probleme.",
        "dberr-again": "Wach n aantal minute en probeer t daonao opnuuj.",
        "dberr-info": "(Kan gein toegank kriege toet de databank: $1)",
+       "dberr-info-hidden": "(Kan gein toegank kriege toet de databank)",
        "dberr-usegoogle": "Wellich kins se in de tussetied zeuke via Google.",
        "dberr-outofdate": "Let op: häör indices ven os pagina's zeen wellich neet recent.",
        "dberr-cachederror": "Deze pagina is n kopie oet de cache en is wellich neet de lèste versie.",
        "htmlform-submit": "Opsjlaon",
        "htmlform-reset": "Maak verangeringe óngedaon",
        "htmlform-selectorother-other": "Anges",
+       "htmlform-no": "Nein",
+       "htmlform-yes": "Jao",
+       "htmlform-chosen-placeholder": "Vink 'n optie aan",
+       "htmlform-cloner-create": "Veug mier tou",
+       "htmlform-cloner-delete": "Haol eweg",
+       "htmlform-cloner-required": "Minstes ein waerd is vereisj.",
        "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 waerd die se höbs opgegaove weurt neet herkènd es datum. Perbeer de stiel JJJJ-MM-DD.",
+       "htmlform-time-invalid": "De waerd die se höbs opgegaove weurt neet herkènd es tied. Perbeer de stiel OO:MM:SS.",
+       "htmlform-datetime-invalid": "De waerd die se höbs opgegaove weurt neet herkènd es datum en tied. Perbeer de stiel JJJJ-MM-DD OO:MM:SS.",
+       "htmlform-date-toolow": "De waerd die se höbs opgegaove ligk veur d'n ieëste toegestange datum van $1.",
+       "htmlform-date-toohigh": "De waerd die se höbs opgegaove ligk nao d'n ieëste toegestange datum van $1.",
+       "htmlform-time-toolow": "De waerd die se höbs opgegaove ligk veur d'n ieëste toegestange tied van $1.",
+       "htmlform-time-toohigh": "De waerd die se höbs opgegaove ligk nao d'n ieëste toegestange tied van $1.",
+       "htmlform-datetime-toolow": "De waerd die se höbs opgegaove ligk veur d'n ieëste toegestange datum en tied van $1.",
+       "htmlform-datetime-toohigh": "De waerd die se höbs opgegaove ligk nao d'n ieëste toegestange datum en tied van $1.",
+       "htmlform-title-badnamespace": "[[:$1]] bevindj zich neet inne naamruumde \"{{ns:$2}}\".",
+       "htmlform-title-not-creatable": "\"$1\" is geine paginanaam dae kan waere aangemaak",
+       "htmlform-title-not-exists": "$1 besjteit neet.",
+       "htmlform-user-not-exists": "<strong>$1</strong> besjteit neet.",
+       "htmlform-user-not-valid": "<strong>$1</strong> is geine geljige gebroekersnaam.",
        "logentry-delete-delete": "$1 {{GENDER:$1|haet}} de pagina $3 gewösj",
+       "logentry-delete-delete_redir": "$1 haet de redirek $3 {{GENDER:$2|eweggehaold}} door deze te euversjrieve",
        "logentry-delete-restore": "$1 {{GENDER:$2|haet}} de pagina $3 ($4) trögkgezatte",
+       "logentry-delete-restore-nocount": "$1 {{GENDER:$2|haet}} de pagina $3 trögkgezatte",
+       "restore-count-revisions": "{{PLURAL:$1|1 versie|$1 versies}}",
+       "restore-count-files": "{{PLURAL:$1|bestandj|bestenj}}",
        "logentry-delete-event": "$1 {{GENDER:$2|haet}} de zichbaarheid van {{PLURAL:$5|'ne logbookregel|$5 logbookregels}} van $3 gewiezig: $4",
        "logentry-delete-revision": "$1 {{GENDER:$2|haet}} de zichbaarheid van {{PLURAL:$5|'n versie|$5 versies}} van de pagina $3 verangerdj: $4",
        "logentry-delete-event-legacy": "$1 {{GENDER:$2|haet}} de zichbaarheid van logbookregels van $3 gewiezig",
        "logentry-delete-revision-legacy": "$1 {{GENDER:$2|haet}} de zichbaarheid van versies van de pagina $3 verangerd",
        "logentry-suppress-delete": "$1 {{GENDER:$2|haet}} de pagina $3 óngerdrök",
-       "logentry-suppress-event": "$1 haet heimelik de zichbaarheid van {{PLURAL:$5|'ne logbookregel|$5 logbookregels}} van $3 gewiezig: $4",
-       "logentry-suppress-revision": "$1 haet heimelik de zichbaarheid van {{PLURAL:$5|'n versie|$5 versies}} van $3 gewiezig: $4",
-       "logentry-suppress-event-legacy": "$1 haet heimelik de zichbaarheid van logbookregels van $3 gewiezig",
-       "logentry-suppress-revision-legacy": "$1 haet heimelik de zichbaarheid van versies van de pagina $3 gewiezig.",
+       "logentry-suppress-event": "$1 {{GENDER:$2|haet}} heimelik de zichbaarheid van {{PLURAL:$5|'ne logbookregel|$5 logbookregels}} van $3 gewiezig: $4",
+       "logentry-suppress-revision": "$1 {{GENDER:$2|haet}} heimelik de zichbaarheid van {{PLURAL:$5|'n versie|$5 versies}} van $3 gewiezig: $4",
+       "logentry-suppress-event-legacy": "$1 {{GENDER:$2|haet}} heimelik de zichbaarheid van logbookregels van $3 gewiezig",
+       "logentry-suppress-revision-legacy": "$1 {{GENDER:$2|haet}} heimelik de zichbaarheid van versies van de pagina $3 gewiezig.",
        "revdelete-content-hid": "inhawd verbórge",
        "revdelete-summary-hid": "bewirkingssamevatting verbórge",
        "revdelete-uname-hid": "gebroekersnaam verbórge",
        "revdelete-uname-unhid": "gebroekersnaam ónthöld",
        "revdelete-restricted": "haet beperkinge aan beheerders opgelag",
        "revdelete-unrestricted": "haet beperkinge veur beheerders opgehaeve",
+       "logentry-block-block": "$1 {{GENDER:$2|haet}} {{GENDER:$4|$3}} geblokkeerd veur d'n doer van $5 $6",
+       "logentry-block-unblock": "$1 {{GENDER:$2|haet}} {{GENDER:$4|$3}} gedeblokkeerd",
+       "logentry-block-reblock": "$1 {{GENDER:$2|haet}} de blokkaasj veur {{GENDER:$4|$3}} aangepas. Dees vervèlt noe op $5 $6",
+       "logentry-suppress-block": "$1 {{GENDER:$2|haet}} {{GENDER:$4|$3}} geblokkeerd veur d'n doer van $5 $6",
+       "logentry-suppress-reblock": "$1 {{GENDER:$2|haet}} de blokkaasj veur {{GENDER:$4|$3}} aangepas. Dees vervèlt noe op $5 $6",
+       "logentry-import-upload": "$1 {{GENDER:$2|haet}} $3 geïmporteerd via 'ne bestandjsupload",
+       "logentry-import-upload-details": "$1 {{GENDER:$2|haet}} $3 door middel van 'ne bestandjsupload geïmporteerd ($4 {{PLURAL:$4|versie|versies}})",
+       "logentry-import-interwiki": "$1 {{GENDER:$2|haet}} $3 geïmporteerd vanoet 'nen angere wiki",
+       "logentry-import-interwiki-details": "$1 {{GENDER:$2|haet}} $3 oet $5 geïmporteerd ($4 {{PLURAL:$4|versie|versies}})",
+       "logentry-merge-merge": "$1 {{GENDER:$2|haet}} $3 samegeveugd nao $4 (versies toet en mit $5)",
        "logentry-move-move": "$1 {{GENDER:$2|verplaatsde}} pagina $3 nao $4",
        "logentry-move-move-noredirect": "$1 {{GENDER:$2|verplaatsde}} pagina $3 nao $4 zónger 'ne redirek achter te laote",
        "logentry-move-move_redir": "$1 {{GENDER:$2|verplaatsde}} pagina $3 nao $4 euver 'ne redirek",
        "logentry-newusers-newusers": "$1 haet 'ne {{GENDER:$2|gebroeker}} aangemaak",
        "logentry-newusers-create": "Gebroeker $1 {{GENDER:$2|is}} aangemaak gewaore",
        "logentry-newusers-create2": "$1 haet 'ne gebroeker $3 aangemaak",
+       "logentry-newusers-byemail": "Gebroekersaccount $3 is {{GENDER:$2|aangemaak}} door $1 en 't wachwaord is versjik mitten e-mail",
        "logentry-newusers-autocreate": "De gebroeker $1 {{GENDER:$2|is}} autematis aangemaak gewaore",
+       "logentry-protect-move_prot": "$1 haet de beveiligingsinstèllinge {{GENDER:$2|verplaats}} van $4 nao $3",
+       "logentry-protect-unprotect": "$1 haet de beveiliging {{GENDER:$2|opgehöf}} van $3",
+       "logentry-protect-protect": "$1 haet $3 {{GENDER:$2|beveilig}} $4",
+       "logentry-protect-protect-cascade": "$1 haet $3 {{GENDER:$2|beveilid}} $4 [kaskaad]",
+       "logentry-protect-modify": "$1 haet 't beveiligingsniveau van $3 {{GENDER:$2|aangepas}} $4",
+       "logentry-protect-modify-cascade": "$1 hq4t het beveiligingsniveau van $3 {{GENDER:$2|aangepas}} $4 [kaskaad]",
+       "logentry-rights-rights": "$1 {{GENDER:$2|haet}} groepslidmaotsjap veur {{GENDER:$6|$3}} verangerd van $4 nao $5",
+       "logentry-rights-rights-legacy": "$1 {{GENDER:$2|haet}} 't groepslidmaotsjap verangerd veur $3",
+       "logentry-rights-autopromote": "$1 {{GENDER:$2|is}} automatisch gepromoveerd van $4 nao $5",
        "logentry-upload-upload": "$1 {{GENDER:$2|loadje}} $3 up",
        "logentry-upload-overwrite": "$1 {{GENDER:$2|haet}} 'n nuuj versie van $3 hoaggelaje",
+       "logentry-upload-revert": "$1 {{GENDER:$2|loadje}} $3 up",
+       "log-name-managetags": "Labelbehieërlogbook",
+       "log-description-managetags": "Dees pagina geuf 'n euverzich van behieërstake mit betrèkking toet [[Special:Tags|labels]]. 't Logbook bevatj allein aktiviteite die handjmaesig zint oetgeveurd door 'ne behieërder. Labels kónne waere gemaak of eweggehaold dore wikisofware zónger det 'n vermeljing hieveur weurt opgenómme in 't logbook.",
+       "logentry-managetags-create": "$1 {{GENDER:$2|maakde}} 't label \"$4\" aan",
+       "logentry-managetags-delete": "$1 {{GENDER:$2|haolde}} 't label \"$4\" eweg (haolde det eweg van $5 {{PLURAL:$5|versue of logbookregel|versies dan logbookregele}})",
+       "logentry-managetags-activate": "$1 {{GENDER:$2|aktiveerde}} 't label \"$4\" aan veur gebroekers- en botgebroek",
+       "logentry-managetags-deactivate": "$1 {{GENDER:$2|deaktiveerde}} 't label \"$4\" aan veur gebroekers- en botgebroek",
+       "log-name-tag": "Labellogbook",
+       "log-description-tag": "Op dees pagina weurt getuind wen gebroekers [[Special:Tags|labels]] höbbe toegeveug of eweggehaold van versies of logbookregele. In 't logbook is neet opgenómme det labels zint toegeveug wore es 'n óngerdeil van 'n bewirking, ewegsjaffing of 'n saortgelieke hanjeling.",
+       "logentry-tag-update-add-revision": "$1 {{GENDER:$2|veugde}} {{PLURAL:$7|'t label|de labels}} $6 toe aan versie $4 van pagina $3",
+       "logentry-tag-update-add-logentry": "$1 {{GENDER:$2|veugde}} {{PLURAL:$7|'t label|de labels}} $6 toe aan logbookregel $5 van pagina $3",
+       "logentry-tag-update-remove-revision": "$1 {{GENDER:$2|haolde}} {{PLURAL:$9|'t label|de labels}} $8 eweg aan versie $4 van pagina $3",
+       "logentry-tag-update-remove-logentry": "$1 {{GENDER:$2|haolde}} {{PLURAL:$9|'t label|de labels}} $8 eweg aan logbookregel $5 van pagina $3",
+       "logentry-tag-update-revision": "$1 {{GENDER:$2|wirkde}} de labels van versie $4 van pagina $3 bie ($6 {{PLURAL:$7|toegeveug}}; $8 {{PLURAL:$9|eweggehaold}})",
+       "logentry-tag-update-logentry": "$1 {{GENDER:$2|wirkde}} de labels van logbookregel $5 van pagina $3 bie ($6 {{PLURAL:$7|toegeveug}}; $8 {{PLURAL:$9|eweggehaold}})",
        "rightsnone": "(gein)",
+       "rightslogentry-temporary-group": "$1 (tiejelik, toet $2)",
        "feedback-adding": "Feedback weurt aan pagina toegevoeg...",
+       "feedback-back": "Trök",
        "feedback-bugcheck": "Good! Kónterleer ef of 't neet al ein vanne [$1 bekèndje bugs] is.",
        "feedback-bugnew": "Gekónterleerdj. Mèlj 'ne nuuj bug.",
        "feedback-bugornote": "Es se zewied bös óm e technisch perbleem in détail te besjrieve, [$1 rapperteer 'ne bug]. \nAnges kin se-n ouch 't einvawdig formeleer hieónger gebroeke. Dien commentaar zal waere toegeveug ane pagina \"[$3 $2]\", same mit diene gebroekersnaam enne browser dae se gebruuks.",
        "feedback-cancel": "Braek aaf",
        "feedback-close": "Gedaon",
+       "feedback-external-bug-report-button": "Deen 'n technische taak in",
+       "feedback-dialog-title": "Versjik feedback",
+       "feedback-dialog-intro": "Doe kans 't einveljig formeleer broeke veur diene feedback in te sjikke. Dien reactie weurt toegeveug aan de pagina \"$1\" same mit diene gebroekersnaam.",
        "feedback-error1": "Fout: ónbekind rizzeltaot vanne API",
        "feedback-error2": "Fout: bewirking mislök",
        "feedback-error3": "Fout: gein reactie vanne API",
+       "feedback-error4": "Fout: 't waas neet meugelik det besjeid te plaatse op de pagina",
        "feedback-message": "Berich:",
        "feedback-subject": "Óngerwerp:",
        "feedback-submit": "Opsjlaon",
+       "feedback-terms": "Ich verstaon det mien gebroekersagentgegaeves infermasie bevatte euver de browser en 't besturingssysteem det ich broek en det dees gegaeves same mit miene feedback aopenbaar waere gemaak.",
+       "feedback-termsofuse": "Ich gaon akkaord mit 't gaeve van feedback in euvereinstumming mit de Gebroeksverwaerd.",
        "feedback-thanks": "Danke! Diene feedback is oppe pagina \"[$2 $1]\" geplaats.",
        "feedback-thanks-title": "Danke!",
+       "feedback-useragent": "Gebroekeragent:",
        "searchsuggest-search": "Doorzeuk {{SITENAME}}",
        "searchsuggest-containing": "bevat...",
        "api-error-badtoken": "Intern fout: toke is slech.",
        "api-error-emptypage": "Doe maags gein nuuj, laeg pagina's aanmake.",
+       "api-error-publishfailed": "Intern fout: de server kós 't tiedelik bestandj neet oetbringe.",
        "api-error-stashfailed": "Intern fout: de server kós 't tiedelik bestandj neet ópslaon.",
        "api-error-unknown-warning": "Onbekinde waorsjuwing: \"$1\"",
        "api-error-unknownerror": "Ónbekèndje fout: \"$1\"",
        "duration-decades": "$1 {{PLURAL:$1|decennium|decennia}}",
        "duration-centuries": "$1 {{PLURAL:$1|ieëf|ieëf}}",
        "duration-millennia": "$1 {{PLURAL:$1|millennium|millennia}}",
+       "rotate-comment": "Plaetje gedrejd, $1 {{PLURAL:$1|graod}} mit de klok mit",
+       "limitreport-title": "Prestaasjegegaeves vanne parser:",
+       "limitreport-cputime": "CPU-tiedsverbroek",
+       "limitreport-cputime-value": "$1 {{PLURAL:$1|sekond}}",
+       "limitreport-walltime": "Wirkelik tiedsbroek",
+       "limitreport-walltime-value": "$1 {{PLURAL:$1|sekond}}",
+       "limitreport-ppvisitednodes": "Aantaal nodes bekeke tiejes de veurverwirking",
+       "limitreport-ppgeneratednodes": "Aantaal nodes aangemaak tiejes de veurverwirking",
+       "limitreport-postexpandincludesize": "Inclusiegreudje nao oetbreijing",
+       "limitreport-postexpandincludesize-value": "$1/$2 {{PLURAL:$2|byte|bytes}}",
+       "limitreport-templateargumentsize": "Gruuedje sjabloonparamaeters",
+       "limitreport-templateargumentsize-value": "$1 / $2 {{PLURAL:$2|byte|bytes}}",
+       "limitreport-expansiondepth": "Heugste oetbreijingsdeepdje",
+       "limitreport-expensivefunctioncount": "Aantaal kosbaar parserfuncties",
+       "limitreport-unstrip-size-value": "$1/$2 {{PLURAL:$2|byte|bytes}}",
        "expandtemplates": "Sjablone plekke",
-       "expand_templates_intro": "Dees speciaal pazjena laes de ingegaeve teks in en plektj (mitte functie subst) recursief alle sjablone in de teks. 't Plek ouch alle parserfuncties wie <nowiki>{{</nowiki>#language:...}} en variabele wie <nowiki>{{</nowiki>CURRENTDAY}} - vriejwaal al tösse dóbbel accolades.\nHiej veur waere de relevante functies van de MediaWiki-parser gebroek.",
+       "expand_templates_intro": "Dees speciaal pazjena laes de ingegaeve teks in en plek recursief alle sjablone in de wikiteks. 't Plek ouch alle parserfuncties wie <nowiki>{{</nowiki>#language:...}} en variabele wie <nowiki>{{</nowiki>CURRENTDAY}} - vriejwaal al tösse dóbbel accolades.\nVriewaal alles tösse dóbbel akkolades weurt geplek.",
        "expand_templates_title": "Contekstitel, veur {{FULLPAGENAME}}, etc:",
        "expand_templates_input": "Veur wikiteks in:",
        "expand_templates_output": "Rezultaot",
        "expand_templates_xml_output": "XML-oetveur",
+       "expand_templates_html_output": "Roewen HTML",
        "expand_templates_ok": "ok",
        "expand_templates_remove_comments": "Wis opmerkinge",
        "expand_templates_remove_nowiki": "Óngerdrök <nowiki>-tags in 't resultaat",
        "expand_templates_generate_xml": "XML-parserboum bekieke",
+       "expand_templates_generate_rawhtml": "Tuin roewen HTML",
        "expand_templates_preview": "Veurvertuining",
+       "expand_templates_input_missing": "Doe mós mindestes get van wikiteks inveure.",
+       "pagelanguage": "Veranger paginaspraok",
+       "pagelang-name": "Pazjena",
+       "pagelang-language": "Spraok",
+       "pagelang-use-default": "Gebroek standerdspraok",
+       "pagelang-select-lang": "Kees spraok",
+       "pagelang-reason": "Raeje",
+       "pagelang-submit": "Slaon op",
+       "pagelang-nonexistent-page": "De pagina $1 besteit neet.",
+       "pagelang-unchanged-language": "De pagina $1 is al ingestèld wore op de spraok $2.",
+       "pagelang-unchanged-language-default": "De pagina $1 is al ingestèld wore op de standerd inhawdsspraok van de wiki.",
+       "pagelang-db-failed": "De databank kós de paginaspraok neet verangere.",
+       "right-pagelang": "Veranger paginaspraok",
+       "action-pagelang": "de paginaspraok te verangere",
+       "log-name-pagelang": "Spraokverangeringslogbook",
+       "log-description-pagelang": "Dit is e logbook van verangeringe in de paginaspraoke.",
+       "logentry-pagelang-pagelang": "$1 {{GENDER:$2|verangerde}} de spraok van $3 van $4 nao $5",
+       "default-skin-not-found-row-enabled": "* <code>$1</code> / $2 (ingesjakeld)",
+       "default-skin-not-found-row-disabled": "* <code>$1</code> / $2 (<strong>oetgezatte</strong>)",
+       "mediastatistics": "Mediasjtattestieke",
+       "mediastatistics-summary": "Stattestieke euver upgeloade bestandjstype. Dit euverzich bevatj allein de recènste versie van e bestandj. Aaj of eweggesjafde versies waere neet mitgetaldj.",
+       "mediastatistics-nbytes": "{{PLURAL:$1|$1 byte|$1 bytes}} ($2; $3%)",
+       "mediastatistics-bytespertype": "Bestandjsgreudje veur dees sectie gans biejein: {{PLURAL:$1|$1 byte|$1 bytes}} ($2; $3%).",
+       "mediastatistics-allbytes": "Bestandjsgreudje van alle bestenj gans biejein: {{PLURAL:$1|$1 byte|$1 bytes}} ($2).",
+       "mediastatistics-table-mimetype": "MIME-type",
+       "mediastatistics-table-extensions": "Meugelike oetbreijinge",
+       "mediastatistics-table-count": "Aantaal bestenj",
+       "mediastatistics-table-totalbytes": "Gruuedje biejein",
+       "mediastatistics-header-unknown": "Ónbekènd",
+       "mediastatistics-header-bitmap": "Bitmapplaetjes",
+       "mediastatistics-header-drawing": "Teikeninge (vectorbestenj)",
+       "mediastatistics-header-audio": "Audio",
+       "mediastatistics-header-video": "Video's",
+       "mediastatistics-header-multimedia": "Interactief media",
+       "mediastatistics-header-office": "Kantoearbestenj",
+       "mediastatistics-header-text": "Teksbestenj",
+       "mediastatistics-header-executable": "Oetveurbaar bestenj",
+       "mediastatistics-header-archive": "Gecomprimeerde bestenj",
+       "mediastatistics-header-total": "Alle bestenj",
+       "json-warn-trailing-comma": "{{PLURAL:$1|Eine komma anen ènj vanne regel is|$1 komma's anen ènj vanne regel zint}} eweggehaoldj oet de JSON",
+       "json-error-unknown": "'n Fout is opgetraoje mit de JSON. Foutmeljing: $1",
+       "json-error-depth": "De maximaal stackdeepdje is euversjreje.",
+       "json-error-state-mismatch": "Óngeljige of ónjuuste JSON",
+       "json-error-ctrl-char": "Fout in kóntraolkarakter, meugelik verkieërd gecodeerd",
+       "json-error-syntax": "Syntaxisfout",
        "special-characters-group-latin": "Letien",
        "special-characters-group-latinextended": "Oetgebreid letien",
        "special-characters-group-ipa": "IPA",
        "special-characters-group-thai": "Thai",
        "special-characters-group-lao": "Lao",
        "special-characters-group-khmer": "Cambodzjaans",
+       "special-characters-group-canadianaboriginal": "Canadees Inboorling",
+       "special-characters-title-endash": "koppelteike",
+       "special-characters-title-emdash": "gedechtestreep",
+       "special-characters-title-minus": "minteike",
+       "mw-widgets-dateinput-no-date": "Geinen datum gekaoze",
        "mw-widgets-dateinput-placeholder-day": "JJJJ-MM-DD",
        "mw-widgets-dateinput-placeholder-month": "JJJJ-MM",
+       "mw-widgets-mediasearch-input-placeholder": "Zeuk nao media",
+       "mw-widgets-mediasearch-noresults": "Gein rizzeltaote gevónje.",
+       "mw-widgets-titleinput-description-new-page": "pazjena besteit nag neet",
+       "mw-widgets-titleinput-description-redirect": "redirek nao $1",
+       "sessionprovider-generic": "$1-sessies",
        "randomrootpage": "Willekäörige wrootpagina",
+       "log-action-filter-block": "Saort blokkaasj:",
+       "log-action-filter-contentmodel": "Saort inhawdsmodelverangering:",
+       "log-action-filter-delete": "Saort ewegsjaffing:",
+       "log-action-filter-import": "Saort inveuring:",
+       "log-action-filter-managetags": "Saort labelbehieërhanjeling:",
+       "log-action-filter-move": "Saort verplaatsing:",
+       "log-action-filter-newusers": "Saort gebroekersaanmaak:",
+       "log-action-filter-patrol": "Saort markering:",
+       "log-action-filter-protect": "Saort beveiliging:",
+       "log-action-filter-rights": "Saort rechteverangering:",
+       "log-action-filter-suppress": "Saort óngerdrökking:",
+       "log-action-filter-upload": "Saort upload:",
        "log-action-filter-all": "Alle",
        "log-action-filter-block-block": "Blokkeer",
        "log-action-filter-block-reblock": "Aanpassing van blokkaasj",
        "log-action-filter-delete-event": "Ewegsjaffe van logbookregele",
        "log-action-filter-delete-revision": "Ewegsjaffe van versies",
        "log-action-filter-import-interwiki": "Transwikiimport",
+       "log-action-filter-import-upload": "Inveur middels XML-upload",
+       "log-action-filter-managetags-create": "Labelaanmaak",
+       "log-action-filter-managetags-delete": "Labelewegsjaffing",
+       "log-action-filter-managetags-activate": "Labelaktivering",
+       "log-action-filter-managetags-deactivate": "Labeldeaktivering",
+       "authmanager-authplugin-setpass-bad-domain": "Óngeljig demien.",
+       "authmanager-email-label": "E-mail",
+       "authmanager-email-help": "E-mailadres",
+       "authmanager-realname-label": "Echte naam",
+       "authmanager-realname-help": "Echte naam van de gebroeker",
+       "authprovider-resetpass-skip-label": "Slaon euver",
+       "edit-error-short": "Fout: $1",
+       "edit-error-long": "Foute:\n\n$1",
+       "revid": "versie $1",
+       "pageid": "paginanómmer $1",
+       "pagedata-title": "Paginagegaeves",
        "pagedata-bad-title": "Óngeljigen titel: $1."
 }
index 47498e8..4420985 100644 (file)
@@ -25,7 +25,8 @@
                        "Nitalynx",
                        "Silraks",
                        "Zuiks",
-                       "Martinsdzerve"
+                       "Martinsdzerve",
+                       "Nixiéoffset"
                ]
        },
        "tog-underline": "Pasvītrot saites:",
        "customcssprotected": "Jums nav tiesību rediģēt šo CSS lapu, jo tā satur cita lietotāja personiskos iestatījumus.",
        "customjsprotected": "Jums nav tiesību rediģēt šo JavaScript lapu, jo tā satur cita lietotāja personiskos iestatījumus.",
        "mycustomcssprotected": "Jums nav tiesību rediģēt šo CSS lapu.",
+       "mycustomjsonprotected": "Jums nav tiesību rediģēt šo JSON lapu.",
        "mycustomjsprotected": "Jums nav tiesību rediģēt šo JavaScript lapu.",
        "myprivateinfoprotected": "Jums nav tiesību rediģēt savu privāto informāciju.",
        "mypreferencesprotected": "Jums nav tiesību rediģēt savus iestatījumus.",
        "invalidtitle-knownnamespace": "Nederīgs nosaukums ar vārdtelpu \"$2\" un tekstu \"$3\"",
        "invalidtitle-unknownnamespace": "Nederīgs nosaukums ar nezināmu vārdtelpas numuru \"$1\" un tekstu \"$2\"",
        "exception-nologin": "Neesat pieslēdzies",
+       "exception-nologin-text": "Lūdzu ienāciet lai piekļūtu šai lapai/veiktu šo darbību.",
+       "exception-nologin-text-manual": "Lūdzu $1, lai varētu piekļūt šai lapai/veikt šo darbību.",
        "virus-badscanner": "Nekorekta konfigurācija: nezināms vīrusu skeneris: ''$1''",
        "virus-scanfailed": "skenēšana neizdevās (kods $1)",
        "virus-unknownscanner": "nezināms antivīruss:",
        "cannotlogin-text": "Pieslēgšanās nav iespējama.",
        "cannotloginnow-title": "Šobrīd nevar pieslēgties",
        "cannotcreateaccount-title": "Nevar izveidot kontus",
+       "cannotcreateaccount-text": "Tieša konta izveide nav ieslēgta šajā viki.",
        "yourdomainname": "Tavs domēns",
        "password-change-forbidden": "Šajā wiki paroles nevar mainīt.",
        "externaldberror": "Notikusi vai nu ārējās autentifikācijas datubāzes kļūda, vai arī tev nav atļauts izmainīt savu ārējo kontu.",
        "wrongpassword": "Tu ievadīji nepareizu paroli. Lūdzu, mēģini vēlreiz.",
        "wrongpasswordempty": "Parole bija tukša. Lūdzu mēģini vēlreiz.",
        "passwordtooshort": "Tava parole ir pārāk īsa.\nTajā jābūt vismaz {{PLURAL:$1|$1 zīmēm|1 zīmei|$1 zīmēm}}.",
+       "passwordtoolong": "Paroles nevar būt garākas par {{PLURAL:$1|$1 simboliem|$1 simbolu|$1 simboliem}}.",
        "password-name-match": "Tava parole nedrīkst būt tāda pati kā tavs lietotājvārds.",
        "password-login-forbidden": "Šī lietotājvārda un paroles izmantošana ir aizliegta.",
        "mailmypassword": "Atiestatīt paroli",
        "savechanges": "Saglabāt izmaiņas",
        "publishpage": "Saglabāt lapu",
        "publishchanges": "Publicēt izmaiņas",
+       "savearticle-start": "Saglabāt lapu...",
+       "savechanges-start": "Saglabāt izmaiņas...",
+       "publishpage-start": "Publicēt lapu...",
+       "publishchanges-start": "Publicēt izmaiņas...",
        "preview": "Pirmskats",
        "showpreview": "Rādīt pirmskatu",
        "showdiff": "Rādīt izmaiņas",
        "undo-failure": "Šo labojumu nevar atcelt, jo ir veikti nozīmīgi labojumi vēl pēc šī labojuma izdarīšanas.",
        "undo-norev": "Šo izmaiņu nevar atcelt, jo tādas nav vai tā ir izdzēsta.",
        "undo-summary": "Atcēlu [[Special:Contributions/$2|$2]] ([[User talk:$2|Diskusija]]) izdarīto izmaiņu $1",
+       "undo-summary-username-hidden": "Atsaukta slēpta lietotāja revīzija $1",
        "cantcreateaccount-text": "[[Lietotājs:$3|$3]] ir bloķējis lietotāja izveidošanu no šīs IP adreses ('''$1''').\n\n$3 norādītais iemesls ir ''$2''",
        "viewpagelogs": "Apskatīt ar šo lapu saistītos reģistru ierakstus",
        "nohistory": "Šai lapai nav pieejama versiju hronoloģija.",
        "powersearch-remember": "Atcerēties izvēli turpmākajā meklēšanā",
        "search-external": "Ārējā meklēšana",
        "searchdisabled": "Meklēšana {{grammar:lokatīvs|{{SITENAME}}}} šobrīd ir atslēgta darbības traucējumu dēļ.\nPagaidām vari meklēt, izmantojot Google vai Yahoo.\nŅem vērā, ka meklētāju indeksētais {{grammar:ģenitīvs|{{SITENAME}}}} saturs var būt novecojis.",
+       "search-error": "Ir notikusi kļūda meklējot: $1",
        "preferences": "Izvēles",
        "mypreferences": "Izvēles",
        "prefs-edits": "Izmaiņu skaits:",
        "recentchangesdays": "Dienu skaits, kuru rādīt pēdējās izmaiņās:",
        "recentchangesdays-max": "Ne vairāk kā $1 {{PLURAL:$1|dienas|diena|dienas}}",
        "recentchangescount": "Izmaiņu skaits, kuru rāda pēc noklusējuma:",
-       "prefs-help-recentchangescount": "Šis parametrs attiecas uz pēdējo izmaiņu un hronoloģijas lapām, kā arī uz sistēmas žurnāliem",
+       "prefs-help-recentchangescount": "Maksimums: 1000",
        "prefs-help-watchlist-token2": "Šī ir slepena atslēga tavam uzraugāmo lapu sarakstam.\nIkvienam, kas to zinās, būs iespēja apskatīt tavu uzraugāmo lapu sarakstu, tāpēc nedalies ar to.\n[[Special:ResetTokens|Spied šeit, lai to atjaunotu]].",
        "savedprefs": "Jūsu izvēles ir saglabātas.",
        "timezonelegend": "Laika josla:",
        "userrights-nodatabase": "Datubāze $1 neeksistē vai nav lokāla.",
        "userrights-changeable-col": "Grupas, kuras tu vari izmainīt",
        "userrights-unchangeable-col": "Grupas, kuras tu nevari izmainīt",
+       "userrights-expiry-current": "beidzas $1",
        "userrights-expiry-othertime": "Cits laiks:",
        "group": "Grupa:",
        "group-user": "Dalībnieki",
        "php-uploaddisabledtext": "Failu augšupielāde ir atslēgta PHP.\nLūdzu, pārbaudi file_uploads uzstādījumu.",
        "uploadscripted": "Šis fails satur HTML vai skriptu kodu, kuru, interneta pārlūks, var kļūdas pēc, mēģināt interpretēt (ar potenciāli sliktām sekām).",
        "upload-scripted-dtd": "Nevar augšupielādēt SVG failus, kuri satur nestandarta DTD deklarāciju.",
+       "uploaded-hostile-svg": "Atrasts nedrošs CSS elements augšupielādētajā SVG failā.",
        "uploadinvalidxml": "Nevarēja apstrādāt augšupielādētā faila XML saturu.",
        "uploadvirus": "Šis fails satur vīrusu! Sīkāk: $1",
        "uploadjava": "Fails ir ZIP fails, kas satur Java .class failu.\nJava failu augšupielāde nav atļauta, jo tas var radīt iespējas apiet drošības ierobežojumus.",
        "zip-wrong-format": "Norādītais fails nebija ZIP fails.",
        "uploadstash-errclear": "Failu tīrīšana neizdevās.",
        "uploadstash-refresh": "Atsvaidzināt failu sarakstu",
+       "uploadstash-thumbnail": "aplūkot sīkbildi",
        "uploadstash-bad-path-unknown-type": "Nezināms tips \"$1\".",
        "uploadstash-bad-path-unrecognized-thumb-name": "Neatpazīts sīktēla nosaukums.",
+       "uploadstash-file-not-found-no-thumb": "Nevarēja iegūt sīkbildi.",
        "uploadstash-zero-length": "Faila garums ir nulle.",
        "img-auth-accessdenied": "Pieeja liegta",
        "img-auth-nopathinfo": "Trūkst PATH_INFO.\nJūsu serveris nav konfigurēts nodot šo informāciju.\nTas var būt bāzēts uz CGI un neatbalstīt img_auth.\nSkatīt https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Image_Authorization.",
        "randomincategory-legend": "Nejauša lapa kategorijā",
        "randomincategory-submit": "Aiziet!",
        "randomredirect": "Nejauša pāradresācijas lapa",
+       "randomredirect-nopages": "Vārdtelpā \"$1\" nav pāradresāciju.",
        "statistics": "Statistika",
        "statistics-header-pages": "Lapu statistika",
        "statistics-header-edits": "Izmaiņu statistika",
index a10585b..820f783 100644 (file)
        "statistics-files": "Подигнати податотеки",
        "statistics-edits": "Број на уредувања од започнувањето на {{SITENAME}}",
        "statistics-edits-average": "Просечен број на уредувања по страница",
-       "statistics-users": "Регистрирани [[Special:ListUsers|корисници]]",
+       "statistics-users": "Регистрирани корисници",
        "statistics-users-active": "Активни корисници",
        "statistics-users-active-desc": "Корисници кои имаат извршено некое дејство {{PLURAL:$1|претходниот ден|во претходните $1 дена}}",
        "pageswithprop": "Страници со својство",
        "deadendpages": "Слепи страници",
        "deadendpagestext": "Следните страници немаат врски кон ниту една друга страница на ова вики.",
        "protectedpages": "Заштитени страници",
+       "protectedpages-filters": "Филтри:",
        "protectedpages-indef": "Само бесконечни заштити",
        "protectedpages-summary": "На страницата се наведени постоечки страници што се моментално под заштита. За список на наслови што се заштитени од создавање, погледајте [[{{#special:ProtectedTitles}}|{{int:protectedtitles}}]].",
        "protectedpages-cascade": "Само каскадни заштити",
index 7feb18c..39bcb0d 100644 (file)
        "password-login-forbidden": "ഈ ഉപയോക്തൃനാമത്തിന്റെയും രഹസ്യവാക്കിന്റെയും ഉപയോഗം നിരോധിച്ചിരിക്കുന്നു.",
        "mailmypassword": "രഹസ്യവാക്ക് പുനഃക്രമീകരിക്കുക",
        "passwordremindertitle": "{{SITENAME}} സംരംഭത്തിൽ ഉപയോഗിക്കാനുള്ള താത്കാലിക രഹസ്യവാക്ക്",
-       "passwordremindertext": "ആരോ ഒരാൾ ($1 എന്ന ഐ.പി. വിലാസത്തിൽനിന്ന് ഒരാൾ, ഒരു പക്ഷേ താങ്കളായിരിക്കാം) {{SITENAME}} ($4) സംരംഭത്തിലേക്ക് പുതിയ രഹസ്യവാക്ക് ആവശ്യപ്പെട്ടിരിക്കുന്നു. \"$2\" എന്ന ഉപയോക്താവിന്റെ താത്കാലിക രഹസ്യവാക്കായി \"$3\" സജ്ജീകരിച്ചിരിക്കുന്നു. താങ്കൾക്ക് ആവശ്യമെങ്കിൽ, താങ്കൾ പ്രവേശിച്ചശേഷം പുതിയ രഹസ്യവാക്ക് സജ്ജീകരിക്കേണ്ടതാണ്. താങ്കളുടെ താത്കാലിക രഹസ്യവാക്കിന്റെ കാലാവധി {{PLURAL:$5|ഒരു ദിവസമാകുന്നു|$5 ദിവങ്ങളാകുന്നു}}.\n\nഈ അഭ്യർത്ഥന മറ്റാരെങ്കിലും നടത്തിയതാണെങ്കിൽ, അതല്ല പഴയ രഹസ്യവാക്ക് ഓർമ്മയുണ്ടായിരിക്കുകയും അത് മാറ്റുവാൻ താങ്കൾക്ക് താത്പര്യവുമില്ലെങ്കിൽ, ഈ സന്ദേശം അവഗണിച്ച് താങ്കളുടെ പഴയ രഹസ്യവാക്ക് തുടർന്നും ഉപയോഗിക്കാവുന്നതാണ്‌.",
+       "passwordremindertext": "ആരോ ഒരാൾ ($1 എന്ന ഐ.പി. വിലാസത്തിൽനിന്ന് ഒരാൾ) {{SITENAME}} ($4) സംരംഭത്തിൽ പുതിയ രഹസ്യവാക്ക് ആവശ്യപ്പെട്ടിരിക്കുന്നു. \"$2\" എന്ന ഉപയോക്താവിന്റെ താത്കാലിക രഹസ്യവാക്കായി \"$3\" സജ്ജീകരിച്ചിരിക്കുന്നു. താങ്കൾക്ക് ആവശ്യമെങ്കിൽ, താങ്കൾ പ്രവേശിച്ചശേഷം പുതിയ രഹസ്യവാക്ക് സജ്ജീകരിക്കേണ്ടതാണ്. താങ്കളുടെ താത്കാലിക രഹസ്യവാക്കിന്റെ കാലാവധി {{PLURAL:$5|ഒരു ദിവസമാകുന്നു|$5 ദിവങ്ങളാകുന്നു}}.\n\nഈ അഭ്യർത്ഥന മറ്റാരെങ്കിലും നടത്തിയതാണെങ്കിൽ, അതല്ല പഴയ രഹസ്യവാക്ക് ഓർമ്മയുണ്ടായിരിക്കുകയും അത് മാറ്റുവാൻ താങ്കൾക്ക് താത്പര്യവുമില്ലെങ്കിൽ, ഈ സന്ദേശം അവഗണിച്ച് താങ്കളുടെ പഴയ രഹസ്യവാക്ക് തുടർന്നും ഉപയോഗിക്കാവുന്നതാണ്‌.",
        "noemail": "\"$1\" എന്ന ഉപയോക്താവ് ഇമെയിൽ വിലാസം ക്രമീകരിച്ചിട്ടില്ല.",
        "noemailcreate": "താങ്കൾ സാധുവായ ഇമെയിൽ വിലാസം നൽകേണ്ടതാണ്",
        "passwordsent": "‘$1” എന്ന അംഗത്വത്തിനായി രജിസ്റ്റർ ചെയ്യപ്പെട്ടിട്ടുള്ള ഇമെയിൽ വിലാസത്തിലേക്ക് ഒരു പുതിയ രഹസ്യവാക്ക് അയച്ചിട്ടുണ്ട്. അത് ലഭിച്ചശേഷം ദയവായി ലോഗിൻ ചെയ്യുക.",
        "statistics-files": "അപ്‌ലോഡ് ചെയ്തിട്ടുള്ള പ്രമാണങ്ങൾ",
        "statistics-edits": "{{SITENAME}} സം‌രംഭത്തിന്റെ തുടക്കം മുതലുള്ള തിരുത്തുകൾ",
        "statistics-edits-average": "ഒരു താളിലെ ശരാശരി തിരുത്തുകൾ",
-       "statistics-users": "അംഗത്വമെടുത്തിട്ടുള്ള [[Special:ListUsers|ഉപയോക്താക്കൾ]]",
+       "statistics-users": "അംഗത്വമെടുത്ത ഉപയോക്താക്കൾ",
        "statistics-users-active": "സജീവ ഉപയോക്താക്കൾ",
        "statistics-users-active-desc": "കഴിഞ്ഞ {{PLURAL:$1|ദിവസം|$1 ദിവസങ്ങൾക്കുള്ളിൽ}} പ്രവർത്തിച്ചിട്ടുള്ള ഉപയോക്താക്കൾ",
        "pageswithprop": "താളിന്റെ സവിശേഷതകളുള്ള താളുകൾ",
index 321a9be..19975aa 100644 (file)
        "rcfilters-filter-humans-label": "Menselijk (geen bot)",
        "rcfilters-filter-humans-description": "Bewerkingen door menselijke bewerkers.",
        "rcfilters-filtergroup-reviewstatus": "Beoordelingsstatus",
+       "rcfilters-filter-reviewstatus-unpatrolled-description": "Bewerkingen die niet handmatig of automatisch gecontroleerd zijn.",
        "rcfilters-filter-reviewstatus-unpatrolled-label": "Niet gecontroleerd",
+       "rcfilters-filter-reviewstatus-manual-description": "Bewerkingen die handmatig zijn gecontroleerd",
+       "rcfilters-filter-reviewstatus-manual-label": "Handmatig gecontroleerd",
+       "rcfilters-filter-reviewstatus-auto-description": "Bewerkingen door geavanceerde gebruikers wiens werk automatisch gecontroleerd is.",
+       "rcfilters-filter-reviewstatus-auto-label": "Automatisch gecontroleerd",
        "rcfilters-filtergroup-significance": "Belangrijkheid",
        "rcfilters-filter-minor-label": "Kleine bewerkingen",
        "rcfilters-filter-minor-description": "Bewerkingen die door de bewerker zijn gelabeld als klein.",
        "statistics-files": "Bestanden",
        "statistics-edits": "Paginabewerkingen sinds het begin van {{SITENAME}}",
        "statistics-edits-average": "Gemiddeld aantal bewerkingen per pagina",
-       "statistics-users": "Geregistreerde [[Special:ListUsers|gebruikers]]",
+       "statistics-users": "Geregistreerde gebruikers",
        "statistics-users-active": "Actieve gebruikers",
        "statistics-users-active-desc": "Gebruikers die in de afgelopen {{PLURAL:$1|dag|$1 dagen}} een handeling hebben uitgevoerd",
        "pageswithprop": "Pagina's met een pagina-eigenschap",
        "version-specialpages": "Speciale pagina's",
        "version-parserhooks": "Parserhooks",
        "version-variables": "Variabelen",
+       "version-editors": "Tekstverwerkers",
        "version-antispam": "Spampreventie",
        "version-other": "Overige",
        "version-mediahandlers": "Mediaverwerkers",
        "log-action-filter-delete-event": "Verwijderen van logboekregels",
        "log-action-filter-delete-revision": "Verwijderen van versies",
        "log-action-filter-import-interwiki": "Transwiki imports",
-       "log-action-filter-import-upload": "Import doormiddel van XML uploads",
+       "log-action-filter-import-upload": "Import door middel van XML uploads",
        "log-action-filter-managetags-create": "Aanmaken van label",
        "log-action-filter-managetags-delete": "Verwijderen van label",
        "log-action-filter-managetags-activate": "Activeren van label",
        "gotointerwiki-external": "U staat op het punt om {{SITENAME}} te verlaten en [[$2]] te bezoeken. [[$2]] is een aparte website.\n\n'''[$1 Doorgaan naar $1]'''",
        "undelete-cantedit": "U kunt deze pagina niet terug plaatsen omdat u niet het recht hebt om deze pagina te bewerken.",
        "undelete-cantcreate": "U kunt deze pagina niet terugplaatsen omdat er geen bestaande pagina met deze naam is en u geen toestemming hebt om deze pagina aan te maken.",
-       "pagedata-title": "Pagina data",
+       "pagedata-title": "Paginagegevens",
        "pagedata-text": "Deze pagina biedt een data-interface voor pagina's. Geef een paginatitel op door deze in de URL op te nemen, op de manier van een deelpagina.\n* De inhoud wordt afgestemd op de door de client meegestuurde Accept Header. Dit betekent dat de gegevens voor de pagina worden aangeboden in het voorkeursformaat van uw client.",
        "pagedata-not-acceptable": "Er is geen overeenkomende indeling gevonden. Ondersteunde MIME-typen: $1",
        "pagedata-bad-title": "Ongeldige titel: $1."
index 4eee09a..a32bb91 100644 (file)
        "longpageerror": "'''Błąd! Wprowadzony przez Ciebie tekst ma {{PLURAL:$1|1 kilobajt|$1 kilobajty|$1 kilobajtów}}. Długość tekstu nie może przekraczać {{PLURAL:$2|1 kilobajt|$2 kilobajty|$2 kilobajtów}}. Tekst nie może być zapisany.'''",
        "readonlywarning": "<strong>Uwaga! Baza danych została zablokowana do celów administracyjnych. W tej chwili nie można zapisać nowej wersji strony. Jeśli chcesz, możesz skopiować ją do pliku, aby móc zapisać ją później.</strong>\n\nAdministrator systemu, który zablokował bazę, podał następujący powód: $1",
        "protectedpagewarning": "'''Uwaga! Możliwość modyfikacji tej strony została zabezpieczona. Mogą ją edytować jedynie użytkownicy z uprawnieniami administratora.'''\nOstatni wpis z rejestru jest pokazany poniżej.",
-       "semiprotectedpagewarning": "'''Uwaga!''' Ta strona została zabezpieczona i tylko zarejestrowani użytkownicy mogą ją edytować.\nOstatni wpis z rejestru jest pokazany poniżej.",
+       "semiprotectedpagewarning": "<strong>Uwaga:</strong>  Ta strona została zabezpieczona i tylko zarejestrowani użytkownicy mogą ją edytować.\nOstatni wpis z rejestru jest pokazany poniżej:",
        "cascadeprotectedwarning": "<strong>Uwaga:</strong> Ta strona została zabezpieczona i tylko użytkownicy z [[Special:ListGroupRights|określonymi uprawnieniami]] mogą ją edytować. Została ona osadzona w {{PLURAL:$1|następującej stronie, która została zabezpieczona|następujących stronach, które zostały zabezpieczone}} z włączoną opcją dziedziczenia:",
        "titleprotectedwarning": "'''Uwaga! Utworzenie strony o tej nazwie zostało zabezpieczone. Do jej utworzenia wymagane są [[Special:ListGroupRights|specyficzne uprawnienia]].'''\nOstatni wpis z rejestru jest pokazany poniżej.",
        "templatesused": "{{PLURAL:$1|Szablon użyty|Szablony użyte}} w tym artykule:",
        "statistics-files": "Przesłane pliki",
        "statistics-edits": "Edycje wykonane od powstania {{GRAMMAR:D.lp|{{SITENAME}}}}",
        "statistics-edits-average": "Średnia liczba edycji na stronę",
-       "statistics-users": "Zarejestrowanych [[Special:ListUsers|użytkowników]]",
+       "statistics-users": "Zarejestrowani użytkownicy",
        "statistics-users-active": "Aktywnych użytkowników",
        "statistics-users-active-desc": "Użytkownicy, którzy byli aktywni w ciągu {{PLURAL:$1|ostatniego dnia|ostatnich $1 dni}}",
        "pageswithprop": "Strony z właściwościami",
        "deadendpages": "Strony bez linków wewnętrznych",
        "deadendpagestext": "Poniższe strony nie posiadają odnośników do innych stron znajdujących się w {{GRAMMAR:MS.lp|{{SITENAME}}}}.",
        "protectedpages": "Zabezpieczone strony",
+       "protectedpages-filters": "Filtry:",
        "protectedpages-indef": "Tylko strony zabezpieczone na zawsze",
        "protectedpages-summary": "Ta strona zawiera listę stron, które są obecnie chronione. Aby uzyskać listę tytułów, których utworzenie jest zabronione, zobacz: [[{{#special:ProtectedTitles}}|{{int:protectedtitles}}]].",
        "protectedpages-cascade": "Tylko strony zabezpieczone rekursywnie",
        "fix-double-redirects": "Zaktualizuj wszystkie przekierowania wskazujące na stary tytuł",
        "move-leave-redirect": "Pozostaw przekierowanie pod dotychczasowym tytułem.",
        "protectedpagemovewarning": "'''UWAGA!''' Ponieważ strona została zabezpieczona, tylko użytkownicy z uprawnieniami administratora mogą zmienić jej nazwę.\nOstatni wpis z rejestru jest pokazany poniżej.",
-       "semiprotectedpagemovewarning": "'''Uwaga!''' Ponieważ strona została zabezpieczona, tylko zarejestrowani użytkownicy mogą zmienić jej nazwę.\nOstatni wpis z rejestru jest pokazany poniżej.",
+       "semiprotectedpagemovewarning": "<strong>Uwaga:</strong> Ponieważ strona została zabezpieczona, tylko zarejestrowani użytkownicy mogą zmienić jej nazwę.\nOstatni wpis z rejestru jest pokazany poniżej:",
        "move-over-sharedrepo": "[[:$1]] istnieje we wspólnym repozytorium. Zmiana nazwy pliku na tę spowoduje przesłonięcie współdzielonego pliku.",
        "file-exists-sharedrepo": "Plik o wybranej nazwie istnieje we wspólnym repozytorium.\nWybierz inną nazwę.",
        "export": "Eksport stron",
index eac5ab0..00f9ab2 100644 (file)
        "nextdiff": "بل توپير →",
        "imagemaxsize": "د انځور کچې بريد:<br /><em>(د دوتنې څرگندونو مخونو لپاره)</em>",
        "thumbsize": "د بټنوک کچه:",
-       "widthheightpage": "$1 × $2, $3 {{PLURAL:$3|مخ|مخونه}}",
+       "widthheightpage": "$1 × $2، $3 {{PLURAL:$3|مخ|مخونه}}",
        "file-info": "د دوتنې کچه: $1, MIME ډول: $2",
        "file-info-size": "$1 × $2 پېکسل, د دوتنې کچه: $3, MIME بڼه: $4",
        "file-info-size-pages": "$1 × $2 پېکسل، دوتنې کچه: $3، MIME ډول: $4، $5 {{PLURAL:$5|مخ|مخونه}}",
index f1bf26e..69396de 100644 (file)
        "toolbox": "Ferramentas",
        "tool-link-userrights": "Alterar grupos {{GENDER:$1|do utilizador|da utilizadora}}",
        "tool-link-userrights-readonly": "Ver grupos {{GENDER:$1|do utilizador|da utilizadora}}",
-       "tool-link-emailuser": "Enviar correio eletrónico a {{GENDER:$1|este utilizador|esta utilizadora|este(a) utilizador(a)}}",
+       "tool-link-emailuser": "Enviar correio {{GENDER:$1|ao utilizador|à utilizadora}}",
        "imagepage": "Ver página de ficheiro",
        "mediawikipage": "Ver página de mensagem",
        "templatepage": "Ver página de predefinição",
        "viewsource-title": "Mostrar código-fonte de $1",
        "actionthrottled": "Operação limitada",
        "actionthrottledtext": "Como medida anti-spam, está impedido de realizar esta operação demasiadas vezes num espaço de tempo curto e já excedeu esse limite. Tente de novo dentro de alguns minutos, por favor.",
-       "protectedpagetext": "Esta página foi protegida para prevenir a sua edição.",
+       "protectedpagetext": "Esta página foi protegida para impedir a sua edição ou outras operações.",
        "viewsourcetext": "Pode ver e copiar o conteúdo desta página.",
        "viewyourtext": "Pode ver e copiar o código-fonte das <strong>suas edições</strong> desta página.",
-       "protectedinterface": "Esta página fornece o texto da interface ao software, e está protegida para prevenir abusos.",
+       "protectedinterface": "Esta página fornece o texto da interface ao programa informático desta wiki e está protegida para impedir abusos. Para adicionar ou modificar as traduções em todas as wikis, use o [https://translatewiki.net/ translatewiki.net], o projeto de localização do MediaWiki.",
        "editinginterface": "<strong>Aviso:</strong> Está a editar uma página usada para fornecer texto de interface ao software. Alterações a esta página afetarão a aparência da interface de utilizador para os outros utilizadores.",
        "translateinterface": "Para adicionar ou alterar traduções para todas as wikis, considere utilizar a [https://translatewiki.net/wiki/Main_Page?setlang=pt translatewiki.net], um projeto destinado à tradução do MediaWiki.",
        "cascadeprotected": "Esta página foi protegida contra edições por estar transcluída {{PLURAL:$1|na página listada|nas páginas listadas}} a seguir, ({{PLURAL:$1|página essa que está protegida|páginas essas que estão protegidas}} com a opção de proteção \"em cascata\" ativada):\n$2",
        "passwordsent": "Foi enviada uma palavra-passe nova para o endereço de correio eletrónico do utilizador \"$1\".\nVolte a iniciar sessão após recebê-la, por favor.",
        "blocked-mailpassword": "O seu endereço IP está bloqueado para edição. Para evitar abusos, não é permitido usar a recuperação da palavra-passe a partir deste endereço IP.",
        "eauthentsent": "Foi enviada uma mensagem de confirmação para o endereço de correio eletrónico que especificou.\nAntes que seja enviada qualquer outra mensagem para a conta, terá de seguir as instruções na mensagem enviada, de modo a confirmar que a conta lhe pertence.",
-       "throttled-mailpassword": "Já foi enviada uma mensagem de reinício da palavra-passe {{PLURAL:$1|na última hora|nas últimas $1 horas}}.\nPara prevenir abusos, só pode ser enviada uma mensagem de reinício da palavra-passe a cada {{PLURAL:$1|hora|$1 horas}}.",
+       "throttled-mailpassword": "Já foi enviada uma mensagem de reinício da palavra-passe {{PLURAL:$1|na última hora|nas últimas $1 horas}}.\nPara impedir abusos, só pode ser enviada uma mensagem de reinício da palavra-passe a cada {{PLURAL:$1|hora|$1 horas}}.",
        "mailerror": "Erro ao enviar correio eletrónico: $1",
        "acct_creation_throttle_hit": "Visitantes desta wiki com um endereço IP igual ao seu criaram {{PLURAL:$1|uma conta|$1 contas}} nos últimos (ou últimas) $2, o que é o máximo permitido neste período de tempo.\nEm resultado, visitantes com este endereço IP não podem criar mais nenhuma conta de momento.",
        "emailauthenticated": "O seu endereço de correio eletrónico foi confirmado a $2, às $3.",
        "template-loop-category-desc": "Esta página contém um ciclo infinito de predefinições, isto é, uma predefinição que se chama a si própria recursivamente.",
        "template-loop-warning": "<strong>Aviso:</strong> Esta página chama [[:$1]] o que causa um ciclo infinito de predefinições (uma chamada recursiva sem término).",
        "parser-template-recursion-depth-warning": "Foi excedido o limite da profundidade de recursividade nas predefinições ($1)",
-       "language-converter-depth-warning": "O limite de profundidade do conversor de idiomas excedeu a ($1)",
+       "language-converter-depth-warning": "O limite de profundidade do conversor de línguas foi excedido ($1)",
        "node-count-exceeded-category": "Páginas em que o total de nós é excedido",
        "node-count-exceeded-category-desc": "A página excede a contagem de nós permitida.",
        "node-count-exceeded-warning": "A página excedeu o total de nós",
        "statistics-files": "Ficheiros carregados",
        "statistics-edits": "Edições de páginas desde que a wiki {{SITENAME}} foi instalada",
        "statistics-edits-average": "Média de edições por página",
-       "statistics-users": "[[Special:ListUsers|Utilizadores]] registados",
+       "statistics-users": "Utilizadores registados",
        "statistics-users-active": "Utilizadores ativos",
        "statistics-users-active-desc": "Utilizadores que efetuaram uma operação {{PLURAL:$1|no último dia|nos últimos $1 dias}}",
        "pageswithprop": "Páginas que usam uma propriedade",
        "deadendpages": "Páginas sem saída",
        "deadendpagestext": "As seguintes páginas não contêm hiperligações para outras páginas na wiki {{SITENAME}}.",
        "protectedpages": "Páginas protegidas",
+       "protectedpages-filters": "Filtros:",
        "protectedpages-indef": "Apenas proteções indefinidas",
        "protectedpages-summary": "Esta página lista páginas existentes que estão protegidas. Para ver os títulos cuja criação está impossibilitada, consulte [[{{#special:ProtectedTitles}}|{{int:protectedtitles}}]].",
        "protectedpages-cascade": "Apenas proteções em cascata",
        "block": "Bloquear utilizador",
        "unblock": "Desbloquear utilizador",
        "blockip": "Bloquear {{GENDER:$1|utilizador|utilizadora}}",
-       "blockiptext": "Utilize o formulário abaixo para bloquear o acesso de escrita a um endereço IP específico ou a um nome de utilizador.\nIsto só deve ser feito para prevenir vandalismo e de acordo com a [[{{MediaWiki:Policy-url}}|política]]. Indique a seguir um motivo de bloqueio específico (por exemplo, indicando as páginas que foram alvo de vandalismo).\nPode bloquear intervalos de endereços IP com a sintaxe [https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing CIDR]; o maior intervalo permitido é /$1 para IPv4 e /$2 para IPv6.",
+       "blockiptext": "Utilize o formulário abaixo para bloquear o acesso de escrita de um endereço IP específico ou de um nome de utilizador.\nIsto só deve ser feito para impedir vandalismo e de acordo com as [[{{MediaWiki:Policy-url}}|normas]]. Indique abaixo um motivo de bloqueio específico (por exemplo, mencionando as páginas que foram alvo de vandalismo).\nPode bloquear intervalos de endereços IP com a sintaxe [https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing CIDR]; o maior intervalo permitido é /$1 para IPv4 e /$2 para IPv6.",
        "ipaddressorusername": "Endereço IP ou nome de utilizador:",
        "ipbexpiry": "Expiração:",
        "ipbreason": "Motivo:",
        "import-mapping-namespace": "Importar para um domínio:",
        "import-mapping-subpage": "Importar como sub-páginas da seguinte página:",
        "import-upload-filename": "Nome do ficheiro:",
-       "import-upload-username-prefix": "Prefixo interwikis:",
+       "import-upload-username-prefix": "Prefixo para o nome de utilizador:",
        "import-assign-known-users": "Atribuir as edições aos utilizadores locais se o utilizador nomeado existir localmente",
        "import-comment": "Comentário:",
        "importtext": "Exporte o ficheiro da wiki de origem utilizando a página especial [[Special:Export|exportação de páginas]].\nGrave o ficheiro no seu computador e importe-o aqui.",
        "imported-log-entries": "{{PLURAL:$1|Foi importada $1 entrada|Foram importadas $1 entradas}} de registo.",
        "importfailed": "A importação falhou: $1",
        "importunknownsource": "Tipo da fonte de importação desconhecido",
-       "importnoprefix": "Não foi fornecido nenhum prefixo interwikis",
+       "importnoprefix": "Não foi fornecido nenhum prefixo interwiki para o nome de utilizador",
        "importcantopen": "Não foi possível abrir o ficheiro a importar",
        "importbadinterwiki": "Hiperligação interwikis incorreta",
        "importsuccess": "Importação completa!",
        "tag-mw-undo": "Desfazer",
        "tag-mw-undo-description": "Edições que desfazem edições anteriores usando a hiperligação «desfazer»",
        "tags-title": "Etiquetas de modificação válidas",
-       "tags-intro": "Esta página lista as etiquetas com que o software poderá marcar uma edição, e o seu significado.",
+       "tags-intro": "Esta página lista as etiquetas com que o software poderá marcar uma edição e o respetivo significado.",
        "tags-tag": "Nome da etiqueta",
        "tags-display-header": "Aparência nas listas de modificações",
        "tags-description-header": "Descrição completa do significado",
        "tags-delete-explanation-initial": "Está prestes a eliminar a etiqueta \"$1\" da base de dados.",
        "tags-delete-explanation-in-use": "Será removida de {{PLURAL:$2|$2 edição ou entrada de registo|todas as $2 edições e/ou entradas de registo}} em que está atualmente aplicada.",
        "tags-delete-explanation-warning": "Esta ação é <strong>irreversível</strong> e <strong>não pode ser desfeita</strong>, nem mesmo por administradores da base de dados. Tenha a certeza de que é esta etiqueta que pretende eliminar.",
-       "tags-delete-explanation-active": "<strong>A etiqueta \"$1\" ainda está ativa e continuará a ser aplicada no futuro.</strong> Para prevenir que isto aconteça, deve dirigir-se ao(s) local(is) em que a etiqueta é aplicada, e a partir daí, desativá-la.",
+       "tags-delete-explanation-active": "<strong>A etiqueta \"$1\" ainda está ativa e continuará a ser aplicada no futuro.</strong> Para impedir que isto aconteça, dirija-se ao local, ou locais, em que a etiqueta é aplicada e desative-a lá.",
        "tags-delete-reason": "Motivo:",
        "tags-delete-submit": "Eliminar irreversivelmente esta etiqueta",
        "tags-delete-not-allowed": "Etiquetas definidas por uma extensão não podem ser eliminadas, a menos que a extensão, especificamente, o permita.",
index c07c1fa..8aee6f2 100644 (file)
        "savechanges": "Text on the button to save the changes to an existing page. It should be an action which is short and makes clear that the effect is immediate and public.\n\nSee also {{msg-mw|showpreview}} and {{msg-mw|showdiff}} for the other buttons, and {{msg-mw|savearticle}} for the label for the button when the page is being modified.\n\nNote: This i18n is being introduced in advance of usage to provide extra time for translators.\n\nSee also:\n* {{msg-mw|Accesskey-publish}}\n* {{msg-mw|Tooltip-publish}}\n{{Identical|Save changes}}",
        "publishpage": "Text on the button to create a new page on a public wiki. It should be an action which is short and makes clear that the effect is immediate and public.\n\nSee also {{msg-mw|showpreview}} and {{msg-mw|showdiff}} for the other buttons, and {{msg-mw|publishchanges}} for the label for the button when the page is being modified.\n\nNote: This i18n is being introduced in advance of usage to provide extra time for translators.\n\nSee also:\n* {{msg-mw|Accesskey-publish}}\n* {{msg-mw|Tooltip-publish}}\n{{Identical|Publish page}}",
        "publishchanges": "Text on the button to save the changes to an existing page on a public wiki. It should be an action which is short and makes clear that the effect is immediate and public.\n\nSee also {{msg-mw|showpreview}} and {{msg-mw|showdiff}} for the other buttons, and {{msg-mw|publishchanges}} for the label for the button when the page is being created.\n\nNote: This i18n is being introduced in advance of usage to provide extra time for translators.\n\nSee also:\n* {{msg-mw|Accesskey-publish}}\n* {{msg-mw|Tooltip-publish}}\n{{Identical|Publish changes}}",
-       "savearticle-start": "Text on the button to start the process to create a new page. Usually just {{msg-mw|savearticle}} with an ellipsis (…).",
+       "savearticle-start": "Text on the button to start the process to create a new page. Usually just {{msg-mw|savearticle}} with an ellipsis (…).\n{{Identical|Save page}}",
        "savechanges-start": "Text on the button to start the process save the changes to an existing page. Usually just {{msg-mw|savechanges}} with an ellipsis (…).",
        "publishpage-start": "Text on the button to start the process create a new page on a public wiki. Usually just {{msg-mw|publishpage}} with an ellipsis (…).",
        "publishchanges-start": "Text on the button to start the process save the changes to an existing page on a public wiki. Usually just {{msg-mw|publishchanges}} with an ellipsis (…).",
        "deadendpages-summary": "{{notranslate}}\nThe summary displayed at the top of [[Special:Deadendpages]]. [[mw:Manual:Interface/Special pages summary|mw manual]].",
        "deadendpagestext": "Introductory text for [[Special:DeadendPages]]",
        "protectedpages": "{{doc-special|ProtectedPages}}",
+       "protectedpages-filters": "Title in [[Special:ProtectedPages]]\n{{Identical|Filter}}",
        "protectedpages-indef": "Option in [[Special:ProtectedPages]]",
        "protectedpages-summary": "Summary of [[Special:ProtectedPages]].\n\nSee also:\n* {{msg-mw|Protectedtitles-summary}}",
        "protectedpages-cascade": "Option in [[Special:ProtectedPages]]",
        "import-mapping-namespace": "Used as label for the second of three radio buttons in Import form on [[Special:Import]]. The radio button is followed by a drop-down list from which the user can select a namespace.\n\nSee also:\n* {{msg-mw|Import-mapping-default}}\n* {{msg-mw|Import-mapping-subpage}}",
        "import-mapping-subpage": "Used as label for the third of three radio buttons in Import form on [[Special:Import]]. The radio button is followed by a text box in which the user can type a page name. The imported pages will be created as subpages of the entered page name.\n\nSee also:\n* {{msg-mw|Import-mapping-default}}\n* {{msg-mw|Import-mapping-namespace}}",
        "import-upload-filename": "Used on [[Special:Import]] as label for upload of an XML file containing the pages to import.\n{{Identical|Filename}}",
-       "import-upload-username-prefix": "Used as label for input box in [[Special:Import]].",
+       "import-upload-username-prefix": "Used as the label for an input box in [[Special:Import]]. The contents of that box are used as a prefix to the usernames in page histories.",
        "import-assign-known-users": "Use as label for checkbox in [[Special:Import]].",
        "import-comment": "Used as label for input box in [[Special:Import]].\n\nSee also:\n* {{msg-mw|Import-interwiki-history}}\n* {{msg-mw|Import-interwiki-templates}}\n* {{msg-mw|Import-interwiki-namespace}}\n* {{msg-mw|Import-interwiki-rootpage}}\n* {{msg-mw|Import-interwiki-submit}}\n{{Identical|Comment}}",
        "importtext": "Used in the Import form on [[Special:Import]].",
        "imported-log-entries": "Used as success message. Parameters:\n* $1 - number of log items\nSee also:\n* {{msg-mw|Importnopages}} - fatal error message",
        "importfailed": "Used as error message in [[Special:Import]]. Parameters:\n* $1 - import source\nSee also:\n* {{msg-mw|Importstart}}\n* {{msg-mw|Importsuccess}}",
        "importunknownsource": "Used as error message in [[Special:Import]].\n\nSee also:\n* {{msg-mw|import-token-mismatch}}\n* {{msg-mw|import-invalid-interwiki}}\n* {{msg-mw|Importunknownsource}}",
-       "importnoprefix": "Used as error message in [[Special:Import]]. Usually this error means that import via upload was attempted and the {{msg-mw|import-upload-username-prefix}} field was left empty.",
+       "importnoprefix": "Used as error message in [[Special:Import]]. Usually this error means that an import via upload was attempted, and the {{msg-mw|import-upload-username-prefix}} field was left empty.",
        "importcantopen": "Used as error message when importing from file or from URL.",
        "importbadinterwiki": "Used as error message when importing from interwiki.\n\nSee also:\n* {{msg-mw|Import-noarticle}}\n* {{msg-mw|Importbadinterwiki}}",
        "importsuccess": "Used in [[Special:Import]].\n\nSee also:\n* {{msg-mw|Importstart}}\n* {{msg-mw|Importfailed}}",
index 89fc7e1..64b2ee4 100644 (file)
                        "OlegCinema",
                        "Movses",
                        "Patrick Star",
-                       "Happy13241"
+                       "Happy13241",
+                       "Vcohen"
                ]
        },
        "tog-underline": "Подчёркивание ссылок:",
        "passwordreset-email": "Адрес электронной почты:",
        "passwordreset-emailtitle": "Сведения об учётной записи {{SITENAME}}",
        "passwordreset-emailtext-ip": "Кто-то (вероятно, вы, с IP-адреса $1) запросил сброс пароля к вашей учётной записи в проекте {{SITENAME}} ($4).\nС этим адресом электронной почты {{PLURAL:$3|1=связана следующая учётная запись|связаны следующие учётные записи}}:\n\n$2\n\n{{PLURAL:$3|1=Этот временный пароль будет|Эти временные пароли будут}} действовать {{PLURAL:$5|$5 день|$5 дня|$5 дней|1=один день}}.\nВы должны представиться системе и выбрать новый пароль. \nЕсли вы не делали этого запроса, или вспомнили свой исходный пароль и не желаете его менять, \nто можете проигнорировать это сообщение и продолжить использовать свой старый пароль.",
-       "passwordreset-emailtext-user": "Участник $1 из проекта {{SITENAME}} запросил сброс пароля для вашей учётной записи в проекте {{SITENAME}} ($4).\nС этим адресом электронной почты {{PLURAL:$3|1=связана следующая учётная запись|связаны следующие учётные записи}}:\n\n$2\n\n{{PLURAL:$3|1=Этот временный пароль будет|Эти временные пароли будут}} действовать {{PLURAL:$5|$5 день|$5 дней|$5 дня|1=один день}}.\nВы должны представиться системе и выбрать новый пароль.\nЕсли вы не делали этого запроса или вспомнили свой исходный пароль и не желаете его менять, \nто можете проигнорировать это сообщение и продолжить использовать свой старый пароль.",
+       "passwordreset-emailtext-user": "Участник $1 из проекта {{SITENAME}} запросил сброс пароля для вашей учётной записи в проекте {{SITENAME}} ($4).\nС этим адресом электронной почты {{PLURAL:$3|1=связана следующая учётная запись|связаны следующие учётные записи}}:\n\n$2\n\n{{PLURAL:$3|1=Этот временный пароль будет|Эти временные пароли будут}} действовать {{PLURAL:$5|один день|$5 дня|$5 дней}}.\nВы должны представиться системе и выбрать новый пароль.\nЕсли вы не делали этого запроса или вспомнили свой исходный пароль и не желаете его менять, \nто можете проигнорировать это сообщение и продолжить использовать свой старый пароль.",
        "passwordreset-emailelement": "Имя участника: \n$1\n\nВременный пароль: \n$2",
        "passwordreset-emailsentemail": "Если это адрес электронной почты связан с вашей учётной записью, вам будет отправлено письмо для сброса пароля.",
        "passwordreset-emailsentusername": "Если есть адрес электронной почты, связанный с этим именем участника, то будет отправлено письмо для восстановления пароля.",
        "deadendpages": "Тупиковые страницы",
        "deadendpagestext": "Следующие страницы не содержат ссылок на другие страницы в этой вики.",
        "protectedpages": "Защищённые страницы",
+       "protectedpages-filters": "Фильтры:",
        "protectedpages-indef": "Только бессрочные защиты",
        "protectedpages-summary": "На этой странице перечислены существующие страницы, которые в настоящее время защищены. Для списка названий, которые защищены от создания см. [[{{#special:ProtectedTitles}}|{{int:protectedtitles}}]].",
        "protectedpages-cascade": "Только каскадная защита",
        "autosumm-blank": "Полностью удалено содержимое страницы",
        "autosumm-replace": "Содержимое страницы заменено на «$1»",
        "autoredircomment": "Перенаправление на [[$1]]",
-       "autosumm-removed-redirect": "Удалённое перенаправление на [[$1]]",
+       "autosumm-removed-redirect": "Удалено перенаправление на [[$1]]",
        "autosumm-changed-redirect-target": "Перенаправление изменено с [[$1]] на [[$2]]",
        "autosumm-new": "Новая страница: «$1»",
        "autosumm-newblank": "Создана пустая страница",
        "tag-mw-contentmodelchange-description": "Правки, которые [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:ChangeContentModel изменяют модель содержимого] страницы",
        "tag-mw-new-redirect": "новое перенаправление",
        "tag-mw-new-redirect-description": "Правки, которые создают новое перенаправление или изменяют страницу на перенаправление",
-       "tag-mw-removed-redirect": "удалённое перенаправление",
+       "tag-mw-removed-redirect": "удалено перенаправление",
        "tag-mw-removed-redirect-description": "Правки, которые изменяют существующее перенаправление на не-перенаправление",
        "tag-mw-changed-redirect-target": "изменение цели перенаправления",
        "tag-mw-changed-redirect-target-description": "Правки, которые изменяют цель перенаправления",
index 31c4d98..575cfa1 100644 (file)
        "upload-tryagain": "Билэ туһунан сурук уларытыытын ыыт",
        "upload-tryagain-nostash": "Билэни уонна ойуулааһынын хос ыыт",
        "uploadnologin": "Биикигэ ааккын билиһиннэрбэтиҥ",
-       "uploadnologintext": "Билэлэри киллэрэргэ $1 наада",
+       "uploadnologintext": "Билэлэри киллэрэргэ $1",
        "upload_directory_missing": "Суруйуу паапката ($1) суох, ону ааһан сиэрбэр ону бэйэтэ оҥорор кыаҕа суох.",
        "upload_directory_read_only": "($1) директорияҕа сиэрбэр билэни суруйар кыаҕа суох.",
        "uploaderror": "Билэ суруллубата",
index c7ee1f6..c8587bb 100644 (file)
        "nmembers": "{{PLURAL:$1|رکن|اراکین}}",
        "prefixindex": "سارے ورقے بمع سابقہ",
        "prefixindex-submit": "ݙِکھاؤ",
+       "protectedpages-filters": "نتارے:",
        "protectedpages-page": "ورقہ",
        "protectedpages-reason": "سبب",
        "protectedpages-unknown-timestamp": "اݨ سونہاں",
        "invert": "انتخاب معکوس",
        "namespace_association": "رلدے ناں دی تھاں",
        "blanknamespace": "(مکھ)",
-       "contributions": " $1 ورتن آلے دا حصہ",
+       "contributions": "\n{{GENDER:$1|ورتݨ آلے}} دیاں حصے داریاں",
        "contributions-title": "صارف $1 دی شراکتاں",
        "mycontris": "شراکتاں",
        "anoncontribs": "شراکتاں",
index eb8680d..2bb516c 100644 (file)
        "statistics-files": "Naložene datoteke",
        "statistics-edits": "Urejanja strani od postavitve {{GRAMMAR:rodilnik|{{SITENAME}}}}",
        "statistics-edits-average": "Povprečno število urejanj na stran",
-       "statistics-users": "Registrirani [[Special:ListUsers|uporabniki]]",
+       "statistics-users": "Registrirani uporabniki",
        "statistics-users-active": "Aktivni uporabniki",
        "statistics-users-active-desc": "Uporabniki, ki so izvedli dejanje v {{PLURAL:$1|zadnjem dnevu|zadnjih $1 dneh}}",
        "pageswithprop": "Strani z lastnostmi strani",
        "deadendpages": "Članki brez delujočih povezav",
        "deadendpagestext": "Spodaj navedene strani se ne povezujejo na druge članke v {{GRAMMAR:dajalnik|{{SITENAME}}}}.",
        "protectedpages": "Zaščitene strani",
+       "protectedpages-filters": "Filtri:",
        "protectedpages-indef": "Samo neomejene zaščite",
        "protectedpages-summary": "Stran navaja obstoječe strani, ki so trenutno zaščitene. Za seznam strani, ki so zaščitene pred ustvarjanjem, glej [[{{#special:ProtectedTitles}}|{{int:protectedtitles}}]].",
        "protectedpages-cascade": "Le kaskadne zaščite",
index e4b1807..6dad251 100644 (file)
        "userlogin-createanother": "Отвори још један налог",
        "createacct-emailrequired": "Имејл адреса",
        "createacct-emailoptional": "Имејл адреса (необавезно)",
-       "createacct-email-ph": "Унесите Вашу имејл адресу",
+       "createacct-email-ph": "Унесите своју имејл адресу",
        "createacct-another-email-ph": "Унесите имејл адресу",
        "createaccountmail": "Користите привремену, случајно створену лозинку и пошаљите на наведену имејл адресу",
        "createaccountmail-help": "Може се користити да се некоме направи налог без сазнања лозинке.",
        "recentchanges-network": "Због техничког проблема не могу да учитам резултате. Покушајте поновно да учитате страницу.",
        "recentchanges-notargetpage": "Унесите назив странице како бисте видели сродне измене.",
        "recentchanges-feed-description": "Пратите скорашње измене уз помоћ овог довода.",
-       "recentchanges-label-newpage": "Ð\9eвом Ð¸Ð·Ð¼ÐµÐ½Ð¾Ð¼ Ñ\98е Ð½Ð°Ð¿Ñ\80авÑ\99ена Ð½ова страница",
+       "recentchanges-label-newpage": "Ð\9dова страница",
        "recentchanges-label-minor": "Ово је мања измена",
        "recentchanges-label-bot": "Ову измену је начинио бот",
        "recentchanges-label-unpatrolled": "Ова измена још није патролирана",
        "htmlform-int-toolow": "Наведена вредност је испод минимума од $1",
        "htmlform-int-toohigh": "Наведена вредност је изнад максимума од $1",
        "htmlform-required": "Ова вредност је обавезна.",
-       "htmlform-submit": "Ð\9fоÑ\88аÑ\99и",
+       "htmlform-submit": "Ð\9fоÑ\81Ñ\82ави",
        "htmlform-reset": "Врати измене",
        "htmlform-selectorother-other": "Друго",
        "htmlform-no": "Не",
index 6522fb0..f2a9bba 100644 (file)
        "recentchanges-noresult": "Nema promena u zadatom vremenu za zadate kriterijume.",
        "recentchanges-notargetpage": "Unesite naziv stranice kako biste videli srodne izmene.",
        "recentchanges-feed-description": "Pratite skorašnje izmene uz pomoć ovog dovoda.",
-       "recentchanges-label-newpage": "Ovom izmenom napravljena je nova izmena",
+       "recentchanges-label-newpage": "Nova stranica",
        "recentchanges-label-minor": "Ovo je manja izmena",
        "recentchanges-label-bot": "Ovu izmenu je napravio bot",
        "recentchanges-label-unpatrolled": "Ova izmena još nije patrolirana",
index 1887c6e..3e884f9 100644 (file)
        "statistics-files": "Uppladdade filer",
        "statistics-edits": "Sidredigeringar sedan {{SITENAME}} startades",
        "statistics-edits-average": "Redigeringar per sida i genomsnitt",
-       "statistics-users": "Registrerade [[Special:ListUsers|användare]]",
+       "statistics-users": "Registrerade användare",
        "statistics-users-active": "Aktiva användare",
        "statistics-users-active-desc": "Användare som utfört någon åtgärd under {{PLURAL:$1|det senaste dygnet|de senaste $1 dygnen}}",
        "pageswithprop": "Sidor med en sidegenskap",
        "deadendpages": "Sidor utan länkar",
        "deadendpagestext": "Följande sidor saknar länkar till andra sidor på {{SITENAME}}.",
        "protectedpages": "Skyddade sidor",
+       "protectedpages-filters": "Filter:",
        "protectedpages-indef": "Endast skydd på obestämd tid",
        "protectedpages-summary": "Denna sida listar befintliga sidor som för närvarande är skyddade. För en lista över titlar som skyddas från att skapas, se [[{{#special:ProtectedTitles}}|{{int:protectedtitles}}]].",
        "protectedpages-cascade": "Endast kaskaderande skydd",
index 5441099..f0a53db 100644 (file)
                        "Przem(1)s"
                ]
        },
-       "tog-underline": "Podsztrychńyńcy linkůw:",
-       "tog-hideminor": "Schow drobne pomjyńańa we ńydowno pomjyńanych",
-       "tog-hidepatrolled": "Schow sprowdzůne sprowjyńa we ńydowno pomjyńanych",
-       "tog-newpageshidepatrolled": "Schow sprawdzůne zajty na wykoźe nowych zajtůw",
-       "tog-extendwatchlist": "Pokoż na mojij pozůrliśće wszyjske, a ńy jyno uostatńe sprowjyńa",
-       "tog-usenewrc": "Używej poszyrzyńo ńydowno pomjyńanych (JavaScript)",
-       "tog-numberheadings": "Automatyczno numeracyjo titlůw",
-       "tog-showtoolbar": "Pokoż gurt werkcojgůw (JavaScript)",
-       "tog-editondblclick": "Edycyjo napoczynajům dwa klikńyńća (JavaScript)",
-       "tog-editsectiononrightclick": "Klikńyńće prawym kneflym myszy na titlu tajli<br />napoczyno jigo sprowjańy(JavaScript)",
-       "tog-watchcreations": "Dowům pozůr na zajty, kere żech naszkryfloł",
-       "tog-watchdefault": "Dowům pozůr na zajty, kere żech sprowjoł",
-       "tog-watchmoves": "Dowům pozůr na zajty, kere żech przećepnył",
-       "tog-watchdeletion": "Dowům pozůr na zajty, kere żech wyćepnył",
-       "tog-minordefault": "Kożde moje sprowjańy je ńywjelge",
-       "tog-previewontop": "Uobźyrej przed placym sprowjańo",
-       "tog-previewonfirst": "Obźyrej zajta przi pjyrszym sprowjańu",
-       "tog-enotifwatchlistpages": "Wyślij e-brifa, kej ftoś zmjyńi zajta, na kero dowom pozůr",
+       "tog-underline": "Podsztrychniyniy linkōw:",
+       "tog-hideminor": "Schŏw drobne pōmiany we niydŏwno pōmiynianych",
+       "tog-hidepatrolled": "Schŏw przichwŏlōne pōmiany we niydŏwno pōmiynianych",
+       "tog-newpageshidepatrolled": "Schŏw przichwŏlōne zajty na wykŏzie nowych zajtōw",
+       "tog-extendwatchlist": "Pokŏż na mojij pozōrliście wszyjske, a niy jyno niydŏwne pōmiany",
+       "tog-usenewrc": "Potajluj pōmiany podug zajtōw we niydŏwnych pōmianach i pozōrliście",
+       "tog-numberheadings": "Automatycznŏ nōmeracyjŏ titlōw",
+       "tog-showtoolbar": "Pokŏż spisek nŏczyniōw",
+       "tog-editondblclick": "Edycyjõ napoczynajōm dwa klikniyncia (JavaScript)",
+       "tog-editsectiononrightclick": "Klikniyncie prawym kneflym myszy na titlu tajli<br />napoczynŏ jigo edycyjõ(JavaScript)",
+       "tog-watchcreations": "Przidej zajty, kere żech napisoł i pliki, kere żech wciepoł, na mojã pozōrlistã",
+       "tog-watchdefault": "Przidej zajty i pliki, kere edytujã dō mojij pozōrlisty",
+       "tog-watchmoves": "Przidej zajty i pliki, kere żech przeciepoł na mojã pozōrlistã",
+       "tog-watchdeletion": "Przidej zajty i pliki, kere wyciepujã dō mojij pozōrlisty",
+       "tog-minordefault": "Kożdõ mojã pōmianã cechuj kej niywielgõ",
+       "tog-previewontop": "Pokŏzywej ôbziyranie nad placym edycyje",
+       "tog-previewonfirst": "Pokŏż ôbziyraniy zajty przi piyrszyj edycyji",
+       "tog-enotifwatchlistpages": "Poślij e-brifa, kej ftoś pōmiyni zajtã abo plik ze mojij pozōrlisty.",
        "tog-enotifusertalkpages": "Wyślij e-brifa, kej zajta mojij godki bydźe půmjyńono",
        "tog-enotifminoredits": "Wyślij e-brifa tyż, kej by szło uo drobne pomjyńańa",
        "tog-enotifrevealaddr": "Ńy chow mojigo e-brifa we powjadomjyńach",
        "talkpagelinktext": "dyskusyjŏ",
        "specialpage": "Szpecyjolno zajta",
        "personaltools": "Perzōnŏlne",
-       "talk": "Dyskusyjŏ",
+       "talk": "Dyskusyjo",
        "views": "Ôbŏcz",
        "toolbox": "Nŏczynia",
        "imagepage": "Uobejrz zajta pliku",
        "redirectedfrom": "(Punkńyńto ze $1)",
        "redirectpagesub": "Zajta przekerowujůnco",
        "redirectto": "Przekerowańy do:",
-       "lastmodifiedat": "Ta zajta bůÅ\82a uostatÅ\84o sprowjano $2, $1.",
+       "lastmodifiedat": "Ta zajta bÅ\8dÅ\82a Ã´statnio edytowanÅ\8f $2, $1.",
        "viewcount": "W ta zajta filowano {{PLURAL:$1|tylko roz|$1 rozůw}}.",
        "protectedpage": "Zajta zawarto",
        "jumpto": "Pōdź do:",
        "youhavenewmessagesfromusers": "Mosz $1 uod {{PLURAL:$3|inszygo używocza|$3 używoczy}} ($2).",
        "youhavenewmessagesmanyusers": "Mosz $1 uod wjelu używoczy ($2).",
        "newmessageslinkplural": "{{PLURAL:$1|jedno nowina|999=nowiny}}",
-       "newmessagesdifflinkplural": "{{PLURAL:$1|uostatńe sprowjyńe|999=uostatńe sprowjyńa}}",
+       "newmessagesdifflinkplural": "{{PLURAL:$1|ôstatniŏ pōmiana|999=ôstatnie pōmiany}}",
        "youhavenewmessagesmulti": "Mosz nowe powjadůmjyńa: $1",
        "editsection": "edytuj",
-       "editold": "sprowjej",
+       "editold": "edytuj",
        "viewsourceold": "pokoż zdrzůdło",
-       "editlink": "sprowjej",
+       "editlink": "edytuj",
        "viewsourcelink": "zdrzůdłowy tekst",
        "editsectionhint": "Edytuj tajlã: $1",
        "toc": "Treść",
        "hr_tip": "Poźůmo lińijo (używej mjyrńy)",
        "summary": "Popis půmjyńań:",
        "subject": "Tyjma/iberszryft:",
-       "minoredit": "To je ńywjelge sprowjyńy",
+       "minoredit": "To je niywielgŏ pōmiana",
        "watchthis": "Dej pozůr",
        "savearticle": "Spamjyntej",
        "preview": "Uobźyrańy",
        "accmailtitle": "Hasło posłane.",
        "accmailtext": "Cufalńe hasło lo [[User talk:$1|$1]] uostoło posłane do $2. Hasło lo tygo nowygo kůnta po zalogowańu je mogebność pomjyńić na zajće ''[[Special:ChangePassword|pomjyńańe hasła]]''.",
        "newarticle": "(Nowy)",
-       "newarticletext": "Ńy mo sam jeszcze artikla uo takijj titli. Eli chcesz go sprowjać, naszkryflej niżyj jego tekst (wjyncy informacyj nojdźesz [$1 na zajće půmocy]). Eli żeś chćoł zrobić cośik inksze, naćiś ino knefel \"Nazod\".",
+       "newarticletext": "Niy ma artikla ze takim titlym. Eli chcesz go sprŏwić, napisz niżyj jego tekst (wiyncyj informacyji znojdziesz [$1 na zajcie pōmocy]). Eli jeżeś sam felernie, naciś ino knefel \"Nazŏd\" we swojij przeziyrŏczce.",
        "anontalkpagetext": "---- ''To je zajta godki lo anůnimowych używoczy  - takich, kerzi ńy majům jeszcze swojigo kůnta abo ńy chcům go terozki używać.\nBy jejich idyntyfikować, używomy numerůw IP.\nEli jeżeś anůnimowym używoczym a wydowo Ći śe, aże zamjyszczůne sam kůmyntorze ńy sům skjyrowane do Ćebje, [[Special:CreateAccount|utwůrz kůnto]] abo [[Special:UserLogin|zaloguj śe]] - beztůż uńikńesz potym podobnych ńyporozumjyń.''",
        "noarticletext": "Ńy můmy zajta uo takij titli. Mogesz [{{fullurl:{{FULLPAGENAME}}|action=edit}} wćepać artikel {{FULLPAGENAME}}] abo [[Special:Search/{{PAGENAME}}|sznupać {{PAGENAME}} we inkszych]].",
        "noarticletext-nopermission": "Ta zajta terozki je pusto.\nMogesz [[Special:Search/{{PAGENAME}}|wysznupać ta titla]] we treśćach inkszych zajtůw, abo <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} przesznupać powjůnzane rejery]</span>, nale ńy mosz uprowńyń coby ta zajta wćepać",
        "userpage-userdoesnotexist": "Użytkowńik \"<nowiki>$1</nowiki>\" ńy je zarejesztrowany. Sprowdź eli na pewno chćołżeś stworzyć/pomjynić gynał ta zajta.",
-       "userpage-userdoesnotexist-view": "Konto sprowjorza ''$1'' ńy istnieje.",
+       "userpage-userdoesnotexist-view": "Kōnto używŏcza''$1'' niy je zaregistrowane.",
        "blocked-notice-logextract": "{{GENDER:$1|Tyn sprowjorz|Ta sprowjorka}} mo zawrzite sprowjyńa.",
        "clearyourcache": "'''Dej pozůr:''' Coby uobejrzeć pomjyńańo pů naszkryflańu nowych sztalowań poleć przeglůndorce wyczyśćić zawartość pamjyńći podryncznyj (cache). '''Mozilla / Firefox / Safari:''' przitrzimej ''Shift'' klikajůnc na ''Uodśwjyž'' abo wciś ''Ctrl-Shift-R'' (''Cmd-Shift-R'' na Macu), '''IE :''' przitrzimej ''Ctrl'' klikajůnc na ''Uodśwjyž'' abo wciś ''Ctrl-F5''; '''Konqueror:''': kliknij knefel ''Uodśwjyž'' abo wciś ''F5''; użytkowńicy '''Opery''' mogům być zmuszeńi coby cołkym wyczyśćić jejich pamjyńć podrynczno we menu ''Werkcojgi→Preferencyje''.; '''Internet Explorer:''' trzim ''Ctrl'' a wćiś ''Uodśwjyż'', abo wćiś ''Ctrl-F5''.",
        "usercssyoucanpreview": "!'''Podpowjydź:''' Użyj knefla \"Podglůnd\", coby przetestować Twůj nowy arkusz stylůw CSS abo kod JavaScript przed jego zaszrajbowańym.",
        "updated": "(Pomjyńano)",
        "note": "'''Pozůr:'''",
        "previewnote": "'''To je ino podglůnd - artikel jeszcze ńy je spamjyntany!'''",
-       "continue-editing": "Przyndź do pola sprowjańo",
+       "continue-editing": "Pōdź do placu edycyje",
        "previewconflict": "Wersyjo podglůndano uodnośi śe do tekstu ze pola edycyje na wjyrchu. Tak bydźe wyglůndać zajta jeli zdecydujesz śe jům naszkryflać.",
        "session_fail_preview": "'''Pozůr! Serwer ńy może przetworzić tyj edycyji, beztuż co dane sesyji uostoły utracůne.\nPoprůbuj jeszcze roz.\nEli to tyż ńy do podpory – [[Special:UserLogout|wyloguj śe]] a zaloguj jeszcze roz.'''",
        "session_fail_preview_html": "'''Przepraszomy! Serwer ńy może przetworzić tygo sprowjyńo skuli utraty danych ze sesyji.'''\n\n''Jako iże na {{GRAMMAR:MS.lp|{{SITENAME}}}} włůnczono zostoła uopcyjo \"raw HTML\", podglůnd zostoł schrůńony coby zabezpjeczyć przed atakami JavaScript.''\n\n'''Jeli to je prawiduowo průba sprowjańo, sprůbuj ješče roz. Kejby to ńy pomoguo - wylůguj śe a zalůguj na nowo.'''",
        "token_suffix_mismatch": "'''Twoje sprowjyńy zostoło uodćepane skuli tego, co twůj klijynt pomjyszoł znaki uod interpůnkcyji we żetůńe sprowjyń. Twoje sprowjyńy zostoło uodćepane coby zapobjec zńyszczyńu tekstu zajty. Take felery zdorzajům śe w roźe korzistańo ze felernych anůnimowych śećowych usłůg proxy.'''",
-       "editing": "Sprowjosz $1",
+       "editing": "Edytujesz $1",
        "creating": "Tworzyńy $1",
-       "editingsection": "Sprowjosz $1 (sekcyjo)",
+       "editingsection": "Edytujesz $1 (sekcyjo)",
        "editingcomment": "Sprowjosz \"$1\" (nowy kůmyntorz)",
        "editconflict": "Kůnflikt sprowjyń: $1",
        "explainconflict": "Ftoś zdůnżůł wćepać swoja wersyjo artikla ńim żeś naszkryflou sprowjyńy.\nWe polu edycyji na wjyrchu mosz tekst zajty aktuelńy naszkryflany we baźe danych.\nTwoje pomjyńańo sům we polu edycyji půńiżyj.\nBy wćepać swoje pomjyńańo muśisz pomjyńać tekst we polu na wjyrchu.\n'''Ino''' tekst ze pola na wjyrchu bydźe naszkryflany we baźe jak \nwciśńesz knefel \"$1\".",
        "templatesused": "{{PLURAL:$1|Muster|Mustry}} użyte na tyj zajće:",
        "templatesusedpreview": "{{PLURAL:$1|Muster|Mustry}} użyte na tyj zajće:",
        "templatesusedsection": "{{PLURAL:$1|Szablon|Szablůny}} użyte we tyj tajli:",
-       "template-protected": "(zawrzity uod sprowjańo)",
+       "template-protected": "(chrōniōny)",
        "template-semiprotected": "(tajlowo zawarte)",
        "hiddencategories": "Ta zajta je {{PLURAL:$1|we jednyj schrůńunyj katygoryji|we $1 schrůńunych katygoryjach}}:",
        "nocreatetext": "Na {{GRAMMAR:MS.lp|{{SITENAME}}}} tworzyńy nowych zajtůw uograńiczůno.\nMoges sprowjać te co już sům, abo [[Special:UserLogin|zalogować śe, abo śa zaregisztrować]].",
        "parser-template-loop-warning": "Wykryto muster zapyntlyńo: [[$1]]",
        "parser-template-recursion-depth-warning": "Przekroczůno limit głymbokośći rekurencyji mustru ($1)",
        "undo-success": "Sprowjyńy zostoło wycofane. Prosza pomjarkować ukozane půniżyj dyferencyje mjyndzy wersyjůma, coby zweryfikować jejich poprawność, potym zaś naszkryflać pomjyńańo coby zakończyć uoperacyjo.",
-       "undo-failure": "Sprowjyńo ńy idźe wycofać skuli kůnflikta ze wersyjůma postrzedńimi.",
+       "undo-failure": "Edycyjŏ niy może być cofniyntŏ skuli ôstudy ze wersyjōma postrzednimi.",
        "undo-norev": "Sprowjyńo ńy idźe cofnůńć skuli tego, co ńy istńije abo uostoło wyćepane.",
        "undo-summary": "Wycůfańy wersyji $1 naszkryflanej bez [[Special:Contributions/$2|$2]] ([[User talk:$2|godka]])",
        "cantcreateaccount-text": "Tworzyńy kůnta s tygo adresu IP ('''$1''') uostoło zawarte bez użytkowńika [[User:$3|$3]].\n\nSkuli: ''$2''",
        "mergelog": "Skuplowane",
        "revertmerge": "Uodkupluj",
        "mergelogpagetext": "Půńiżyj je lista uostatńich kuplowań historyji půmjyńań zajtůw.",
-       "history-title": "Gyszichta sprowjyń \"$1\"",
+       "history-title": "Historyjŏ pōmian zajty \"$1\"",
        "difference-title": "$1: Růżńice mjyndzy wersyjůma",
        "difference-multipage": "(Porůwnańy zajt)",
        "lineno": "Lińijo $1:",
        "rightslog": "Uprawńyńo",
        "rightslogtext": "Rejer půmjyńań uprawńyń užytkowńikůw.",
        "action-read": "přeglůndańo tyj zajty",
-       "action-edit": "sprowjańo tyj zajty",
+       "action-edit": "edycyje tyj zajty",
        "action-createpage": "tworzyńo zajtůw",
        "action-createtalk": "tworzyńo zajtůw godki",
        "action-createaccount": "utwořyńo tygo kůnta užytkowńika",
        "recentchanges-legend": "Uopcyje ńydowno půmjyńanych",
        "recentchanges-summary": "Ta zajta ukozuje gyszichta uostatńich půmjyńań na tyj wiki.",
        "recentchanges-feed-description": "Dowej pozůr na půmjyńane na uostatku na tyj wiki.",
-       "recentchanges-label-newpage": "Tym sprowjyńym stworzůno nowa zajta",
-       "recentchanges-label-minor": "To je ńywjelge sprowjyńy",
-       "recentchanges-label-bot": "To sprowjyńy bůło zrobjůne uod bota",
-       "recentchanges-label-unpatrolled": "To sprowjyńy ńy bůło jeszcze uowjerzůne",
+       "recentchanges-label-newpage": "Ta edycyjŏ sprŏwiła nowõ zajtã",
+       "recentchanges-label-minor": "To je niywielgŏ pōmiana",
+       "recentchanges-label-bot": "Ta pōmiana sprŏwił bot",
+       "recentchanges-label-unpatrolled": "Ta edycyjŏ niy ôstała jeszcze przichwŏlōnŏ",
        "recentchanges-label-plusminus": "Půmjyńono mjara zajty we bajtach",
        "recentchanges-legend-heading": "<strong>Legynda:</strong>",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (uobejrzij tyż [[Special:NewPages|lista nowych zajt]])",
        "rcshowhideanons-show": "Pokoż",
        "rcshowhideanons-hide": "Schrůń",
        "rcshowhidepatr": "$1 uowjerzůne",
-       "rcshowhidemine": "$1 uody mje sprowjůne",
+       "rcshowhidemine": "$1 moje edycyje",
        "rcshowhidemine-show": "Pokoż",
        "rcshowhidemine-hide": "Schrůń",
-       "rclinks": "Ukoż uostatńe $1 sprowjyń bez uostatńe $2 dńi.",
+       "rclinks": "Ukŏż ôstatnie $1 pōmian bez ôstatnie $2 dni.",
        "diff": "zmj.",
        "hist": "gysz.",
        "hide": "Schrůń",
        "filehist-thumb": "Mińiwersyjo",
        "filehist-thumbtext": "Mińiwersyje $1",
        "filehist-nothumb": "Ńy ma mińjaturki",
-       "filehist-user": "Sprowjorz",
+       "filehist-user": "Używŏcz",
        "filehist-dimensions": "Wymjyry",
        "filehist-filesize": "Rozmior plika",
        "filehist-comment": "Komyntorz",
        "notvisiblerev": "Wersyja zostoua wyćepano",
        "watchlist-details": "Na pozorliśće {{PLURAL:$1|je 1 artikel|sům $1 artikle|je $1 artikli}} ńy rachujůnc zajtůw godek.",
        "wlheader-enotif": "Wysůuańy powjadůmjyń na adres e-brif je zouůnčůne",
-       "wlheader-showupdated": "Zajty, kere bouy sprowjane uod Twoi uostatńi wizyty na ńych zostoy naškryflane '''tuustym'''",
+       "wlheader-showupdated": "Zajty, kere były pōmiyniane ôd twojij ôstatnij nŏwiydzki na nich ôstały ukŏzane '''na rubo'''",
        "wlnote": "Půńižy pokazano {{PLURAL:$1|ostatńy sprawjyńy dokůnane|ostatńy '''$1''' sprawjyńe dokůnane|ostatńych '''$1''' sprawjyń dokůnanych}} bez {{PLURAL:$2|uostatńo godźina|uostatńich '''$2''' godźin}}.",
        "wlshowlast": "Pokož uostatńy $1 godźin $2 dńi ()",
        "watchlist-options": "Uopcyje artikli na kere dowosz pozůr",
        "protect-locked-dblock": "Ńy idźe půmjyńić poźůmu zawarća s kuli tygo co baza danych tyž je zawarto. Uobecne štalowańa dla zajty '''$1''' to:",
        "protect-locked-access": "Ńy moš uprowńyń coby pomjyńyć poziům zawarcia zajty. Uobecne ustawjyńo dlo zajty '''$1''' to:",
        "protect-cascadeon": "Ta zajta je zawarto od pomjyńań, po takjymu, co jei užywo {{PLURAL:$1|ta zajta, kero je zawarto|nastympůjůnce zajty, kere zostauy zawarte}} a opcyjo dźedźičyńo je zaůončono. Možeš pomjyńyć poziům zawarcia tyi zajty, ale dlo dźedźičyńo zawarcia to ńy mo wpuywu.",
-       "protect-default": "Wszyjske używocze mogům sprowjać",
+       "protect-default": "Dozwolōne do wszyjskich używaczy.",
        "protect-fallback": "Wymago pozwolynjo \"$1\"",
        "protect-level-autoconfirmed": "Blokuj nowe a ńyregistrowane używocze",
        "protect-level-sysop": "Ino admini",
        "minimum-size": "Min. wjelgość",
        "maximum-size": "Maksymalno wjelgość",
        "pagesize": "(bajtůw)",
-       "restriction-edit": "Sprowjéj",
+       "restriction-edit": "Edytuj",
        "restriction-move": "Přećepńjyńće",
        "restriction-create": "Stwůř",
        "restriction-upload": "Wćep",
        "blanknamespace": "(przodńo)",
        "contributions": "Ajnzac {{GENDER:$1|używocza|używoczki}}",
        "contributions-title": "Wkłod użytkowńika $1",
-       "mycontris": "Sprowjyńa",
+       "mycontris": "Edycyje",
        "contribsub2": "Lo {{GENDER:$3|używocza|używoczki}} $1 ($2)",
        "nocontribs": "Brak pomjyńań uodpowjadajůncych tym kryterjům.",
        "uctop": "(teroźńo)",
        "autoblocker": "Zawarto Ci sprowjyńo autůmatyczńy, bez tůż co używosz tygo samygo adresu IP, co używocz „[[User:$1|$1]]”.\nPowůd zawarća $1 to: „$2”",
        "blocklogpage": "Gyszichta zawjyrańo",
        "blocklogentry": "zawarto [[$1]], bydźe uodymkńynty: $2 $3",
-       "reblock-logentry": "půmjyńił sztalowańa zawarća uod sprowjyń lů [[$1]], czas zawarćo: $2 $3",
+       "reblock-logentry": "{{GENDER:$2|pōmiynił|pōmiyniła}} nasztalowania zawarciŏ dlŏ [[$1]], czas zawarciŏ: $2 $3",
        "blocklogtext": "Půńižej znojdowo śe lista zawarć zouožůnych i zdjyntych s poščygůlnych adresůw IP.\nNa li'śće ńy mo adresůw IP, kere zawarto w sposůb autůmatyčny.\nCoby přejřeć lista uobecńy aktywnych zawarć, přyńdź na zajta [[Special:BlockList|zawartych adresůw i užytkowńikůw]].",
        "unblocklogentry": "uodymknyu $1",
        "block-log-flags-anononly": "ino anůnimowi",
        "tooltip-pt-anontalk": "Godka użytkowńika do adresu IP spod kerygo sprowjosz",
        "tooltip-pt-preferences": "Moje preferyncyje",
        "tooltip-pt-watchlist": "Lista artiklůw, na kere dowosz pozůr",
-       "tooltip-pt-mycontris": "Lista uody mje sprowjonych",
+       "tooltip-pt-mycontris": "Lista {{GENDER:|moich}} edycyji",
        "tooltip-pt-login": "Chćeli by my, cobyś śe nalogowoł, nale to ńy je powinne",
        "tooltip-pt-logout": "Uodloguj śe ze wiki",
        "tooltip-pt-createaccount": "Namowjůmy do stworzyńo kůnta a zalogůwańo śe, atoli ńy je to uobowjůnzkowe",
        "tooltip-ca-nstab-category": "Ukoż zajta kategoryje",
        "tooltip-minoredit": "Uoznacz ta zmjana za drobno",
        "tooltip-save": "Naszkryflej půmjyńańa",
-       "tooltip-preview": "Ńiż naszkryflosz, uobźyrej efekt twojigo sprowjyńo.",
+       "tooltip-preview": "Niźli spamiyntŏsz pōmiany pozdrzij na efekt swojij edycyje.",
        "tooltip-diff": "Ukozuje twoje půmjyńańa we tekśće",
        "tooltip-compareselectedversions": "Uobźyrej zmjyny mjyndzy dwůma uobranymi wersyjůma tyj zajty",
        "tooltip-watch": "Dodej tyn artikel do pozorlisty",
        "tooltip-recreate": "Wćepej nazod zajta mimo aže bůua wčeśńij wyćepano.",
        "tooltip-upload": "Rozpočyńće wćepywańa",
-       "tooltip-rollback": "\"cofej\" jednym klikńyńćym rewertuje půmjyńańa uod uostatnigo sprowjorza.",
-       "tooltip-undo": "\"anuluj půmjyÅ\84\84a\" cofo to půmjyÅ\84\84y a uodwjyro uokno sprowjaÅ\84a we trybje widoku.\nIdzie naszkryflaÄ\87 powůd we popiÅ\9be půmjyÅ\84\84.",
+       "tooltip-rollback": "\"cofej\" jednym klikniynciym rewertuje pōmianã ôd ôstatnigo używŏcza.",
+       "tooltip-undo": "\"anuluj pÅ\8dmianã\" cofÅ\8f tã edycyjõ i Ã´twiyrÅ\8f Ã´kno edycyje we trybie Ã´bziyraniÅ\8f.\nDozwolÅ\8f na wkludzyniy szticha we popisie pÅ\8dmian.",
        "tooltip-summary": "Krůtko popisz",
        "anonymous": "{{PLURAL:$1|Anůńimowy użytkowńik|Anůńimowe użytkowńiki}} {{SITENAME}}",
        "siteuser": "Užytkowńik {{GRAMMAR:D.lp|{{SITENAME}}}} – $1",
        "filedelete-old-unregistered": "Żůndanyj wersyji plika „$1” ńy ma w baźe danych.",
        "filedelete-current-unregistered": "Plika „$1” ńy ma w baźe danych.",
        "filedelete-archive-read-only": "Serwer WWW ńy może naszkryflać we katalogu ze archiwůma „$1”.",
-       "previousdiff": "← Poprzedńy sprowjyńy",
-       "nextdiff": "Nostympne sprowjyńy →",
+       "previousdiff": "← Starszŏ edycyjŏ",
+       "nextdiff": "Nowszŏ edycyjŏ →",
        "mediawarning": "'''Pozůr!''' Tyn plik može zawjerać zuośliwy kod. Jak go uodymkńyš možeš zaraźić swůj systym.",
        "imagemaxsize": "Na zajtach uopisu plikůw uůgrańič rozmjar uobrazkůw do:",
        "thumbsize": "Rozmjar mińjatůrki",
index 874fcd4..0d42f52 100644 (file)
        "statistics-header-hooks": "دیگر اعداد و شمار",
        "statistics-articles": "مندرج صفحات",
        "statistics-pages": "صفحات",
-       "statistics-pages-desc": "(وکی اقتباسات کے کل صفحات، بشمولِ تبادلۂ خیال، رجوع مکررات وغیرہ۔)",
+       "statistics-pages-desc": "ویکی کے کل صفحات، بشمول تبادلۂ خیال، رجوع مکررات وغیرہ۔",
        "statistics-files": "اپلوڈ کردہ فائلیں",
        "statistics-edits": "{{SITENAME}} کے آغاز سے کل صفحاتی ترامیم",
        "statistics-edits-average": "فی صفحہ اوسط ترامیم",
index a1ff961..d130f51 100644 (file)
        "editingold": "'''Chú ý: bạn đang sửa một phiên bản cũ. Nếu bạn lưu, các sửa đổi trên các phiên bản mới hơn sẽ bị mất.'''",
        "unicode-support-fail": "Trình duyệt của bạn không hỗ trợ Unicode. Đây là yêu cầu bắt buộc nếu bạn muốn sửa đổi trang tại đây, do đó thay đổi của bạn không được lưu.",
        "yourdiff": "Khác",
-       "copyrightwarning": "Xin chú ý rằng tất cả các đóng góp của bạn tại {{SITENAME}} được xem là sẽ phát hành theo giấy phép $2 (xem $1 để biết thêm chi tiết). Nếu bạn không muốn những gì mình viết ra bị sửa đổi không thương tiếc và không sẵn lòng cho phép phát hành lại, xin đừng nhấn nút \"Lưu trang\".<br />\nBạn phải đảm bảo với chúng tôi rằng chính bạn là tác giả của những gì mình viết ra, hoặc chép nó từ một nguồn thuộc phạm vi công cộng hoặc tự do tương đương.<br />\n<strong>ĐỪNG ĐĂNG NỘI DUNG CÓ BẢN QUYỀN MÀ CHƯA XIN PHÉP!</strong>",
+       "copyrightwarning": "Xin chú ý rằng tất cả các đóng góp của bạn tại {{SITENAME}} được xem là sẽ phát hành theo giấy phép $2 (xem $1 để biết thêm chi tiết). Nếu bạn không muốn những gì mình viết ra bị sửa đổi không thương tiếc và không sẵn lòng cho phép phát hành lại, xin đừng nhấn nút “Lưu trang”.<br />\nBạn phải đảm bảo với chúng tôi rằng chính bạn là tác giả của những gì mình viết ra, hoặc chép nó từ một nguồn thuộc phạm vi công cộng hoặc tự do tương đương.<br />\n<strong>ĐỪNG ĐĂNG NỘI DUNG CÓ BẢN QUYỀN MÀ CHƯA XIN PHÉP!</strong>",
        "copyrightwarning2": "Xin chú ý rằng tất cả các đóng góp của bạn tại {{SITENAME}} có thể được sửa đổi, thay thế, hoặc xóa bỏ bởi các thành viên khác. Nếu bạn không muốn trang của bạn bị sửa đổi không thương tiếc, đừng đăng trang ở đây.<br />\nBạn phải đảm bảo với chúng tôi rằng chính bạn là người viết nên, hoặc chép nó từ một nguồn thuộc phạm vi công cộng hoặc tự do tương đương (xem $1 để biết thêm chi tiết).\n'''Đừng đăng nội dung có bản quyền mà không xin phép!'''",
        "editpage-cannot-use-custom-model": "Không thể thay đổi kiểu nội dung của trang này.",
        "longpageerror": "'''Lỗi: Văn bạn mà bạn muốn lưu dài $1 kilôbyte, dài hơn độ dài tối đa cho phép $2 kilôbyte.'''\nKhông thể lưu trang.",
index d47b280..b2792f8 100644 (file)
        "password-login-forbidden": "באַניצן דעם נאָמען און שפּריכוואָרט איז פאַרבאָטן.",
        "mailmypassword": "צוריקשטעלן פאַסווארט",
        "passwordremindertitle": "ניי צייטווייליג פאסווארט פאר {{SITENAME}}",
-       "passwordremindertext": "×¢×\9eעצער (×\9eסת×\9e×\90 ×\90×\99ר, ×¤Ö¿×\95×\9f IP ×\90×\93רעס $1)\n×\94×\90×\98 ×\92×¢×\91×¢×\98×\9f ×\90 × ×\99×\99 ×¤×\90ַס×\95×\95×\90ר×\98 ×¤Ö¿×\90ר {{SITENAME}} ($4).\n×\90 ×¤×¨×\90×\95×\95×\99×\96×\90ר×\99ש ×¤×\90ַס×\95×\95×\90ר×\98 ×¤Ö¿×\90ר ×\91×\90× ×\99צער  \"$2\" ×\90×\99×\96 ×\90×\99צ×\98 \"$3\".\n×\90×\99ר ×\96×\90×\9c×\98 ×\90ר×\99×\99× ×\9c×\90×\92×\99ר×\9f ×\90×\95×\9f ×\90×\95×\99סק×\9c×\95×\99×\91×\9f ×\90 × ×²Ö· ×¤×\90ַס×\95×\95×\90ר×\98.\n×\93×\90ס ×¤×¨×\90×\95×\95×\99×\96×\90ר×\99שע ×¤×\90ַס×\95×\95×\90ר×\98 ×\95×\95×¢×\98 ×\90×\95×\99ס×\92×\99×\99×\9f × ×\90Ö¸×\9a {{PLURAL:$5|×\90×\99×\99×\9f ×\98×\90×\92|$5 ×\98×¢×\92}}\n\n×\90×\95×\99×\91 ×\90×\99×\99נער ×\90× ×\93ערש×\98 ×\94×\90×\98 ×\92×¢×\9e×\90×\9b×\98 ×\93×\99 ×\91×\99×\98×¢, ×\90×\93ער ×\90×\99ר ×\94×\90×\98 ×\99×\90 ×\92×¢×\93ענק×\98 ×\90×\99×\99ער ×¤×\90ס×\95×\95×\90ר×\98 ×\90×\95×\9f ×\90×\99ר ×\98×\95×\98 ×\9eער × ×\99ש×\98 ×\91×\90×\92ער×\9f ×\93×\90ס ×¦×\95 ×\98×\95×\99ש×\9f, ×§×¢× ×\98 ×\90×\99ר ×\90×\99×\92× ×\90ר×\99ר×\9f ×\93×\99 ×\9e×¢×\9c×\93×\95× ×\92 ×\90×\95×\9f ×\95×\95×\99×\99×\98ער × ×\99צ×\9f ×\90×\99×\99ער ×\90×\9c×\98×¢ ×¤×\90ַס×\95×\95×\90ר×\98.",
+       "passwordremindertext": "עמעצער (פֿון IP אדרעס $1)\nהאט געבעטן א ניי פאַסווארט פֿאר {{SITENAME}} ($4).\nא פראוויזאריש פאַסווארט פֿאר באניצער  \"$2\" איז איצט \"$3\".\nאיר זאלט אריינלאגירן און אויסקלויבן א נײַ פאַסווארט.\nדאס פראוויזארישע פאַסווארט וועט אויסגיין נאָך {{PLURAL:$5|איין טאג|$5 טעג}}\n\nאויב איינער אנדערשט האט געמאכט די ביטע, אדער איר האט יא געדענקט אייער פאסווארט און איר טוט מער נישט באגערן דאס צו טוישן, קענט איר איגנארירן די מעלדונג און ווייטער ניצן אייער אלטע פאַסווארט.",
        "noemail": "ס'איז נישט רעקארדירט קיין ע-פאסט אַדרעס פֿאַר באַניצער  \"$1\".",
        "noemailcreate": "איר דאַרפֿט פֿאַרזארגן א גילטיגן ע-פאסט אַדרעס",
        "passwordsent": "א ניי פאסווארט איז געשיקט געווארן צום ע-פאסט אדרעס רעגיסטרירט פאר \"$1\".\nביטע ווידער אריינלאגירן נאך דעם וואס איר באקומט עס.",
        "longpageerror": "'''פעלער: דער טעקסט וואס איר האט ארײַנגעשטעלט איז לאנג {{PLURAL:$1|איין קילאבייט|$1 קילאבייטן}}, וואס איז לענגער פון דעם מאקסימום פון {{PLURAL:$2|איין קילאבייט|$2 קילאבייטן}}.\nער קען נישט ווערן אפגעהיטן.'''",
        "readonlywarning": "<strong>ווארענונג: די דאטנבאזע איז געווארן פארשלאסן פאר אויפהאלטונג, ממילא וועט איר נישט קענען אפהיטן אייערע ענדערונגען אצינד.</strong>\nאיר קענט קאפירן און ארײַנלייגן דעם טעקסט אריין צו א טעקסט טעקע און דאס דארטן אפהיטן אויף שפעטער.\n\nדער אדמיניסטראטאר וואס האט זי פארשלאסן האט מסביר געווען אזוי: $1",
        "protectedpagewarning": "'''ווארענונג:  דער בלאט איז געווארן פארשפארט אז בלויז באניצערס מיט סיסאפ פריווילעגיעס קענען אים ענדערן.'''\nדי פארגאנגענע לאגבוך באשרײַבונג ווערט געוויזן דא:",
-       "semiprotectedpagewarning": "'''×\91×\90×\9eערק×\95× ×\92:''' ×\93ער ×\93×\90Ö¸×\96×\99קער ×\91×\9c×\90Ö·×\98 ×\90×\99×\96 ×¤×\90ַרשפּ×\90ַר×\98, ×\90Ö·×\96×\95×\99 ×\90Ö·×\96 ×\91×\9c×\95×\99×\96 ×\90×\99×\99× ×\92עשר×\99×\91×¢× ע באַניצער קענען אים ענדערן.\nדאָס פאַרגאַנגענע לאָגבוך באַשרייבונג ווערט געוויזן דאָ:",
+       "semiprotectedpagewarning": "'''×\91×\90×\9eערק×\95× ×\92:''' ×\93ער ×\93×\90Ö¸×\96×\99קער ×\91×\9c×\90Ö·×\98 ×\90×\99×\96 ×¤×\90ַרשפּ×\90ַר×\98, ×\90Ö·×\96×\95×\99 ×\90Ö·×\96 ×\91×\9c×\95×\99×\96 ×\90×\95×\99×\98×\90×\9e×\90×\98×\99ש־×\91×\90ש×\98×¢×\98×\99×\92×\98ע באַניצער קענען אים ענדערן.\nדאָס פאַרגאַנגענע לאָגבוך באַשרייבונג ווערט געוויזן דאָ:",
        "cascadeprotectedwarning": "<strong>ווארענונג:</strong> דער בלאט איז פארשפארט אז בלויז באניצער מיט [[Special:ListGroupRights|ספעציפֿישע רעכטן]] קענען אים ענדערן, וויבאלד ער איז איינגעשלאסן אין {{PLURAL:$1| דעם פאלגנדן בלאט, וואס איז|די פאלגנדע בלעטער, וואס זענען}} קאסקאד באשיצט:",
        "titleprotectedwarning": "'''אזהרה: דער בלאט איז פֿארשפאַרט טא דארף מען [[Special:ListGroupRights|ספעציפֿישע רעכטן]] צו שאפֿן אים.'''\nדי פֿאַרגאַנגענע לאגבוך באשרײַבונג ווערט געוויזן דאָ:",
        "templatesused": "{{PLURAL:$1|מוסטער|מוסטערן}} באנוצט אויף דעם בלאט:",
        "statistics-files": "ארויפֿגעלאדענע טעקעס",
        "statistics-edits": "רעדאַקטירונגען זײַט {{SITENAME}} איז אויפֿגעשטעלט",
        "statistics-edits-average": "דורכשניט רעדאַקטירונגען אין א בלאַט",
-       "statistics-users": "×\90×\99×\99× ×\92עשר×\99×\91×¢× ×¢ [[Special:ListUsers|×\91×\90× ×\99צערס]]",
+       "statistics-users": "×\90ײנ×\92עשר×\99×\91×¢× ×¢ ×\91×\90Ö·× ×\99צער",
        "statistics-users-active": "טעטיקע באניצערס",
        "statistics-users-active-desc": "באניצערס וואס האבן דורכגעפירט א פעולה אין די לעצטע {{PLURAL:$1|טאג|$1 טעג}}",
        "pageswithprop": "בלעטער מיט א בלאט אייגנשאפט",
        "deadendpages": "בלינדע בלעטער",
        "deadendpagestext": "די פאלגנדע בלעטער לינקען נישט צו קיין אנדערע בלעטער אין דער וויקי.",
        "protectedpages": "געשיצטע בלעטער",
+       "protectedpages-filters": "פֿילטערס:",
        "protectedpages-indef": "בלויז אומבאַשרענקטע באַשוצינגען",
        "protectedpages-cascade": "בלויז קאַסקאַדירנדיקע באַשיצונגען",
        "protectedpages-noredirect": "פֿארהיילן ווייטערפֿירונגען",
        "fix-double-redirects": "דערהײַנטיקן ווײַטערפֿירונגען צום ארגינעלן טיטל",
        "move-leave-redirect": "איבערלאזן א ווײַטערפֿירונג",
        "protectedpagemovewarning": "'''ווארענונג:  דער בלאט איז געווארן געשיצט אז בלויז באניצערס מיט סיסאפ פריווילעגיעס קענען אים באוועגן.'''\nדי פארגאנגענע לאגבוך באשרײַבונג ווערט געוויזן דא:",
-       "semiprotectedpagemovewarning": "'''×\91×\90×\9eערק×\95× ×\92:''' ×\93ער ×\93×\90×\96×\99×\92ער ×\91×\9c×\90Ö·×\98 ×\90×\99×\96 ×\92עש×\99צ×\98 ×\90×\96 ×\91×\9c×\95×\99×\96 ×\90×\99×\99× ×\92עשר×\99×\91×¢× ע באניצערס קענען אים באוועגן.\nדי פֿאַרגאַנגענע לאגבוך באשרײַבונג ווערט געוויזן דאָ:",
+       "semiprotectedpagemovewarning": "'''×\91×\90×\9eערק×\95× ×\92:''' ×\93ער ×\93×\90×\96×\99×\92ער ×\91×\9c×\90Ö·×\98 ×\90×\99×\96 ×\92עש×\99צ×\98 ×\90×\96 ×\91×\9c×\95×\99×\96 ×\90×\95×\99×\98×\90×\9e×\90×\98×\99ש־×\91×\90ש×\98×¢×\98×\99×\92×\98ע באניצערס קענען אים באוועגן.\nדי פֿאַרגאַנגענע לאגבוך באשרײַבונג ווערט געוויזן דאָ:",
        "move-over-sharedrepo": "[[:$1]] עקזיסטירט אויף א געטיילטן רעפאזיטאריום. ווען מען באוועגט א טעקע צו דעם טיטל וועט דאס איבערשרייבן די געטיילטע טעקע.",
        "file-exists-sharedrepo": "ס'איז שוין פאראן א טעקע מיטן געקליבענעם נאמען אויף א געמיינזאם רעפאזיטאריום.\nזייט אזוי גוט קלייבט אן אנדער נאמען.",
        "export": "עקספארטירן בלעטער",
index 81c092a..1635a7c 100644 (file)
        "action-suppressionlog": "睇呢個私有日誌",
        "action-block": "封鎖呢位用戶嘅編輯",
        "action-protect": "改呢版嘅保護等級",
-       "action-rollback": "速還原某版最後修改人之修改",
+       "action-rollback": "快速反轉某版最後修改人嘅編輯",
        "action-import": "由其它wiki度倒入版",
        "action-importupload": "由檔案上載度倒入版",
        "action-patrol": "標示其它嘅編輯做已巡查嘅",
index f1ed0f4..34771e3 100644 (file)
        "statistics-files": "上传的文件",
        "statistics-edits": "自{{SITENAME}}建立以来的页面编辑数",
        "statistics-edits-average": "每页平均编辑数",
-       "statistics-users": "注册[[Special:ListUsers|用户]]",
+       "statistics-users": "注册用户",
        "statistics-users-active": "活跃用户",
        "statistics-users-active-desc": "在过去{{PLURAL:$1|$1天}}执行过操作的用户",
        "pageswithprop": "有页面属性的页面",
        "deadendpages": "断链页面",
        "deadendpagestext": "以下页面没有链接至{{SITENAME}}的其它页面。",
        "protectedpages": "受保护页面",
+       "protectedpages-filters": "过滤器:",
        "protectedpages-indef": "仅无限期保护",
        "protectedpages-summary": "本页面列出当前受保护的页面。要浏览受限制创建的标题列表,请参见[[{{#special:ProtectedTitles}}|{{int:protectedtitles}}]]。",
        "protectedpages-cascade": "仅级联保护",
index 140f03f..f8f2fba 100644 (file)
        "customcssprotected": "您並沒有權限編輯此 CSS 頁面,因為此頁面包含了其他使用者的個人設定。",
        "customjsprotected": "您並沒有權限編輯此 JavaScript 頁面,因為此頁面包含了其他使用者的個人設定。",
        "mycustomcssprotected": "您沒有權限編輯此 CSS 頁面。",
+       "mycustomjsonprotected": "您沒有權限編輯此 JSON 頁面。",
        "mycustomjsprotected": "您沒有權限編輯此 JavaScript 頁面。",
        "myprivateinfoprotected": "您沒有權限編輯您的私人資訊。",
        "mypreferencesprotected": "您沒有權限編輯您的偏好設定。",
        "savechanges": "儲存變更",
        "publishpage": "發佈頁面",
        "publishchanges": "發佈變更",
+       "savearticle-start": "儲存頁面…",
+       "savechanges-start": "儲存變更…",
+       "publishpage-start": "發佈頁面…",
+       "publishchanges-start": "發佈變更…",
        "preview": "預覽",
        "showpreview": "顯示預覽",
        "showdiff": "顯示變更",
        "default": "預設",
        "prefs-files": "檔案",
        "prefs-custom-css": "自訂 CSS",
+       "prefs-custom-json": "自定義 JSON",
        "prefs-custom-js": "自訂 JavaScript",
-       "prefs-common-config": "所有外觀共用的 CSS/JavaScript:",
+       "prefs-common-config": "所有外觀共用的 CSS/JSON/JavaScript:",
        "prefs-reset-intro": "您可以使用此頁面重設您的偏好設定為網站預設值。\n這個動作將無法復原。",
        "prefs-emailconfirm-label": "電子郵件確認:",
        "youremail": "Email:",
        "right-reupload-shared": "覆蓋共用媒體檔案庫於本地的檔案",
        "right-upload_by_url": "使用 URL 上傳檔案",
        "right-purge": "不須確認即清除網站的頁面快取",
-       "right-autoconfirmed": "不受 IP-based 的註冊頻率限制",
+       "right-autoconfirmed": "不受基於IP的使用頻率限制",
        "right-bot": "將其視為自動程序",
        "right-nominornewtalk": "不顯示討論頁面中次要編輯的新訊息提示",
        "right-apihighlimits": "使用 API 查詢的最高上限值",
        "right-editcontentmodel": "編輯頁面的內容模型",
        "right-editinterface": "編輯使用者介面",
        "right-editusercss": "編輯其他使用者的 CSS 檔",
+       "right-edituserjson": "編輯其他使用者的 JSON 檔",
        "right-edituserjs": "編輯其他使用者的 JavaScript 檔",
        "right-editmyusercss": "編輯自己的使用者 CSS 檔",
+       "right-editmyuserjson": "編輯您自己的使用者 JSON 檔",
        "right-editmyuserjs": "編輯自己的使用者 JavaScript 檔",
        "right-viewmywatchlist": "檢視自己的監視清單",
        "right-editmywatchlist": "編輯自己的監視清單。注意,即使無此權限,某些操作仍會新增頁面至監視清單。",
        "grant-createaccount": "建立帳號",
        "grant-createeditmovepage": "建立、編輯與移動頁面",
        "grant-delete": "刪除頁面、修訂與日誌記錄",
-       "grant-editinterface": "編輯 MediaWiki 命名空間與使用者 CSS/JavaScript",
-       "grant-editmycssjs": "編輯您的使用者 CSS/JavaScript",
+       "grant-editinterface": "編輯 MediaWiki 命名空間與使用者 CSS/JSON/JavaScript",
+       "grant-editmycssjs": "編輯您的使用者 CSS/JSON/JavaScript",
        "grant-editmyoptions": "編輯您的使用者偏好設定",
        "grant-editmywatchlist": "編輯您的監視清單",
        "grant-editpage": "編輯現有的頁面",
        "statistics-files": "已上傳的檔案",
        "statistics-edits": "自 {{SITENAME}} 成立以來的頁面編輯數",
        "statistics-edits-average": "每頁平均編輯數",
-       "statistics-users": "已註冊的 [[Special:ListUsers|使用者]]",
+       "statistics-users": "已註冊的使用者",
        "statistics-users-active": "活動使用者",
        "statistics-users-active-desc": "在最近 $1 天操作過的使用者",
        "pageswithprop": "擁有屬性的頁面",
        "apisandbox-dynamic-error-exists": "命名的參數 \"$1\" 已經存在。",
        "apisandbox-deprecated-parameters": "停用的參數",
        "apisandbox-fetch-token": "自動填寫密鑰",
+       "apisandbox-add-multi": "新增",
        "apisandbox-submit-invalid-fields-title": "部份欄位無效",
        "apisandbox-submit-invalid-fields-message": "請更正已標註的欄位,然後再試一次。",
        "apisandbox-results": "結果",
        "version-specialpages": "特殊頁面",
        "version-parserhooks": "剖析器鉤",
        "version-variables": "變數",
+       "version-editors": "編輯者",
        "version-antispam": "垃圾訊息防止",
        "version-other": "其他",
        "version-mediahandlers": "媒體處理器",
index 16698d1..eed5e7f 100644 (file)
@@ -94,11 +94,11 @@ $specialPageAliases = [
        'MyLanguage'                => [ 'MiIdioma', 'Mi_idioma' ],
        'Mypage'                    => [ 'MiPágina', 'Mi_página' ],
        'Mytalk'                    => [ 'MiDiscusión', 'Mi_discusión' ],
-       'Myuploads'                 => [ 'MisArchivosSubidos' ],
+       'Myuploads'                 => [ 'MisArchivosSubidos', 'Mis_archivos_subidos' ],
        'Newimages'                 => [ 'NuevasImágenes', 'Nuevas_imágenes' ],
        'Newpages'                  => [ 'PáginasNuevas', 'Páginas_nuevas' ],
-       'PasswordReset'             => [ 'RestablecerContraseña' ],
-       'PermanentLink'             => [ 'EnlacePermanente' ],
+       'PasswordReset'             => [ 'RestablecerContraseña', 'Restablecer_contraseña' ],
+       'PermanentLink'             => [ 'EnlacePermanente', 'Enlace_permanente' ],
        'Preferences'               => [ 'Preferencias' ],
        'Prefixindex'               => [ 'PáginasPorPrefijo', 'Páginas_por_prefijo' ],
        'Protectedpages'            => [ 'PáginasProtegidas', 'Páginas_protegidas' ],
@@ -116,7 +116,7 @@ $specialPageAliases = [
        'Specialpages'              => [ 'PáginasEspeciales', 'Páginas_especiales' ],
        'Statistics'                => [ 'Estadísticas' ],
        'Tags'                      => [ 'Etiquetas' ],
-       'TrackingCategories'        => [ 'CategoríasDeSeguimiento' ],
+       'TrackingCategories'        => [ 'CategoríasDeSeguimiento', 'Categorías_de_seguimiento' ],
        'Unblock'                   => [ 'Desbloquear' ],
        'Uncategorizedcategories'   => [ 'CategoríasSinCategorizar', 'Categorías_sin_categorizar' ],
        'Uncategorizedimages'       => [ 'ImágenesSinCategorizar', 'Imágenes_sin_categorizar' ],
diff --git a/languages/messages/MessagesGor.php b/languages/messages/MessagesGor.php
new file mode 100644 (file)
index 0000000..16d1f7e
--- /dev/null
@@ -0,0 +1,30 @@
+<?php
+/** Gorontalo
+ *
+ * To improve a translation please visit https://translatewiki.net
+ *
+ * @ingroup Language
+ * @file
+ *
+ */
+
+$fallback = 'id';
+
+$namespaceNames = [
+       NS_MEDIA            => "Media",
+       NS_SPECIAL          => "Spesial",
+       NS_TALK             => "Lo'iya",
+       NS_USER             => "Ta_ohu'uwo",
+       NS_USER_TALK        => "Lo'iya_ta_ohu'owo",
+       NS_PROJECT_TALK     => "Lo'iya_$1",
+       NS_FILE             => "Berkas",
+       NS_FILE_TALK        => "Lo'iya_berkas",
+       NS_MEDIAWIKI        => "MediaWiki",
+       NS_MEDIAWIKI_TALK   => "Lo'iya_MediaWiki",
+       NS_TEMPLATE         => "Templat",
+       NS_TEMPLATE_TALK    => "Lo'iya_templat",
+       NS_HELP             => "Wubodu",
+       NS_HELP_TALK        => "Lo'iya_wubodu",
+       NS_CATEGORY         => "Dalala",
+       NS_CATEGORY_TALK    => "Lo'iya_dalala",
+];
index 974771f..1997fe7 100644 (file)
--- a/load.php
+++ b/load.php
@@ -36,11 +36,9 @@ if ( !$wgRequest->checkUrlExtension() ) {
        return;
 }
 
-// Don't initialise ChronologyProtector from object cache, and
-// don't wait for unrelated MediaWiki writes when querying ResourceLoader.
-MediaWikiServices::getInstance()->getDBLoadBalancerFactory()->setRequestInfo( [
-       'ChronologyProtection' => 'false',
-] );
+// Disable ChronologyProtector so that we don't wait for unrelated MediaWiki
+// writes when getting database connections for ResourceLoader. (T192611)
+MediaWikiServices::getInstance()->getDBLoadBalancerFactory()->disableChronologyProtection();
 
 // Set up ResourceLoader
 $resourceLoader = new ResourceLoader(
index ab57b7b..bb62067 100644 (file)
@@ -87,7 +87,7 @@
                } );
 
                // Synchronize radio button label for sitename with textbox
-               $label = $( 'label[for=config__NamespaceType_site-name]' );
+               $label = $( 'label[for="config__NamespaceType_site-name"]' );
                labelText = $label.text();
                $label.text( labelText.replace( '$1', '' ) );
                $( '#config_wgSitename' ).on( 'keyup change', syncText ).each( syncText );
 
                // Disable checkboxes if the extension has dependencies
                $( '.mw-ext-with-dependencies input' ).prop( 'disabled', true );
-               $( 'input[data-name]' ).change( function () {
+               $( '.config-ext-input[data-name]' ).on( 'change', function () {
                        $( '.mw-ext-with-dependencies input' ).each( function () {
-                               var $this = $( this ),
-                                       name = $this.data( 'name' );
+                               var name = this.getAttribute( 'data-name' );
                                if ( areReqsSatisfied( name ) ) {
-                                       // Un-disable it!
-                                       $this.prop( 'disabled', false );
+                                       // Re-enable it!
+                                       this.disabled = false;
                                } else {
-                                       // Disable the checkbox, and uncheck it if it is checked
-                                       $this.prop( 'disabled', true );
-                                       if ( $this.prop( 'checked' ) ) {
-                                               $this.prop( 'checked', false );
-                                       }
+                                       // Uncheck and disable the checkbox
+                                       this.checked = false;
+                                       this.disabled = true;
                                }
                        } );
                } );
index a282d69..b9a7ccc 100644 (file)
@@ -5,7 +5,8 @@
     "qunit": "grunt qunit",
     "doc": "jsduck",
     "postdoc": "grunt copy:jsduck",
-    "selenium": "./tests/selenium/selenium.sh"
+    "selenium": "./tests/selenium/selenium.sh",
+    "selenium-test": "grunt webdriver:test"
   },
   "devDependencies": {
     "bluebird": "3.5.1",
     "karma-chrome-launcher": "2.2.0",
     "karma-firefox-launcher": "1.0.1",
     "karma-mocha-reporter": "2.2.5",
-    "karma-qunit": "1.2.1",
+    "karma-qunit": "2.0.1",
     "mwbot": "1.0.10",
     "postcss-less": "1.1.5",
-    "qunitjs": "2.4.1",
+    "qunit": "2.5.0",
     "stylelint": "9.2.0",
     "stylelint-config-wikimedia": "0.4.3",
     "wdio-junit-reporter": "0.2.0",
index 0595bb0..2f230f2 100644 (file)
@@ -2536,6 +2536,7 @@ return [
                'dependencies' => [
                        'oojs-ui-core',
                        'jquery.lengthLimit',
+                       'mediawiki.language',
                        'mediawiki.String',
                ],
                'targets' => [ 'desktop', 'mobile' ]
index 693cd7f..6364c70 100644 (file)
@@ -6,10 +6,10 @@
        -ms-user-select: none;
        user-select: none;
 }
-.mw-collapsible-toggle:before {
+.mw-collapsible-toggle-default:before {
        content: '[';
 }
-.mw-collapsible-toggle:after {
+.mw-collapsible-toggle-default:after {
        content: ']';
 }
 /* Align the toggle based on the direction of the content language */
index 7826bab..1f40e0a 100644 (file)
                        buildDefaultToggleLink = function () {
                                return $( '<a class="mw-collapsible-text"></a>' )
                                        .text( collapseText )
-                                       .wrap( '<span class="mw-collapsible-toggle"></span>' )
+                                       .wrap( '<span class="mw-collapsible-toggle mw-collapsible-toggle-default"></span>' )
                                        .parent()
                                        .attr( {
                                                role: 'button',
index 8aa22a8..e9d5a91 100644 (file)
                }
                return $.makeArray( node.childNodes ).map( function ( elem ) {
                        if ( elem.nodeType === Node.ELEMENT_NODE ) {
-                               return getElementSortKey( elem );
+                               if ( $( elem ).hasClass( 'reference' ) ) {
+                                       return null;
+                               } else {
+                                       return getElementSortKey( elem );
+                               }
                        }
                        return $.text( elem );
                } ).join( '' );
index d6e6796..7dcdc81 100644 (file)
@@ -24,7 +24,7 @@
                if ( summaryCodePointLimit ) {
                        $wpReason.codePointLimit( summaryCodePointLimit, filterFn );
                } else if ( summaryByteLimit ) {
-                       $wpReason.bytePointLimit( summaryByteLimit, filterFn );
+                       $wpReason.byteLimit( summaryByteLimit, filterFn );
                }
        } );
 
index c353a48..005a8df 100644 (file)
@@ -24,7 +24,7 @@
                if ( summaryCodePointLimit ) {
                        reason.$input.codePointLimit( summaryCodePointLimit, filterFn );
                } else if ( summaryByteLimit ) {
-                       reason.$input.bytePointLimit( summaryByteLimit, filterFn );
+                       reason.$input.byteLimit( summaryByteLimit, filterFn );
                }
        } );
 }( mediaWiki, jQuery ) );
index 27d049e..f58f039 100644 (file)
        window.importScript = importScript;
        window.importStylesheet = importStylesheet;
 
-       /**
-        * Replace document.write/writeln with basic html parsing that appends
-        * to the <body> to avoid blanking pages. Added JavaScript will not run.
-        *
-        * @deprecated since 1.26
-        */
-       [ 'write', 'writeln' ].forEach( function ( method ) {
-               mw.log.deprecate( document, method, function () {
-                       $( 'body' ).append( $.parseHTML( Array.prototype.join.call( arguments, '' ) ) );
-               }, 'Use jQuery or mw.loader.load instead.', 'document.' + method );
-       } );
-
 }( mediaWiki, jQuery ) );
index 45c3cf9..4f51e9b 100644 (file)
@@ -31,7 +31,7 @@
                if ( summaryCodePointLimit ) {
                        $wpReason.codePointLimit();
                } else if ( summaryByteLimit ) {
-                       $wpReason.bytePointLimit();
+                       $wpReason.byteLimit();
                }
        } );
 
index c6d44fa..cad9db0 100644 (file)
@@ -23,7 +23,7 @@
        if ( summaryCodePointLimit ) {
                $wpReason.codePointLimit( summaryCodePointLimit, filterFn );
        } else if ( summaryByteLimit ) {
-               $wpReason.bytePointLimit( summaryByteLimit, filterFn );
+               $wpReason.byteLimit( summaryByteLimit, filterFn );
        }
 
 }( mediaWiki, jQuery ) );
index 981344d..487e63a 100644 (file)
@@ -19,7 +19,7 @@
        if ( summaryCodePointLimit ) {
                $wpReason.codePointLimit( summaryCodePointLimit );
        } else if ( summaryByteLimit ) {
-               $wpReason.bytePointLimit( summaryByteLimit );
+               $wpReason.byteLimit( summaryByteLimit );
        }
 
 }( mediaWiki, jQuery ) );
index 52ebe74..c92c5e5 100644 (file)
@@ -19,7 +19,9 @@
                limit = limit || +textInputWidget.$input.attr( 'maxlength' );
 
                function updateCount() {
-                       textInputWidget.setLabel( ( limit - byteLength( textInputWidget.getValue() ) ).toString() );
+                       var remaining = limit - byteLength( textInputWidget.getValue() );
+                       remaining = mw.language.convertNumber( remaining );
+                       textInputWidget.setLabel( remaining );
                }
                textInputWidget.on( 'change', updateCount );
                // Initialise value
@@ -41,7 +43,9 @@
                limit = limit || +textInputWidget.$input.attr( 'maxlength' );
 
                function updateCount() {
-                       textInputWidget.setLabel( ( limit - codePointLength( textInputWidget.getValue() ) ).toString() );
+                       var remaining = limit - codePointLength( textInputWidget.getValue() );
+                       remaining = mw.language.convertNumber( remaining );
+                       textInputWidget.setLabel( remaining );
                }
                textInputWidget.on( 'change', updateCount );
                // Initialise value
index 10e853b..abf718d 100644 (file)
@@ -150,6 +150,7 @@ $wgAutoloadClasses += [
 
        # tests/phpunit/includes/Storage
        'MediaWiki\Tests\Storage\RevisionSlotsTest' => "$testDir/phpunit/includes/Storage/RevisionSlotsTest.php",
+       'MediaWiki\Tests\Storage\RevisionRecordTests' => "$testDir/phpunit/includes/Storage/RevisionRecordTests.php",
 
        # tests/phpunit/languages
        'LanguageClassesTestCase' => "$testDir/phpunit/languages/LanguageClassesTestCase.php",
index 844a43f..91ddf24 100644 (file)
@@ -27,6 +27,7 @@
  */
 use Wikimedia\Rdbms\IDatabase;
 use MediaWiki\MediaWikiServices;
+use MediaWiki\Tidy\TidyDriverBase;
 use Wikimedia\ScopedCallback;
 use Wikimedia\TestingAccessWrapper;
 
@@ -802,7 +803,7 @@ class ParserTestRunner {
         *  - options: Array of test options
         *  - config: Overrides for global variables, one per line
         *
-        * @return ParserTestResult or false if skipped
+        * @return ParserTestResult|false false if skipped
         */
        public function runTest( $test ) {
                wfDebug( __METHOD__.": running {$test['desc']}" );
index 514150c..d5c14a2 100644 (file)
@@ -61,7 +61,6 @@ abstract class ResourceLoaderTestCase extends MediaWikiTestCase {
 
                        // For wfScript()
                        'ScriptPath' => '/w',
-                       'ScriptExtension' => '.php',
                        'Script' => '/w/index.php',
                        'LoadScript' => '/w/load.php',
                ];
index 81bbcd7..0a657d8 100644 (file)
@@ -124,6 +124,47 @@ class OutputPageTest extends MediaWikiTestCase {
                ] );
        }
 
+       public static function provideCdnCacheEpoch() {
+               $base = [
+                       'pageTime' => '2011-04-01T12:00:00+00:00',
+                       'maxAge' => 24 * 3600,
+               ];
+               return [
+                       'after 1s' => [ $base + [
+                               'reqTime' => '2011-04-01T12:00:01+00:00',
+                               'expect' => '2011-04-01T12:00:00+00:00',
+                       ] ],
+                       'after 23h' => [ $base + [
+                               'reqTime' => '2011-04-02T11:00:00+00:00',
+                               'expect' => '2011-04-01T12:00:00+00:00',
+                       ] ],
+                       'after 24h and a bit' => [ $base + [
+                               'reqTime' => '2011-04-02T12:34:56+00:00',
+                               'expect' => '2011-04-01T12:34:56+00:00',
+                       ] ],
+                       'after a year' => [ $base + [
+                               'reqTime' => '2012-05-06T00:12:07+00:00',
+                               'expect' => '2012-05-05T00:12:07+00:00',
+                       ] ],
+               ];
+       }
+
+       /**
+        * @dataProvider provideCdnCacheEpoch
+        */
+       public function testCdnCacheEpoch( $params ) {
+               $out = TestingAccessWrapper::newFromObject( $this->newInstance() );
+               $reqTime = strtotime( $params['reqTime'] );
+               $pageTime = strtotime( $params['pageTime'] );
+               $actual = max( $pageTime, $out->getCdnCacheEpoch( $reqTime, $params['maxAge'] ) );
+
+               $this->assertEquals(
+                       $params['expect'],
+                       gmdate( DateTime::ATOM, $actual ),
+                       'cdn epoch'
+               );
+       }
+
        /**
         * Tests screen requests, without either query parameter set
         * @covers OutputPage::transformCssMedia
index 675201e..dd2c4b6 100644 (file)
 namespace MediaWiki\Tests\Storage;
 
 use CommentStoreComment;
+use InvalidArgumentException;
 use MediaWiki\Storage\MutableRevisionRecord;
 use MediaWiki\Storage\RevisionAccessException;
 use MediaWiki\Storage\RevisionRecord;
 use MediaWiki\Storage\SlotRecord;
+use MediaWiki\User\UserIdentityValue;
 use MediaWikiTestCase;
+use TextContent;
 use Title;
 use WikitextContent;
 
 /**
  * @covers \MediaWiki\Storage\MutableRevisionRecord
+ * @covers \MediaWiki\Storage\RevisionRecord
  */
 class MutableRevisionRecordTest extends MediaWikiTestCase {
 
-       public function testSimpleSetGetId() {
+       use RevisionRecordTests;
+
+       /**
+        * @param array $rowOverrides
+        *
+        * @return MutableRevisionRecord
+        */
+       protected function newRevision( array $rowOverrides = [] ) {
+               $title = Title::newFromText( 'Dummy' );
+               $title->resetArticleID( 17 );
+
+               $user = new UserIdentityValue( 11, 'Tester', 0 );
+               $comment = CommentStoreComment::newUnsavedComment( 'Hello World' );
+
+               $record = new MutableRevisionRecord( $title );
+
+               if ( isset( $rowOverrides['rev_deleted'] ) ) {
+                       $record->setVisibility( $rowOverrides['rev_deleted'] );
+               }
+
+               if ( isset( $rowOverrides['rev_id'] ) ) {
+                       $record->setId( $rowOverrides['rev_id'] );
+               }
+
+               if ( isset( $rowOverrides['rev_page'] ) ) {
+                       $record->setPageId( $rowOverrides['rev_page'] );
+               }
+
+               $record->setContent( 'main', new TextContent( 'Lorem Ipsum' ) );
+               $record->setComment( $comment );
+               $record->setUser( $user );
+
+               return $record;
+       }
+
+       public function provideConstructor() {
+               $title = Title::newFromText( 'Dummy' );
+               $title->resetArticleID( 17 );
+
+               yield [
+                       $title,
+                       'acmewiki'
+               ];
+       }
+
+       /**
+        * @dataProvider provideConstructor
+        *
+        * @param Title $title
+        * @param bool $wikiId
+        */
+       public function testConstructorAndGetters(
+               Title $title,
+               $wikiId = false
+       ) {
+               $rec = new MutableRevisionRecord( $title, $wikiId );
+
+               $this->assertSame( $title, $rec->getPageAsLinkTarget(), 'getPageAsLinkTarget' );
+               $this->assertSame( $wikiId, $rec->getWikiId(), 'getWikiId' );
+       }
+
+       public function provideConstructorFailure() {
+               $title = Title::newFromText( 'Dummy' );
+               $title->resetArticleID( 17 );
+
+               yield 'not a wiki id' => [
+                       $title,
+                       null
+               ];
+       }
+
+       /**
+        * @dataProvider provideConstructorFailure
+        *
+        * @param Title $title
+        * @param bool $wikiId
+        */
+       public function testConstructorFailure(
+               Title $title,
+               $wikiId = false
+       ) {
+               $this->setExpectedException( InvalidArgumentException::class );
+               new MutableRevisionRecord( $title, $wikiId );
+       }
+
+       public function testSetGetId() {
                $record = new MutableRevisionRecord( Title::newFromText( 'Foo' ) );
                $this->assertNull( $record->getId() );
                $record->setId( 888 );
                $this->assertSame( 888, $record->getId() );
        }
 
-       public function testSimpleSetGetUser() {
+       public function testSetGetUser() {
                $record = new MutableRevisionRecord( Title::newFromText( 'Foo' ) );
                $user = $this->getTestSysop()->getUser();
                $this->assertNull( $record->getUser() );
@@ -31,34 +120,34 @@ class MutableRevisionRecordTest extends MediaWikiTestCase {
                $this->assertSame( $user, $record->getUser() );
        }
 
-       public function testSimpleSetGetPageId() {
+       public function testSetGetPageId() {
                $record = new MutableRevisionRecord( Title::newFromText( 'Foo' ) );
                $this->assertSame( 0, $record->getPageId() );
                $record->setPageId( 999 );
                $this->assertSame( 999, $record->getPageId() );
        }
 
-       public function testSimpleSetGetParentId() {
+       public function testSetGetParentId() {
                $record = new MutableRevisionRecord( Title::newFromText( 'Foo' ) );
                $this->assertNull( $record->getParentId() );
                $record->setParentId( 100 );
                $this->assertSame( 100, $record->getParentId() );
        }
 
-       public function testSimpleGetMainContentWhenEmpty() {
+       public function testGetMainContentWhenEmpty() {
                $record = new MutableRevisionRecord( Title::newFromText( 'Foo' ) );
                $this->setExpectedException( RevisionAccessException::class );
                $this->assertNull( $record->getContent( 'main' ) );
        }
 
-       public function testSimpleSetGetMainContent() {
+       public function testSetGetMainContent() {
                $record = new MutableRevisionRecord( Title::newFromText( 'Foo' ) );
                $content = new WikitextContent( 'Badger' );
                $record->setContent( 'main', $content );
                $this->assertSame( $content, $record->getContent( 'main' ) );
        }
 
-       public function testSimpleGetSlotWhenEmpty() {
+       public function testGetSlotWhenEmpty() {
                $record = new MutableRevisionRecord( Title::newFromText( 'Foo' ) );
                $this->assertFalse( $record->hasSlot( 'main' ) );
 
@@ -66,7 +155,7 @@ class MutableRevisionRecordTest extends MediaWikiTestCase {
                $record->getSlot( 'main' );
        }
 
-       public function testSimpleSetGetSlot() {
+       public function testSetGetSlot() {
                $record = new MutableRevisionRecord( Title::newFromText( 'Foo' ) );
                $slot = SlotRecord::newUnsaved(
                        'main',
@@ -77,42 +166,42 @@ class MutableRevisionRecordTest extends MediaWikiTestCase {
                $this->assertSame( $slot, $record->getSlot( 'main' ) );
        }
 
-       public function testSimpleSetGetMinor() {
+       public function testSetGetMinor() {
                $record = new MutableRevisionRecord( Title::newFromText( 'Foo' ) );
                $this->assertFalse( $record->isMinor() );
                $record->setMinorEdit( true );
                $this->assertSame( true, $record->isMinor() );
        }
 
-       public function testSimpleSetGetTimestamp() {
+       public function testSetGetTimestamp() {
                $record = new MutableRevisionRecord( Title::newFromText( 'Foo' ) );
                $this->assertNull( $record->getTimestamp() );
                $record->setTimestamp( '20180101010101' );
                $this->assertSame( '20180101010101', $record->getTimestamp() );
        }
 
-       public function testSimpleSetGetVisibility() {
+       public function testSetGetVisibility() {
                $record = new MutableRevisionRecord( Title::newFromText( 'Foo' ) );
                $this->assertSame( 0, $record->getVisibility() );
                $record->setVisibility( RevisionRecord::DELETED_USER );
                $this->assertSame( RevisionRecord::DELETED_USER, $record->getVisibility() );
        }
 
-       public function testSimpleSetGetSha1() {
+       public function testSetGetSha1() {
                $record = new MutableRevisionRecord( Title::newFromText( 'Foo' ) );
                $this->assertSame( 'phoiac9h4m842xq45sp7s6u21eteeq1', $record->getSha1() );
                $record->setSha1( 'someHash' );
                $this->assertSame( 'someHash', $record->getSha1() );
        }
 
-       public function testSimpleSetGetSize() {
+       public function testSetGetSize() {
                $record = new MutableRevisionRecord( Title::newFromText( 'Foo' ) );
                $this->assertSame( 0, $record->getSize() );
                $record->setSize( 775 );
                $this->assertSame( 775, $record->getSize() );
        }
 
-       public function testSimpleSetGetComment() {
+       public function testSetGetComment() {
                $record = new MutableRevisionRecord( Title::newFromText( 'Foo' ) );
                $comment = new CommentStoreComment( 1, 'foo' );
                $this->assertNull( $record->getComment() );
diff --git a/tests/phpunit/includes/Storage/RevisionArchiveRecordTest.php b/tests/phpunit/includes/Storage/RevisionArchiveRecordTest.php
new file mode 100644 (file)
index 0000000..f959d68
--- /dev/null
@@ -0,0 +1,272 @@
+<?php
+
+namespace MediaWiki\Tests\Storage;
+
+use CommentStoreComment;
+use InvalidArgumentException;
+use MediaWiki\Storage\RevisionRecord;
+use MediaWiki\Storage\RevisionSlots;
+use MediaWiki\Storage\RevisionArchiveRecord;
+use MediaWiki\Storage\SlotRecord;
+use MediaWiki\User\UserIdentity;
+use MediaWiki\User\UserIdentityValue;
+use MediaWikiTestCase;
+use TextContent;
+use Title;
+
+/**
+ * @covers \MediaWiki\Storage\RevisionArchiveRecord
+ * @covers \MediaWiki\Storage\RevisionRecord
+ */
+class RevisionArchiveRecordTest extends MediaWikiTestCase {
+
+       use RevisionRecordTests;
+
+       /**
+        * @param array $rowOverrides
+        *
+        * @return RevisionArchiveRecord
+        */
+       protected function newRevision( array $rowOverrides = [] ) {
+               $title = Title::newFromText( 'Dummy' );
+               $title->resetArticleID( 17 );
+
+               $user = new UserIdentityValue( 11, 'Tester', 0 );
+               $comment = CommentStoreComment::newUnsavedComment( 'Hello World' );
+
+               $main = SlotRecord::newUnsaved( 'main', new TextContent( 'Lorem Ipsum' ) );
+               $aux = SlotRecord::newUnsaved( 'aux', new TextContent( 'Frumious Bandersnatch' ) );
+               $slots = new RevisionSlots( [ $main, $aux ] );
+
+               $row = [
+                       'ar_id' => '5',
+                       'ar_rev_id' => '7',
+                       'ar_page_id' => strval( $title->getArticleID() ),
+                       'ar_timestamp' => '20200101000000',
+                       'ar_deleted' => 0,
+                       'ar_minor_edit' => 0,
+                       'ar_parent_id' => '5',
+                       'ar_len' => $slots->computeSize(),
+                       'ar_sha1' => $slots->computeSha1(),
+               ];
+
+               foreach ( $rowOverrides as $field => $value ) {
+                       $field = preg_replace( '/^rev_/', 'ar_', $field );
+                       $row[$field] = $value;
+               }
+
+               return new RevisionArchiveRecord( $title, $user, $comment, (object)$row, $slots );
+       }
+
+       public function provideConstructor() {
+               $title = Title::newFromText( 'Dummy' );
+               $title->resetArticleID( 17 );
+
+               $user = new UserIdentityValue( 11, 'Tester', 0 );
+               $comment = CommentStoreComment::newUnsavedComment( 'Hello World' );
+
+               $main = SlotRecord::newUnsaved( 'main', new TextContent( 'Lorem Ipsum' ) );
+               $aux = SlotRecord::newUnsaved( 'aux', new TextContent( 'Frumious Bandersnatch' ) );
+               $slots = new RevisionSlots( [ $main, $aux ] );
+
+               $protoRow = [
+                       'ar_id' => '5',
+                       'ar_rev_id' => '7',
+                       'ar_page_id' => strval( $title->getArticleID() ),
+                       'ar_timestamp' => '20200101000000',
+                       'ar_deleted' => 0,
+                       'ar_minor_edit' => 0,
+                       'ar_parent_id' => '5',
+                       'ar_len' => $slots->computeSize(),
+                       'ar_sha1' => $slots->computeSha1(),
+               ];
+
+               $row = $protoRow;
+               yield 'all info' => [
+                       $title,
+                       $user,
+                       $comment,
+                       (object)$row,
+                       $slots,
+                       'acmewiki'
+               ];
+
+               $row = $protoRow;
+               $row['ar_minor_edit'] = '1';
+               $row['ar_deleted'] = strval( RevisionRecord::DELETED_USER );
+
+               yield 'minor deleted' => [
+                       $title,
+                       $user,
+                       $comment,
+                       (object)$row,
+                       $slots
+               ];
+
+               $row = $protoRow;
+               unset( $row['ar_parent'] );
+
+               yield 'no parent' => [
+                       $title,
+                       $user,
+                       $comment,
+                       (object)$row,
+                       $slots
+               ];
+
+               $row = $protoRow;
+               $row['ar_len'] = null;
+               $row['ar_sha1'] = '';
+
+               yield 'ar_len is null, ar_sha1 is ""' => [
+                       $title,
+                       $user,
+                       $comment,
+                       (object)$row,
+                       $slots
+               ];
+
+               $row = $protoRow;
+               yield 'no length, no hash' => [
+                       Title::newFromText( 'DummyDoesNotExist' ),
+                       $user,
+                       $comment,
+                       (object)$row,
+                       $slots
+               ];
+       }
+
+       /**
+        * @dataProvider provideConstructor
+        *
+        * @param Title $title
+        * @param UserIdentity $user
+        * @param CommentStoreComment $comment
+        * @param object $row
+        * @param RevisionSlots $slots
+        * @param bool $wikiId
+        */
+       public function testConstructorAndGetters(
+               Title $title,
+               UserIdentity $user,
+               CommentStoreComment $comment,
+               $row,
+               RevisionSlots $slots,
+               $wikiId = false
+       ) {
+               $rec = new RevisionArchiveRecord( $title, $user, $comment, $row, $slots, $wikiId );
+
+               $this->assertSame( $title, $rec->getPageAsLinkTarget(), 'getPageAsLinkTarget' );
+               $this->assertSame( $user, $rec->getUser( RevisionRecord::RAW ), 'getUser' );
+               $this->assertSame( $comment, $rec->getComment(), 'getComment' );
+
+               $this->assertSame( $slots->getSlotRoles(), $rec->getSlotRoles(), 'getSlotRoles' );
+               $this->assertSame( $wikiId, $rec->getWikiId(), 'getWikiId' );
+
+               $this->assertSame( (int)$row->ar_id, $rec->getArchiveId(), 'getArchiveId' );
+               $this->assertSame( (int)$row->ar_rev_id, $rec->getId(), 'getId' );
+               $this->assertSame( (int)$row->ar_page_id, $rec->getPageId(), 'getId' );
+               $this->assertSame( $row->ar_timestamp, $rec->getTimestamp(), 'getTimestamp' );
+               $this->assertSame( (int)$row->ar_deleted, $rec->getVisibility(), 'getVisibility' );
+               $this->assertSame( (bool)$row->ar_minor_edit, $rec->isMinor(), 'getIsMinor' );
+
+               if ( isset( $row->ar_parent_id ) ) {
+                       $this->assertSame( (int)$row->ar_parent_id, $rec->getParentId(), 'getParentId' );
+               } else {
+                       $this->assertSame( 0, $rec->getParentId(), 'getParentId' );
+               }
+
+               if ( isset( $row->ar_len ) ) {
+                       $this->assertSame( (int)$row->ar_len, $rec->getSize(), 'getSize' );
+               } else {
+                       $this->assertSame( $slots->computeSize(), $rec->getSize(), 'getSize' );
+               }
+
+               if ( !empty( $row->ar_sha1 ) ) {
+                       $this->assertSame( $row->ar_sha1, $rec->getSha1(), 'getSha1' );
+               } else {
+                       $this->assertSame( $slots->computeSha1(), $rec->getSha1(), 'getSha1' );
+               }
+       }
+
+       public function provideConstructorFailure() {
+               $title = Title::newFromText( 'Dummy' );
+               $title->resetArticleID( 17 );
+
+               $user = new UserIdentityValue( 11, 'Tester', 0 );
+
+               $comment = CommentStoreComment::newUnsavedComment( 'Hello World' );
+
+               $main = SlotRecord::newUnsaved( 'main', new TextContent( 'Lorem Ipsum' ) );
+               $aux = SlotRecord::newUnsaved( 'aux', new TextContent( 'Frumious Bandersnatch' ) );
+               $slots = new RevisionSlots( [ $main, $aux ] );
+
+               $protoRow = [
+                       'ar_id' => '5',
+                       'ar_rev_id' => '7',
+                       'ar_page_id' => strval( $title->getArticleID() ),
+                       'ar_timestamp' => '20200101000000',
+                       'ar_deleted' => 0,
+                       'ar_minor_edit' => 0,
+                       'ar_parent_id' => '5',
+                       'ar_len' => $slots->computeSize(),
+                       'ar_sha1' => $slots->computeSha1(),
+               ];
+
+               yield 'not a row' => [
+                       $title,
+                       $user,
+                       $comment,
+                       'not a row',
+                       $slots,
+                       'acmewiki'
+               ];
+
+               $row = $protoRow;
+               $row['ar_timestamp'] = 'kittens';
+
+               yield 'bad timestamp' => [
+                       $title,
+                       $user,
+                       $comment,
+                       (object)$row,
+                       $slots
+               ];
+
+               $row = $protoRow;
+
+               yield 'bad wiki' => [
+                       $title,
+                       $user,
+                       $comment,
+                       (object)$row,
+                       $slots,
+                       12345
+               ];
+
+               // NOTE: $title->getArticleID does *not* have to match ar_page_id in all cases!
+       }
+
+       /**
+        * @dataProvider provideConstructorFailure
+        *
+        * @param Title $title
+        * @param UserIdentity $user
+        * @param CommentStoreComment $comment
+        * @param object $row
+        * @param RevisionSlots $slots
+        * @param bool $wikiId
+        */
+       public function testConstructorFailure(
+               Title $title,
+               UserIdentity $user,
+               CommentStoreComment $comment,
+               $row,
+               RevisionSlots $slots,
+               $wikiId = false
+       ) {
+               $this->setExpectedException( InvalidArgumentException::class );
+               new RevisionArchiveRecord( $title, $user, $comment, $row, $slots, $wikiId );
+       }
+
+}
diff --git a/tests/phpunit/includes/Storage/RevisionRecordTests.php b/tests/phpunit/includes/Storage/RevisionRecordTests.php
new file mode 100644 (file)
index 0000000..607f782
--- /dev/null
@@ -0,0 +1,512 @@
+<?php
+
+namespace MediaWiki\Tests\Storage;
+
+use CommentStoreComment;
+use LogicException;
+use MediaWiki\Storage\RevisionRecord;
+use MediaWiki\Storage\RevisionSlots;
+use MediaWiki\Storage\RevisionStoreRecord;
+use MediaWiki\Storage\SlotRecord;
+use MediaWiki\Storage\SuppressedDataException;
+use MediaWiki\User\UserIdentityValue;
+use TextContent;
+use Title;
+
+// PHPCS should not complain about @covers and @dataProvider being used in traits, see T192384
+// phpcs:disable MediaWiki.Commenting.PhpunitAnnotations.NotTestClass
+
+/**
+ * @covers \MediaWiki\Storage\RevisionRecord
+ *
+ * @note Expects to be used in classes that extend MediaWikiTestCase.
+ */
+trait RevisionRecordTests {
+
+       /**
+        * @param array $rowOverrides
+        *
+        * @return RevisionRecord
+        */
+       protected abstract function newRevision( array $rowOverrides = [] );
+
+       private function provideAudienceCheckData( $field ) {
+               yield 'field accessible for oversighter (ALL)' => [
+                       RevisionRecord::SUPPRESSED_ALL,
+                       [ 'oversight' ],
+                       true,
+                       false
+               ];
+
+               yield 'field accessible for oversighter' => [
+                       RevisionRecord::DELETED_RESTRICTED | $field,
+                       [ 'oversight' ],
+                       true,
+                       false
+               ];
+
+               yield 'field not accessible for sysops (ALL)' => [
+                       RevisionRecord::SUPPRESSED_ALL,
+                       [ 'sysop' ],
+                       false,
+                       false
+               ];
+
+               yield 'field not accessible for sysops' => [
+                       RevisionRecord::DELETED_RESTRICTED | $field,
+                       [ 'sysop' ],
+                       false,
+                       false
+               ];
+
+               yield 'field accessible for sysops' => [
+                       $field,
+                       [ 'sysop' ],
+                       true,
+                       false
+               ];
+
+               yield 'field suppressed for logged in users' => [
+                       $field,
+                       [ 'user' ],
+                       false,
+                       false
+               ];
+
+               yield 'unrelated field suppressed' => [
+                       $field === RevisionRecord::DELETED_COMMENT
+                               ? RevisionRecord::DELETED_USER
+                               : RevisionRecord::DELETED_COMMENT,
+                       [ 'user' ],
+                       true,
+                       true
+               ];
+
+               yield 'nothing suppressed' => [
+                       0,
+                       [ 'user' ],
+                       true,
+                       true
+               ];
+       }
+
+       public function testSerialization_fails() {
+               $this->setExpectedException( LogicException::class );
+               $rev = $this->newRevision();
+               serialize( $rev );
+       }
+
+       public function provideGetComment_audience() {
+               return $this->provideAudienceCheckData( RevisionRecord::DELETED_COMMENT );
+       }
+
+       private function forceStandardPermissions() {
+               $this->setMwGlobals(
+                       'wgGroupPermissions',
+                       [
+                               'user' => [
+                                       'viewsuppressed' => false,
+                                       'suppressrevision' => false,
+                                       'deletedtext' => false,
+                                       'deletedhistory' => false,
+                               ],
+                               'sysop' => [
+                                       'viewsuppressed' => false,
+                                       'suppressrevision' => false,
+                                       'deletedtext' => true,
+                                       'deletedhistory' => true,
+                               ],
+                               'oversight' => [
+                                       'deletedtext' => true,
+                                       'deletedhistory' => true,
+                                       'viewsuppressed' => true,
+                                       'suppressrevision' => true,
+                               ],
+                       ]
+               );
+       }
+
+       /**
+        * @dataProvider provideGetComment_audience
+        */
+       public function testGetComment_audience( $visibility, $groups, $userCan, $publicCan ) {
+               $this->forceStandardPermissions();
+
+               $user = $this->getTestUser( $groups )->getUser();
+               $rev = $this->newRevision( [ 'rev_deleted' => $visibility ] );
+
+               $this->assertNotNull( $rev->getComment( RevisionRecord::RAW ), 'raw can' );
+
+               $this->assertSame(
+                       $publicCan,
+                       $rev->getComment( RevisionRecord::FOR_PUBLIC ) !== null,
+                       'public can'
+               );
+               $this->assertSame(
+                       $userCan,
+                       $rev->getComment( RevisionRecord::FOR_THIS_USER, $user ) !== null,
+                       'user can'
+               );
+       }
+
+       public function provideGetUser_audience() {
+               return $this->provideAudienceCheckData( RevisionRecord::DELETED_USER );
+       }
+
+       /**
+        * @dataProvider provideGetUser_audience
+        */
+       public function testGetUser_audience( $visibility, $groups, $userCan, $publicCan ) {
+               $this->forceStandardPermissions();
+
+               $user = $this->getTestUser( $groups )->getUser();
+               $rev = $this->newRevision( [ 'rev_deleted' => $visibility ] );
+
+               $this->assertNotNull( $rev->getUser( RevisionRecord::RAW ), 'raw can' );
+
+               $this->assertSame(
+                       $publicCan,
+                       $rev->getUser( RevisionRecord::FOR_PUBLIC ) !== null,
+                       'public can'
+               );
+               $this->assertSame(
+                       $userCan,
+                       $rev->getUser( RevisionRecord::FOR_THIS_USER, $user ) !== null,
+                       'user can'
+               );
+       }
+
+       public function provideGetSlot_audience() {
+               return $this->provideAudienceCheckData( RevisionRecord::DELETED_TEXT );
+       }
+
+       /**
+        * @dataProvider provideGetSlot_audience
+        */
+       public function testGetSlot_audience( $visibility, $groups, $userCan, $publicCan ) {
+               $this->forceStandardPermissions();
+
+               $user = $this->getTestUser( $groups )->getUser();
+               $rev = $this->newRevision( [ 'rev_deleted' => $visibility ] );
+
+               // NOTE: slot meta-data is never suppressed, just the content is!
+               $this->assertTrue( $rev->hasSlot( 'main' ), 'hasSlot is never suppressed' );
+               $this->assertNotNull( $rev->getSlot( 'main', RevisionRecord::RAW ), 'raw meta' );
+               $this->assertNotNull( $rev->getSlot( 'main', RevisionRecord::FOR_PUBLIC ), 'public meta' );
+
+               $this->assertNotNull(
+                       $rev->getSlot( 'main', RevisionRecord::FOR_THIS_USER, $user ),
+                       'user can'
+               );
+
+               try {
+                       $rev->getSlot( 'main', RevisionRecord::FOR_PUBLIC )->getContent();
+                       $exception = null;
+               } catch ( SuppressedDataException $ex ) {
+                       $exception = $ex;
+               }
+
+               $this->assertSame(
+                       $publicCan,
+                       $exception === null,
+                       'public can'
+               );
+
+               try {
+                       $rev->getSlot( 'main', RevisionRecord::FOR_THIS_USER, $user )->getContent();
+                       $exception = null;
+               } catch ( SuppressedDataException $ex ) {
+                       $exception = $ex;
+               }
+
+               $this->assertSame(
+                       $userCan,
+                       $exception === null,
+                       'user can'
+               );
+       }
+
+       /**
+        * @dataProvider provideGetSlot_audience
+        */
+       public function testGetContent_audience( $visibility, $groups, $userCan, $publicCan ) {
+               $this->forceStandardPermissions();
+
+               $user = $this->getTestUser( $groups )->getUser();
+               $rev = $this->newRevision( [ 'rev_deleted' => $visibility ] );
+
+               $this->assertNotNull( $rev->getContent( 'main', RevisionRecord::RAW ), 'raw can' );
+
+               $this->assertSame(
+                       $publicCan,
+                       $rev->getContent( 'main', RevisionRecord::FOR_PUBLIC ) !== null,
+                       'public can'
+               );
+               $this->assertSame(
+                       $userCan,
+                       $rev->getContent( 'main', RevisionRecord::FOR_THIS_USER, $user ) !== null,
+                       'user can'
+               );
+       }
+
+       public function testGetSlot() {
+               $rev = $this->newRevision();
+
+               $slot = $rev->getSlot( 'main' );
+               $this->assertNotNull( $slot, 'getSlot()' );
+               $this->assertSame( 'main', $slot->getRole(), 'getRole()' );
+       }
+
+       public function testHasSlot() {
+               $rev = $this->newRevision();
+
+               $this->assertTrue( $rev->hasSlot( 'main' ) );
+               $this->assertFalse( $rev->hasSlot( 'xyz' ) );
+       }
+
+       public function testGetContent() {
+               $rev = $this->newRevision();
+
+               $content = $rev->getSlot( 'main' );
+               $this->assertNotNull( $content, 'getContent()' );
+               $this->assertSame( CONTENT_MODEL_TEXT, $content->getModel(), 'getModel()' );
+       }
+
+       public function provideUserCanBitfield() {
+               yield [ 0, 0, [], null, true ];
+               // Bitfields match, user has no permissions
+               yield [
+                       RevisionRecord::DELETED_TEXT,
+                       RevisionRecord::DELETED_TEXT,
+                       [],
+                       null,
+                       false
+               ];
+               yield [
+                       RevisionRecord::DELETED_COMMENT,
+                       RevisionRecord::DELETED_COMMENT,
+                       [],
+                       null,
+                       false,
+               ];
+               yield [
+                       RevisionRecord::DELETED_USER,
+                       RevisionRecord::DELETED_USER,
+                       [],
+                       null,
+                       false
+               ];
+               yield [
+                       RevisionRecord::DELETED_RESTRICTED,
+                       RevisionRecord::DELETED_RESTRICTED,
+                       [],
+                       null,
+                       false,
+               ];
+               // Bitfields match, user (admin) does have permissions
+               yield [
+                       RevisionRecord::DELETED_TEXT,
+                       RevisionRecord::DELETED_TEXT,
+                       [ 'sysop' ],
+                       null,
+                       true,
+               ];
+               yield [
+                       RevisionRecord::DELETED_COMMENT,
+                       RevisionRecord::DELETED_COMMENT,
+                       [ 'sysop' ],
+                       null,
+                       true,
+               ];
+               yield [
+                       RevisionRecord::DELETED_USER,
+                       RevisionRecord::DELETED_USER,
+                       [ 'sysop' ],
+                       null,
+                       true,
+               ];
+               // Bitfields match, user (admin) does not have permissions
+               yield [
+                       RevisionRecord::DELETED_RESTRICTED,
+                       RevisionRecord::DELETED_RESTRICTED,
+                       [ 'sysop' ],
+                       null,
+                       false,
+               ];
+               // Bitfields match, user (oversight) does have permissions
+               yield [
+                       RevisionRecord::DELETED_RESTRICTED,
+                       RevisionRecord::DELETED_RESTRICTED,
+                       [ 'oversight' ],
+                       null,
+                       true,
+               ];
+               // Check permissions using the title
+               yield [
+                       RevisionRecord::DELETED_TEXT,
+                       RevisionRecord::DELETED_TEXT,
+                       [ 'sysop' ],
+                       Title::newFromText( __METHOD__ ),
+                       true,
+               ];
+               yield [
+                       RevisionRecord::DELETED_TEXT,
+                       RevisionRecord::DELETED_TEXT,
+                       [],
+                       Title::newFromText( __METHOD__ ),
+                       false,
+               ];
+       }
+
+       /**
+        * @dataProvider provideUserCanBitfield
+        * @covers \MediaWiki\Storage\RevisionRecord::userCanBitfield
+        */
+       public function testUserCanBitfield( $bitField, $field, $userGroups, $title, $expected ) {
+               $this->forceStandardPermissions();
+
+               $user = $this->getTestUser( $userGroups )->getUser();
+
+               $this->assertSame(
+                       $expected,
+                       RevisionRecord::userCanBitfield( $bitField, $field, $user, $title )
+               );
+       }
+
+       public function provideHasSameContent() {
+               /**
+                * @param SlotRecord[] $slots
+                * @param int $revId
+                * @return RevisionStoreRecord
+                */
+               $recordCreator = function ( array $slots, $revId ) {
+                       $title = Title::newFromText( 'provideHasSameContent' );
+                       $title->resetArticleID( 19 );
+                       $slots = new RevisionSlots( $slots );
+
+                       return new RevisionStoreRecord(
+                               $title,
+                               new UserIdentityValue( 11, __METHOD__, 0 ),
+                               CommentStoreComment::newUnsavedComment( __METHOD__ ),
+                               (object)[
+                                       'rev_id' => strval( $revId ),
+                                       'rev_page' => strval( $title->getArticleID() ),
+                                       'rev_timestamp' => '20200101000000',
+                                       'rev_deleted' => 0,
+                                       'rev_minor_edit' => 0,
+                                       'rev_parent_id' => '5',
+                                       'rev_len' => $slots->computeSize(),
+                                       'rev_sha1' => $slots->computeSha1(),
+                                       'page_latest' => '18',
+                               ],
+                               $slots
+                       );
+               };
+
+               // Create some slots with content
+               $mainA = SlotRecord::newUnsaved( 'main', new TextContent( 'A' ) );
+               $mainB = SlotRecord::newUnsaved( 'main', new TextContent( 'B' ) );
+               $auxA = SlotRecord::newUnsaved( 'aux', new TextContent( 'A' ) );
+               $auxB = SlotRecord::newUnsaved( 'aux', new TextContent( 'A' ) );
+
+               $initialRecord = $recordCreator( [ $mainA ], 12 );
+
+               return [
+                       'same record object' => [
+                               true,
+                               $initialRecord,
+                               $initialRecord,
+                       ],
+                       'same record content, different object' => [
+                               true,
+                               $recordCreator( [ $mainA ], 12 ),
+                               $recordCreator( [ $mainA ], 13 ),
+                       ],
+                       'same record content, aux slot, different object' => [
+                               true,
+                               $recordCreator( [ $auxA ], 12 ),
+                               $recordCreator( [ $auxB ], 13 ),
+                       ],
+                       'different content' => [
+                               false,
+                               $recordCreator( [ $mainA ], 12 ),
+                               $recordCreator( [ $mainB ], 13 ),
+                       ],
+                       'different content and number of slots' => [
+                               false,
+                               $recordCreator( [ $mainA ], 12 ),
+                               $recordCreator( [ $mainA, $mainB ], 13 ),
+                       ],
+               ];
+       }
+
+       /**
+        * @dataProvider provideHasSameContent
+        * @covers \MediaWiki\Storage\RevisionRecord::hasSameContent
+        * @group Database
+        */
+       public function testHasSameContent(
+               $expected,
+               RevisionRecord $record1,
+               RevisionRecord $record2
+       ) {
+               $this->assertSame(
+                       $expected,
+                       $record1->hasSameContent( $record2 )
+               );
+       }
+
+       public function provideIsDeleted() {
+               yield 'no deletion' => [
+                       0,
+                       [
+                               RevisionRecord::DELETED_TEXT => false,
+                               RevisionRecord::DELETED_COMMENT => false,
+                               RevisionRecord::DELETED_USER => false,
+                               RevisionRecord::DELETED_RESTRICTED => false,
+                       ]
+               ];
+               yield 'text deleted' => [
+                       RevisionRecord::DELETED_TEXT,
+                       [
+                               RevisionRecord::DELETED_TEXT => true,
+                               RevisionRecord::DELETED_COMMENT => false,
+                               RevisionRecord::DELETED_USER => false,
+                               RevisionRecord::DELETED_RESTRICTED => false,
+                       ]
+               ];
+               yield 'text and comment deleted' => [
+                       RevisionRecord::DELETED_TEXT + RevisionRecord::DELETED_COMMENT,
+                       [
+                               RevisionRecord::DELETED_TEXT => true,
+                               RevisionRecord::DELETED_COMMENT => true,
+                               RevisionRecord::DELETED_USER => false,
+                               RevisionRecord::DELETED_RESTRICTED => false,
+                       ]
+               ];
+               yield 'all 4 deleted' => [
+                       RevisionRecord::DELETED_TEXT +
+                       RevisionRecord::DELETED_COMMENT +
+                       RevisionRecord::DELETED_RESTRICTED +
+                       RevisionRecord::DELETED_USER,
+                       [
+                               RevisionRecord::DELETED_TEXT => true,
+                               RevisionRecord::DELETED_COMMENT => true,
+                               RevisionRecord::DELETED_USER => true,
+                               RevisionRecord::DELETED_RESTRICTED => true,
+                       ]
+               ];
+       }
+
+       /**
+        * @dataProvider provideIsDeleted
+        * @covers \MediaWiki\Storage\RevisionRecord::isDeleted
+        */
+       public function testIsDeleted( $revDeleted, $assertionMap ) {
+               $rev = $this->newRevision( [ 'rev_deleted' => $revDeleted ] );
+               foreach ( $assertionMap as $deletionLevel => $expected ) {
+                       $this->assertSame( $expected, $rev->isDeleted( $deletionLevel ) );
+               }
+       }
+
+}
index 09f5675..0295e90 100644 (file)
@@ -4,12 +4,10 @@ namespace MediaWiki\Tests\Storage;
 
 use CommentStoreComment;
 use InvalidArgumentException;
-use LogicException;
 use MediaWiki\Storage\RevisionRecord;
 use MediaWiki\Storage\RevisionSlots;
 use MediaWiki\Storage\RevisionStoreRecord;
 use MediaWiki\Storage\SlotRecord;
-use MediaWiki\Storage\SuppressedDataException;
 use MediaWiki\User\UserIdentity;
 use MediaWiki\User\UserIdentityValue;
 use MediaWikiTestCase;
@@ -18,15 +16,18 @@ use Title;
 
 /**
  * @covers \MediaWiki\Storage\RevisionStoreRecord
+ * @covers \MediaWiki\Storage\RevisionRecord
  */
 class RevisionStoreRecordTest extends MediaWikiTestCase {
 
+       use RevisionRecordTests;
+
        /**
         * @param array $rowOverrides
         *
         * @return RevisionStoreRecord
         */
-       public function newRevision( array $rowOverrides = [] ) {
+       protected function newRevision( array $rowOverrides = [] ) {
                $title = Title::newFromText( 'Dummy' );
                $title->resetArticleID( 17 );
 
@@ -122,10 +123,10 @@ class RevisionStoreRecordTest extends MediaWikiTestCase {
                ];
 
                $row = $protoRow;
-               unset( $row['rev_len'] );
-               unset( $row['rev_sha1'] );
+               $row['rev_len'] = null;
+               $row['rev_sha1'] = '';
 
-               yield 'no length, no hash' => [
+               yield 'rev_len is null, rev_sha1 is ""' => [
                        $title,
                        $user,
                        $comment,
@@ -188,7 +189,7 @@ class RevisionStoreRecordTest extends MediaWikiTestCase {
                        $this->assertSame( $slots->computeSize(), $rec->getSize(), 'getSize' );
                }
 
-               if ( isset( $row->rev_sha1 ) ) {
+               if ( !empty( $row->rev_sha1 ) ) {
                        $this->assertSame( $row->rev_sha1, $rec->getSha1(), 'getSha1' );
                } else {
                        $this->assertSame( $slots->computeSha1(), $rec->getSha1(), 'getSha1' );
@@ -298,200 +299,30 @@ class RevisionStoreRecordTest extends MediaWikiTestCase {
                new RevisionStoreRecord( $title, $user, $comment, $row, $slots, $wikiId );
        }
 
-       private function provideAudienceCheckData( $field ) {
-               yield 'field accessible for oversighter (ALL)' => [
-                       RevisionRecord::SUPPRESSED_ALL,
-                       [ 'oversight' ],
-                       true,
-                       false
-               ];
-
-               yield 'field accessible for oversighter' => [
-                       RevisionRecord::DELETED_RESTRICTED | $field,
-                       [ 'oversight' ],
-                       true,
-                       false
-               ];
-
-               yield 'field not accessible for sysops (ALL)' => [
-                       RevisionRecord::SUPPRESSED_ALL,
-                       [ 'sysop' ],
-                       false,
-                       false
-               ];
-
-               yield 'field not accessible for sysops' => [
-                       RevisionRecord::DELETED_RESTRICTED | $field,
-                       [ 'sysop' ],
-                       false,
-                       false
-               ];
-
-               yield 'field accessible for sysops' => [
-                       $field,
-                       [ 'sysop' ],
+       public function provideIsCurrent() {
+               yield [
+                       [
+                               'rev_id' => 11,
+                               'page_latest' => 11,
+                       ],
                        true,
-                       false
                ];
-
-               yield 'field suppressed for logged in users' => [
-                       $field,
-                       [ 'user' ],
+               yield [
+                       [
+                               'rev_id' => 11,
+                               'page_latest' => 10,
+                       ],
                        false,
-                       false
-               ];
-
-               yield 'unrelated field suppressed' => [
-                       $field === RevisionRecord::DELETED_COMMENT
-                               ? RevisionRecord::DELETED_USER
-                               : RevisionRecord::DELETED_COMMENT,
-                       [ 'user' ],
-                       true,
-                       true
-               ];
-
-               yield 'nothing suppressed' => [
-                       0,
-                       [ 'user' ],
-                       true,
-                       true
                ];
        }
 
-       public function testSerialization_fails() {
-               $this->setExpectedException( LogicException::class );
-               $rev = $this->newRevision();
-               serialize( $rev );
-       }
-
-       public function provideGetComment_audience() {
-               return $this->provideAudienceCheckData( RevisionRecord::DELETED_COMMENT );
-       }
-
-       private function forceStandardPermissions() {
-               $this->setMwGlobals(
-                       'wgGroupPermissions',
-                       [
-                               'user' => [
-                                       'viewsuppressed' => false,
-                                       'suppressrevision' => false,
-                                       'deletedtext' => false,
-                                       'deletedhistory' => false,
-                               ],
-                               'sysop' => [
-                                       'viewsuppressed' => false,
-                                       'suppressrevision' => false,
-                                       'deletedtext' => true,
-                                       'deletedhistory' => true,
-                               ],
-                               'oversight' => [
-                                       'deletedtext' => true,
-                                       'deletedhistory' => true,
-                                       'viewsuppressed' => true,
-                                       'suppressrevision' => true,
-                               ],
-                       ]
-               );
-       }
-
        /**
-        * @dataProvider provideGetComment_audience
+        * @dataProvider provideIsCurrent
         */
-       public function testGetComment_audience( $visibility, $groups, $userCan, $publicCan ) {
-               $this->forceStandardPermissions();
-
-               $user = $this->getTestUser( $groups )->getUser();
-               $rev = $this->newRevision( [ 'rev_deleted' => $visibility ] );
-
-               $this->assertNotNull( $rev->getComment( RevisionRecord::RAW ), 'raw can' );
+       public function testIsCurrent( $row, $current ) {
+               $rev = $this->newRevision( $row );
 
-               $this->assertSame(
-                       $publicCan,
-                       $rev->getComment( RevisionRecord::FOR_PUBLIC ) !== null,
-                       'public can'
-               );
-               $this->assertSame(
-                       $userCan,
-                       $rev->getComment( RevisionRecord::FOR_THIS_USER, $user ) !== null,
-                       'user can'
-               );
-       }
-
-       public function provideGetUser_audience() {
-               return $this->provideAudienceCheckData( RevisionRecord::DELETED_USER );
-       }
-
-       /**
-        * @dataProvider provideGetUser_audience
-        */
-       public function testGetUser_audience( $visibility, $groups, $userCan, $publicCan ) {
-               $this->forceStandardPermissions();
-
-               $user = $this->getTestUser( $groups )->getUser();
-               $rev = $this->newRevision( [ 'rev_deleted' => $visibility ] );
-
-               $this->assertNotNull( $rev->getUser( RevisionRecord::RAW ), 'raw can' );
-
-               $this->assertSame(
-                       $publicCan,
-                       $rev->getUser( RevisionRecord::FOR_PUBLIC ) !== null,
-                       'public can'
-               );
-               $this->assertSame(
-                       $userCan,
-                       $rev->getUser( RevisionRecord::FOR_THIS_USER, $user ) !== null,
-                       'user can'
-               );
-       }
-
-       public function provideGetSlot_audience() {
-               return $this->provideAudienceCheckData( RevisionRecord::DELETED_TEXT );
-       }
-
-       /**
-        * @dataProvider provideGetSlot_audience
-        */
-       public function testGetSlot_audience( $visibility, $groups, $userCan, $publicCan ) {
-               $this->forceStandardPermissions();
-
-               $user = $this->getTestUser( $groups )->getUser();
-               $rev = $this->newRevision( [ 'rev_deleted' => $visibility ] );
-
-               // NOTE: slot meta-data is never suppressed, just the content is!
-               $this->assertTrue( $rev->hasSlot( 'main' ), 'hasSlot is never suppressed' );
-               $this->assertNotNull( $rev->getSlot( 'main', RevisionRecord::RAW ), 'raw meta' );
-               $this->assertNotNull( $rev->getSlot( 'main', RevisionRecord::FOR_PUBLIC ), 'public meta' );
-
-               $this->assertNotNull(
-                       $rev->getSlot( 'main', RevisionRecord::FOR_THIS_USER, $user ),
-                       'user can'
-               );
-
-               try {
-                       $rev->getSlot( 'main', RevisionRecord::FOR_PUBLIC )->getContent();
-                       $exception = null;
-               } catch ( SuppressedDataException $ex ) {
-                       $exception = $ex;
-               }
-
-               $this->assertSame(
-                       $publicCan,
-                       $exception === null,
-                       'public can'
-               );
-
-               try {
-                       $rev->getSlot( 'main', RevisionRecord::FOR_THIS_USER, $user )->getContent();
-                       $exception = null;
-               } catch ( SuppressedDataException $ex ) {
-                       $exception = $ex;
-               }
-
-               $this->assertSame(
-                       $userCan,
-                       $exception === null,
-                       'user can'
-               );
+               $this->assertSame( $current, $rev->isCurrent(), 'isCurrent()' );
        }
 
        public function provideGetSlot_audience_latest() {
@@ -513,9 +344,6 @@ class RevisionStoreRecordTest extends MediaWikiTestCase {
                        ]
                );
 
-               // sanity check
-               $this->assertTrue( $rev->isCurrent(), 'isCurrent()' );
-
                // NOTE: slot meta-data is never suppressed, just the content is!
                $this->assertNotNull( $rev->getSlot( 'main', RevisionRecord::RAW ), 'raw can' );
                $this->assertNotNull( $rev->getSlot( 'main', RevisionRecord::FOR_PUBLIC ), 'public can' );
@@ -525,294 +353,11 @@ class RevisionStoreRecordTest extends MediaWikiTestCase {
                        'user can'
                );
 
+               $rev->getSlot( 'main', RevisionRecord::RAW )->getContent();
                // NOTE: the content of the current revision is never suppressed!
                // Check that getContent() doesn't throw SuppressedDataException
-               $rev->getSlot( 'main', RevisionRecord::RAW )->getContent();
                $rev->getSlot( 'main', RevisionRecord::FOR_PUBLIC )->getContent();
                $rev->getSlot( 'main', RevisionRecord::FOR_THIS_USER, $user )->getContent();
        }
 
-       /**
-        * @dataProvider provideGetSlot_audience
-        */
-       public function testGetContent_audience( $visibility, $groups, $userCan, $publicCan ) {
-               $this->forceStandardPermissions();
-
-               $user = $this->getTestUser( $groups )->getUser();
-               $rev = $this->newRevision( [ 'rev_deleted' => $visibility ] );
-
-               $this->assertNotNull( $rev->getContent( 'main', RevisionRecord::RAW ), 'raw can' );
-
-               $this->assertSame(
-                       $publicCan,
-                       $rev->getContent( 'main', RevisionRecord::FOR_PUBLIC ) !== null,
-                       'public can'
-               );
-               $this->assertSame(
-                       $userCan,
-                       $rev->getContent( 'main', RevisionRecord::FOR_THIS_USER, $user ) !== null,
-                       'user can'
-               );
-       }
-
-       public function testGetSlot() {
-               $rev = $this->newRevision();
-
-               $slot = $rev->getSlot( 'main' );
-               $this->assertNotNull( $slot, 'getSlot()' );
-               $this->assertSame( 'main', $slot->getRole(), 'getRole()' );
-       }
-
-       public function testHasSlot() {
-               $rev = $this->newRevision();
-
-               $this->assertTrue( $rev->hasSlot( 'main' ) );
-               $this->assertFalse( $rev->hasSlot( 'xyz' ) );
-       }
-
-       public function testGetContent() {
-               $rev = $this->newRevision();
-
-               $content = $rev->getSlot( 'main' );
-               $this->assertNotNull( $content, 'getContent()' );
-               $this->assertSame( CONTENT_MODEL_TEXT, $content->getModel(), 'getModel()' );
-       }
-
-       public function provideUserCanBitfield() {
-               yield [ 0, 0, [], null, true ];
-               // Bitfields match, user has no permissions
-               yield [
-                       RevisionRecord::DELETED_TEXT,
-                       RevisionRecord::DELETED_TEXT,
-                       [],
-                       null,
-                       false
-               ];
-               yield [
-                       RevisionRecord::DELETED_COMMENT,
-                       RevisionRecord::DELETED_COMMENT,
-                       [],
-                       null,
-                       false,
-               ];
-               yield [
-                       RevisionRecord::DELETED_USER,
-                       RevisionRecord::DELETED_USER,
-                       [],
-                       null,
-                       false
-               ];
-               yield [
-                       RevisionRecord::DELETED_RESTRICTED,
-                       RevisionRecord::DELETED_RESTRICTED,
-                       [],
-                       null,
-                       false,
-               ];
-               // Bitfields match, user (admin) does have permissions
-               yield [
-                       RevisionRecord::DELETED_TEXT,
-                       RevisionRecord::DELETED_TEXT,
-                       [ 'sysop' ],
-                       null,
-                       true,
-               ];
-               yield [
-                       RevisionRecord::DELETED_COMMENT,
-                       RevisionRecord::DELETED_COMMENT,
-                       [ 'sysop' ],
-                       null,
-                       true,
-               ];
-               yield [
-                       RevisionRecord::DELETED_USER,
-                       RevisionRecord::DELETED_USER,
-                       [ 'sysop' ],
-                       null,
-                       true,
-               ];
-               // Bitfields match, user (admin) does not have permissions
-               yield [
-                       RevisionRecord::DELETED_RESTRICTED,
-                       RevisionRecord::DELETED_RESTRICTED,
-                       [ 'sysop' ],
-                       null,
-                       false,
-               ];
-               // Bitfields match, user (oversight) does have permissions
-               yield [
-                       RevisionRecord::DELETED_RESTRICTED,
-                       RevisionRecord::DELETED_RESTRICTED,
-                       [ 'oversight' ],
-                       null,
-                       true,
-               ];
-               // Check permissions using the title
-               yield [
-                       RevisionRecord::DELETED_TEXT,
-                       RevisionRecord::DELETED_TEXT,
-                       [ 'sysop' ],
-                       Title::newFromText( __METHOD__ ),
-                       true,
-               ];
-               yield [
-                       RevisionRecord::DELETED_TEXT,
-                       RevisionRecord::DELETED_TEXT,
-                       [],
-                       Title::newFromText( __METHOD__ ),
-                       false,
-               ];
-       }
-
-       /**
-        * @dataProvider provideUserCanBitfield
-        * @covers \MediaWiki\Storage\RevisionRecord::userCanBitfield
-        */
-       public function testUserCanBitfield( $bitField, $field, $userGroups, $title, $expected ) {
-               $this->forceStandardPermissions();
-
-               $user = $this->getTestUser( $userGroups )->getUser();
-
-               $this->assertSame(
-                       $expected,
-                       RevisionRecord::userCanBitfield( $bitField, $field, $user, $title )
-               );
-       }
-
-       public function provideHasSameContent() {
-               /**
-                * @param SlotRecord[] $slots
-                * @param int $revId
-                * @return RevisionStoreRecord
-                */
-               $recordCreator = function ( array $slots, $revId ) {
-                       $title = Title::newFromText( 'provideHasSameContent' );
-                       $title->resetArticleID( 19 );
-                       $slots = new RevisionSlots( $slots );
-
-                       return new RevisionStoreRecord(
-                               $title,
-                               new UserIdentityValue( 11, __METHOD__, 0 ),
-                               CommentStoreComment::newUnsavedComment( __METHOD__ ),
-                               (object)[
-                                       'rev_id' => strval( $revId ),
-                                       'rev_page' => strval( $title->getArticleID() ),
-                                       'rev_timestamp' => '20200101000000',
-                                       'rev_deleted' => 0,
-                                       'rev_minor_edit' => 0,
-                                       'rev_parent_id' => '5',
-                                       'rev_len' => $slots->computeSize(),
-                                       'rev_sha1' => $slots->computeSha1(),
-                                       'page_latest' => '18',
-                               ],
-                               $slots
-                       );
-               };
-
-               // Create some slots with content
-               $mainA = SlotRecord::newUnsaved( 'main', new TextContent( 'A' ) );
-               $mainB = SlotRecord::newUnsaved( 'main', new TextContent( 'B' ) );
-               $auxA = SlotRecord::newUnsaved( 'aux', new TextContent( 'A' ) );
-               $auxB = SlotRecord::newUnsaved( 'aux', new TextContent( 'A' ) );
-
-               $initialRecord = $recordCreator( [ $mainA ], 12 );
-
-               return [
-                       'same record object' => [
-                               true,
-                               $initialRecord,
-                               $initialRecord,
-                       ],
-                       'same record content, different object' => [
-                               true,
-                               $recordCreator( [ $mainA ], 12 ),
-                               $recordCreator( [ $mainA ], 13 ),
-                       ],
-                       'same record content, aux slot, different object' => [
-                               true,
-                               $recordCreator( [ $auxA ], 12 ),
-                               $recordCreator( [ $auxB ], 13 ),
-                       ],
-                       'different content' => [
-                               false,
-                               $recordCreator( [ $mainA ], 12 ),
-                               $recordCreator( [ $mainB ], 13 ),
-                       ],
-                       'different content and number of slots' => [
-                               false,
-                               $recordCreator( [ $mainA ], 12 ),
-                               $recordCreator( [ $mainA, $mainB ], 13 ),
-                       ],
-               ];
-       }
-
-       /**
-        * @dataProvider provideHasSameContent
-        * @covers \MediaWiki\Storage\RevisionRecord::hasSameContent
-        * @group Database
-        */
-       public function testHasSameContent(
-               $expected,
-               RevisionRecord $record1,
-               RevisionRecord $record2
-       ) {
-               $this->assertSame(
-                       $expected,
-                       $record1->hasSameContent( $record2 )
-               );
-       }
-
-       public function provideIsDeleted() {
-               yield 'no deletion' => [
-                       0,
-                       [
-                               RevisionRecord::DELETED_TEXT => false,
-                               RevisionRecord::DELETED_COMMENT => false,
-                               RevisionRecord::DELETED_USER => false,
-                               RevisionRecord::DELETED_RESTRICTED => false,
-                       ]
-               ];
-               yield 'text deleted' => [
-                       RevisionRecord::DELETED_TEXT,
-                       [
-                               RevisionRecord::DELETED_TEXT => true,
-                               RevisionRecord::DELETED_COMMENT => false,
-                               RevisionRecord::DELETED_USER => false,
-                               RevisionRecord::DELETED_RESTRICTED => false,
-                       ]
-               ];
-               yield 'text and comment deleted' => [
-                       RevisionRecord::DELETED_TEXT + RevisionRecord::DELETED_COMMENT,
-                       [
-                               RevisionRecord::DELETED_TEXT => true,
-                               RevisionRecord::DELETED_COMMENT => true,
-                               RevisionRecord::DELETED_USER => false,
-                               RevisionRecord::DELETED_RESTRICTED => false,
-                       ]
-               ];
-               yield 'all 4 deleted' => [
-                       RevisionRecord::DELETED_TEXT +
-                       RevisionRecord::DELETED_COMMENT +
-                       RevisionRecord::DELETED_RESTRICTED +
-                       RevisionRecord::DELETED_USER,
-                       [
-                               RevisionRecord::DELETED_TEXT => true,
-                               RevisionRecord::DELETED_COMMENT => true,
-                               RevisionRecord::DELETED_USER => true,
-                               RevisionRecord::DELETED_RESTRICTED => true,
-                       ]
-               ];
-       }
-
-       /**
-        * @dataProvider provideIsDeleted
-        * @covers \MediaWiki\Storage\RevisionRecord::isDeleted
-        */
-       public function testIsDeleted( $revDeleted, $assertionMap ) {
-               $rev = $this->newRevision( [ 'rev_deleted' => $revDeleted ] );
-               foreach ( $assertionMap as $deletionLevel => $expected ) {
-                       $this->assertSame( $expected, $rev->isDeleted( $deletionLevel ) );
-               }
-       }
-
 }
index dbbef11..07f1f82 100644 (file)
@@ -2,6 +2,7 @@
 
 namespace MediaWiki\Tests\Storage;
 
+use InvalidArgumentException;
 use Language;
 use MediaWiki\MediaWikiServices;
 use MediaWiki\Storage\SqlBlobStore;
@@ -238,4 +239,40 @@ class SqlBlobStoreTest extends MediaWikiTestCase {
                $this->assertSame( $blob, $store->getBlob( $address ) );
        }
 
+       public function provideGetTextIdFromAddress() {
+               yield [ 'tt:17', 17 ];
+               yield [ 'xy:17', null ];
+               yield [ 'xy:xyzzy', null ];
+       }
+
+       /**
+        * @dataProvider provideGetTextIdFromAddress
+        */
+       public function testGetTextIdFromAddress( $address, $textId ) {
+               $store = $this->getBlobStore();
+               $this->assertSame( $textId, $store->getTextIdFromAddress( $address ) );
+       }
+
+       public function provideGetTextIdFromAddressInvalidArgumentException() {
+               yield [ 'tt:-17' ];
+               yield [ 'tt:xy' ];
+               yield [ 'tt:0' ];
+               yield [ 'tt:' ];
+               yield [ 'xy' ];
+               yield [ '' ];
+       }
+
+       /**
+        * @dataProvider provideGetTextIdFromAddressInvalidArgumentException
+        */
+       public function testGetTextIdFromAddressInvalidArgumentException( $address ) {
+               $this->setExpectedException( InvalidArgumentException::class );
+               $store = $this->getBlobStore();
+               $store->getTextIdFromAddress( $address );
+       }
+
+       public function testMakeAddressFromTextId() {
+               $this->assertSame( 'tt:17', SqlBlobStore::makeAddressFromTextId( 17 ) );
+       }
+
 }
index dbedfc5..4bffc74 100644 (file)
@@ -1159,7 +1159,6 @@ class ApiBaseTest extends ApiTestCase {
                $integerTests = [
                        [ '+1', 1 ],
                        [ '-1', -1 ],
-                       [ '1e3', 1 ],
                        [ '1.5', 1 ],
                        [ '-1.5', -1 ],
                        [ '1abc', 1 ],
diff --git a/tests/phpunit/includes/api/ApiMoveTest.php b/tests/phpunit/includes/api/ApiMoveTest.php
new file mode 100644 (file)
index 0000000..fb697ff
--- /dev/null
@@ -0,0 +1,393 @@
+<?php
+
+/**
+ * @group API
+ * @group Database
+ * @group medium
+ *
+ * @covers ApiMove
+ */
+class ApiMoveTest extends ApiTestCase {
+       /**
+        * @param string $from Prefixed name of source
+        * @param string $to Prefixed name of destination
+        * @param string $id Page id of the page to move
+        * @param array|string|null $opts Options: 'noredirect' to expect no redirect
+        */
+       protected function assertMoved( $from, $to, $id, $opts = null ) {
+               $opts = (array)$opts;
+
+               $fromTitle = Title::newFromText( $from );
+               $toTitle = Title::newFromText( $to );
+
+               $this->assertTrue( $toTitle->exists(),
+                       "Destination {$toTitle->getPrefixedText()} does not exist" );
+
+               if ( in_array( 'noredirect', $opts ) ) {
+                       $this->assertFalse( $fromTitle->exists(),
+                               "Source {$fromTitle->getPrefixedText()} exists" );
+               } else {
+                       $this->assertTrue( $fromTitle->exists(),
+                               "Source {$fromTitle->getPrefixedText()} does not exist" );
+                       $this->assertTrue( $fromTitle->isRedirect(),
+                               "Source {$fromTitle->getPrefixedText()} is not a redirect" );
+
+                       $target = Revision::newFromTitle( $fromTitle )->getContent()->getRedirectTarget();
+                       $this->assertSame( $toTitle->getPrefixedText(), $target->getPrefixedText() );
+               }
+
+               $this->assertSame( $id, $toTitle->getArticleId() );
+       }
+
+       /**
+        * Shortcut function to create a page and return its id.
+        *
+        * @param string $name Page to create
+        * @return int ID of created page
+        */
+       protected function createPage( $name ) {
+               return $this->editPage( $name, 'Content' )->value['revision']->getPage();
+       }
+
+       public function testFromWithFromid() {
+               $this->setExpectedException( ApiUsageException::class,
+                       'The parameters "from" and "fromid" can not be used together.' );
+
+               $this->doApiRequestWithToken( [
+                       'action' => 'move',
+                       'from' => 'Some page',
+                       'fromid' => 123,
+                       'to' => 'Some other page',
+               ] );
+       }
+
+       public function testMove() {
+               $name = ucfirst( __FUNCTION__ );
+
+               $id = $this->createPage( $name );
+
+               $res = $this->doApiRequestWithToken( [
+                       'action' => 'move',
+                       'from' => $name,
+                       'to' => "$name 2",
+               ] );
+
+               $this->assertMoved( $name, "$name 2", $id );
+               $this->assertArrayNotHasKey( 'warnings', $res[0] );
+       }
+
+       public function testMoveById() {
+               $name = ucfirst( __FUNCTION__ );
+
+               $id = $this->createPage( $name );
+
+               $res = $this->doApiRequestWithToken( [
+                       'action' => 'move',
+                       'fromid' => $id,
+                       'to' => "$name 2",
+               ] );
+
+               $this->assertMoved( $name, "$name 2", $id );
+               $this->assertArrayNotHasKey( 'warnings', $res[0] );
+       }
+
+       public function testMoveNonexistent() {
+               $this->setExpectedException( ApiUsageException::class,
+                       "The page you specified doesn't exist." );
+
+               $this->doApiRequestWithToken( [
+                       'action' => 'move',
+                       'from' => 'Nonexistent page',
+                       'to' => 'Different page'
+               ] );
+       }
+
+       public function testMoveNonexistentId() {
+               $this->setExpectedException( ApiUsageException::class,
+                       'There is no page with ID 2147483647.' );
+
+               $this->doApiRequestWithToken( [
+                       'action' => 'move',
+                       'fromid' => pow( 2, 31 ) - 1,
+                       'to' => 'Different page',
+               ] );
+       }
+
+       public function testMoveToInvalidPageName() {
+               $this->setExpectedException( ApiUsageException::class, 'Bad title "[".' );
+
+               $name = ucfirst( __FUNCTION__ );
+               $id = $this->createPage( $name );
+
+               try {
+                       $this->doApiRequestWithToken( [
+                               'action' => 'move',
+                               'from' => $name,
+                               'to' => '[',
+                       ] );
+               } finally {
+                       $this->assertSame( $id, Title::newFromText( $name )->getArticleId() );
+               }
+       }
+
+       // @todo File moving
+
+       public function testPingLimiter() {
+               global $wgRateLimits;
+
+               $this->setExpectedException( ApiUsageException::class,
+                       "You've exceeded your rate limit. Please wait some time and try again." );
+
+               $name = ucfirst( __FUNCTION__ );
+
+               $this->setMwGlobals( 'wgMainCacheType', 'hash' );
+
+               $this->stashMwGlobals( 'wgRateLimits' );
+               $wgRateLimits['move'] = [ '&can-bypass' => false, 'user' => [ 1, 60 ] ];
+
+               $id = $this->createPage( $name );
+
+               $res = $this->doApiRequestWithToken( [
+                       'action' => 'move',
+                       'from' => $name,
+                       'to' => "$name 2",
+               ] );
+
+               $this->assertMoved( $name, "$name 2", $id );
+               $this->assertArrayNotHasKey( 'warnings', $res[0] );
+
+               try {
+                       $this->doApiRequestWithToken( [
+                               'action' => 'move',
+                               'from' => "$name 2",
+                               'to' => "$name 3",
+                       ] );
+               } finally {
+                       $this->assertSame( $id, Title::newFromText( "$name 2" )->getArticleId() );
+                       $this->assertFalse( Title::newFromText( "$name 3" )->exists(),
+                               "\"$name 3\" should not exist" );
+               }
+       }
+
+       public function testTagsNoPermission() {
+               $this->setExpectedException( ApiUsageException::class,
+                       'You do not have permission to apply change tags along with your changes.' );
+
+               $name = ucfirst( __FUNCTION__ );
+
+               ChangeTags::defineTag( 'custom tag' );
+
+               $this->setGroupPermissions( 'user', 'applychangetags', false );
+
+               $id = $this->createPage( $name );
+
+               try {
+                       $this->doApiRequestWithToken( [
+                               'action' => 'move',
+                               'from' => $name,
+                               'to' => "$name 2",
+                               'tags' => 'custom tag',
+                       ] );
+               } finally {
+                       $this->assertSame( $id, Title::newFromText( $name )->getArticleId() );
+                       $this->assertFalse( Title::newFromText( "$name 2" )->exists(),
+                               "\"$name 2\" should not exist" );
+               }
+       }
+
+       public function testSelfMove() {
+               $this->setExpectedException( ApiUsageException::class,
+                       'The title is the same; cannot move a page over itself.' );
+
+               $name = ucfirst( __FUNCTION__ );
+               $this->createPage( $name );
+
+               $this->doApiRequestWithToken( [
+                       'action' => 'move',
+                       'from' => $name,
+                       'to' => $name,
+               ] );
+       }
+
+       public function testMoveTalk() {
+               $name = ucfirst( __FUNCTION__ );
+
+               $id = $this->createPage( $name );
+               $talkId = $this->createPage( "Talk:$name" );
+
+               $res = $this->doApiRequestWithToken( [
+                       'action' => 'move',
+                       'from' => $name,
+                       'to' => "$name 2",
+                       'movetalk' => '',
+               ] );
+
+               $this->assertMoved( $name, "$name 2", $id );
+               $this->assertMoved( "Talk:$name", "Talk:$name 2", $talkId );
+
+               $this->assertArrayNotHasKey( 'warnings', $res[0] );
+       }
+
+       public function testMoveTalkFailed() {
+               $name = ucfirst( __FUNCTION__ );
+
+               $id = $this->createPage( $name );
+               $talkId = $this->createPage( "Talk:$name" );
+               $talkDestinationId = $this->createPage( "Talk:$name 2" );
+
+               $res = $this->doApiRequestWithToken( [
+                       'action' => 'move',
+                       'from' => $name,
+                       'to' => "$name 2",
+                       'movetalk' => '',
+               ] );
+
+               $this->assertMoved( $name, "$name 2", $id );
+               $this->assertSame( $talkId, Title::newFromText( "Talk:$name" )->getArticleId() );
+               $this->assertSame( $talkDestinationId,
+                       Title::newFromText( "Talk:$name 2" )->getArticleId() );
+               $this->assertSame( [ [
+                       'message' => 'articleexists',
+                       'params' => [],
+                       'code' => 'articleexists',
+                       'type' => 'error',
+               ] ], $res[0]['move']['talkmove-errors'] );
+
+               $this->assertArrayNotHasKey( 'warnings', $res[0] );
+       }
+
+       public function testMoveSubpages() {
+               global $wgNamespacesWithSubpages;
+
+               $name = ucfirst( __FUNCTION__ );
+
+               $this->stashMwGlobals( 'wgNamespacesWithSubpages' );
+               $wgNamespacesWithSubpages[NS_MAIN] = true;
+
+               $pages = [ $name, "$name/1", "$name/2", "Talk:$name", "Talk:$name/1", "Talk:$name/3" ];
+               $ids = [];
+               foreach ( array_merge( $pages, [ "$name/error", "$name 2/error" ] ) as $page ) {
+                       $ids[$page] = $this->createPage( $page );
+               }
+
+               $res = $this->doApiRequestWithToken( [
+                       'action' => 'move',
+                       'from' => $name,
+                       'to' => "$name 2",
+                       'movetalk' => '',
+                       'movesubpages' => '',
+               ] );
+
+               foreach ( $pages as $page ) {
+                       $this->assertMoved( $page, str_replace( $name, "$name 2", $page ), $ids[$page] );
+               }
+
+               $this->assertSame( $ids["$name/error"],
+                       Title::newFromText( "$name/error" )->getArticleId() );
+               $this->assertSame( $ids["$name 2/error"],
+                       Title::newFromText( "$name 2/error" )->getArticleId() );
+
+               $results = array_merge( $res[0]['move']['subpages'], $res[0]['move']['subpages-talk'] );
+               foreach ( $results as $arr ) {
+                       if ( $arr['from'] === "$name/error" ) {
+                               $this->assertSame( [ [
+                                       'message' => 'articleexists',
+                                       'params' => [],
+                                       'code' => 'articleexists',
+                                       'type' => 'error'
+                               ] ], $arr['errors'] );
+                       } else {
+                               $this->assertSame( str_replace( $name, "$name 2", $arr['from'] ), $arr['to'] );
+                       }
+                       $this->assertCount( 2, $arr );
+               }
+
+               $this->assertArrayNotHasKey( 'warnings', $res[0] );
+       }
+
+       public function testMoveNoPermission() {
+               $this->setExpectedException( ApiUsageException::class,
+                       'You must be a registered user and [[Special:UserLogin|logged in]] to move a page.' );
+
+               $name = ucfirst( __FUNCTION__ );
+
+               $id = $this->createPage( $name );
+
+               $user = new User();
+
+               try {
+                       $this->doApiRequestWithToken( [
+                               'action' => 'move',
+                               'from' => $name,
+                               'to' => "$name 2",
+                       ], null, $user );
+               } finally {
+                       $this->assertSame( $id, Title::newFromText( "$name" )->getArticleId() );
+                       $this->assertFalse( Title::newFromText( "$name 2" )->exists(),
+                               "\"$name 2\" should not exist" );
+               }
+       }
+
+       public function testSuppressRedirect() {
+               $name = ucfirst( __FUNCTION__ );
+
+               $id = $this->createPage( $name );
+
+               $res = $this->doApiRequestWithToken( [
+                       'action' => 'move',
+                       'from' => $name,
+                       'to' => "$name 2",
+                       'noredirect' => '',
+               ] );
+
+               $this->assertMoved( $name, "$name 2", $id, 'noredirect' );
+               $this->assertArrayNotHasKey( 'warnings', $res[0] );
+       }
+
+       public function testSuppressRedirectNoPermission() {
+               $name = ucfirst( __FUNCTION__ );
+
+               $this->setGroupPermissions( 'sysop', 'suppressredirect', false );
+
+               $id = $this->createPage( $name );
+
+               $res = $this->doApiRequestWithToken( [
+                       'action' => 'move',
+                       'from' => $name,
+                       'to' => "$name 2",
+                       'noredirect' => '',
+               ] );
+
+               $this->assertMoved( $name, "$name 2", $id );
+               $this->assertArrayNotHasKey( 'warnings', $res[0] );
+       }
+
+       public function testMoveSubpagesError() {
+               $name = ucfirst( __FUNCTION__ );
+
+               // Subpages are allowed in talk but not main
+               $idBase = $this->createPage( "Talk:$name" );
+               $idSub = $this->createPage( "Talk:$name/1" );
+
+               $res = $this->doApiRequestWithToken( [
+                       'action' => 'move',
+                       'from' => "Talk:$name",
+                       'to' => $name,
+                       'movesubpages' => '',
+               ] );
+
+               $this->assertMoved( "Talk:$name", $name, $idBase );
+               $this->assertSame( $idSub, Title::newFromText( "Talk:$name/1" )->getArticleId() );
+               $this->assertFalse( Title::newFromText( "$name/1" )->exists(),
+                       "\"$name/1\" should not exist" );
+
+               $this->assertSame( [ 'errors' => [ [
+                       'message' => 'namespace-nosubpages',
+                       'params' => [ '' ],
+                       'code' => 'namespace-nosubpages',
+                       'type' => 'error',
+               ] ] ], $res[0]['move']['subpages'] );
+
+               $this->assertArrayNotHasKey( 'warnings', $res[0] );
+       }
+}
index 7e58555..e054569 100644 (file)
@@ -51,17 +51,23 @@ class LoadBalancerTest extends MediaWikiTestCase {
        public function testWithoutReplica() {
                global $wgDBname;
 
+               $called = false;
                $lb = new LoadBalancer( [
                        'servers' => [ $this->makeServerConfig() ],
                        'queryLogger' => MediaWiki\Logger\LoggerFactory::getInstance( 'DBQuery' ),
-                       'localDomain' => new DatabaseDomain( $wgDBname, null, $this->dbPrefix() )
+                       'localDomain' => new DatabaseDomain( $wgDBname, null, $this->dbPrefix() ),
+                       'chronologyCallback' => function () use ( &$called ) {
+                               $called = true;
+                       }
                ] );
 
                $ld = DatabaseDomain::newFromId( $lb->getLocalDomainID() );
                $this->assertEquals( $wgDBname, $ld->getDatabase(), 'local domain DB set' );
                $this->assertEquals( $this->dbPrefix(), $ld->getTablePrefix(), 'local domain prefix set' );
 
+               $this->assertFalse( $called );
                $dbw = $lb->getConnection( DB_MASTER );
+               $this->assertTrue( $called );
                $this->assertTrue( $dbw->getLBInfo( 'master' ), 'master shows as master' );
                $this->assertTrue( $dbw->getFlag( $dbw::DBO_TRX ), "DBO_TRX set on master" );
                $this->assertWriteAllowed( $dbw );
index 02b3549..46bf2c6 100644 (file)
@@ -515,7 +515,7 @@ class CSSMinTest extends MediaWikiTestCase {
                                'foo { background: url(//localhost/styles.css?quoted=single) }',
                        ],
                        [
-                               'Background URL (containing parentheses; T60473)',
+                               'Background URL (double quoted, containing parentheses; T60473)',
                                'foo { background: url("//localhost/styles.css?query=(parens)") }',
                                'foo { background: url("//localhost/styles.css?query=(parens)") }',
                        ],
@@ -529,6 +529,11 @@ class CSSMinTest extends MediaWikiTestCase {
                                'foo { background: url(\'//localhost/styles.css?quote="\') }',
                                'foo { background: url("//localhost/styles.css?quote=\"") }',
                        ],
+                       [
+                               'Background URL (double quoted with outer spacing)',
+                               'foo { background: url( "http://localhost/styles.css?quoted=double" ) }',
+                               'foo { background: url(http://localhost/styles.css?quoted=double) }',
+                       ],
                        [
                                'Simple case with comments before url',
                                'foo { prop: /* some {funny;} comment */ url(bar.png); }',
index cfe9ad0..3d15b03 100644 (file)
@@ -1428,6 +1428,140 @@ class DatabaseSQLTest extends PHPUnit\Framework\TestCase {
                // phpcs:ignore Generic.Files.LineLength
                $this->assertLastSql( 'BEGIN; SAVEPOINT wikimedia_rdbms_atomic1; RELEASE SAVEPOINT wikimedia_rdbms_atomic1; ROLLBACK' );
 
+               $fname = __METHOD__;
+               $triggerMap = [
+                       '-' => '-',
+                       IDatabase::TRIGGER_COMMIT => 'tCommit',
+                       IDatabase::TRIGGER_ROLLBACK => 'tRollback'
+               ];
+               $callback1 = function ( $trigger = '-' ) use ( $fname, $triggerMap ) {
+                       $this->database->query( "SELECT 1, {$triggerMap[$trigger]} AS t", $fname );
+               };
+               $callback2 = function ( $trigger = '-' ) use ( $fname, $triggerMap ) {
+                       $this->database->query( "SELECT 2, {$triggerMap[$trigger]} AS t", $fname );
+               };
+               $callback3 = function ( $trigger = '-' ) use ( $fname, $triggerMap ) {
+                       $this->database->query( "SELECT 3, {$triggerMap[$trigger]} AS t", $fname );
+               };
+
+               $this->database->startAtomic( __METHOD__, IDatabase::ATOMIC_CANCELABLE );
+               $this->database->onTransactionPreCommitOrIdle( $callback1, __METHOD__ );
+               $this->database->cancelAtomic( __METHOD__ );
+               $this->assertLastSql( 'BEGIN; ROLLBACK' );
+
+               $this->database->startAtomic( __METHOD__, IDatabase::ATOMIC_CANCELABLE );
+               $this->database->onTransactionIdle( $callback1, __METHOD__ );
+               $this->database->cancelAtomic( __METHOD__ );
+               $this->assertLastSql( 'BEGIN; ROLLBACK' );
+
+               $this->database->startAtomic( __METHOD__, IDatabase::ATOMIC_CANCELABLE );
+               $this->database->onTransactionResolution( $callback1, __METHOD__ );
+               $this->database->cancelAtomic( __METHOD__ );
+               $this->assertLastSql( 'BEGIN; ROLLBACK; SELECT 1, tRollback AS t' );
+
+               $this->database->startAtomic( __METHOD__ . '_outer' );
+               $this->database->onTransactionPreCommitOrIdle( $callback1, __METHOD__ );
+               $this->database->startAtomic( __METHOD__, IDatabase::ATOMIC_CANCELABLE );
+               $this->database->onTransactionPreCommitOrIdle( $callback2, __METHOD__ );
+               $this->database->cancelAtomic( __METHOD__ );
+               $this->database->onTransactionPreCommitOrIdle( $callback3, __METHOD__ );
+               $this->database->endAtomic( __METHOD__ . '_outer' );
+               $this->assertLastSql( implode( "; ", [
+                       'BEGIN',
+                       'SAVEPOINT wikimedia_rdbms_atomic1',
+                       'ROLLBACK TO SAVEPOINT wikimedia_rdbms_atomic1',
+                       'SELECT 1, - AS t',
+                       'SELECT 3, - AS t',
+                       'COMMIT'
+               ] ) );
+
+               $this->database->startAtomic( __METHOD__ . '_outer' );
+               $this->database->onTransactionIdle( $callback1, __METHOD__ );
+               $this->database->startAtomic( __METHOD__, IDatabase::ATOMIC_CANCELABLE );
+               $this->database->onTransactionIdle( $callback2, __METHOD__ );
+               $this->database->cancelAtomic( __METHOD__ );
+               $this->database->onTransactionIdle( $callback3, __METHOD__ );
+               $this->database->endAtomic( __METHOD__ . '_outer' );
+               $this->assertLastSql( implode( "; ", [
+                       'BEGIN',
+                       'SAVEPOINT wikimedia_rdbms_atomic1',
+                       'ROLLBACK TO SAVEPOINT wikimedia_rdbms_atomic1',
+                       'COMMIT',
+                       'SELECT 1, tCommit AS t',
+                       'SELECT 3, tCommit AS t'
+               ] ) );
+
+               $this->database->startAtomic( __METHOD__ . '_outer' );
+               $this->database->onTransactionResolution( $callback1, __METHOD__ );
+               $this->database->startAtomic( __METHOD__, IDatabase::ATOMIC_CANCELABLE );
+               $this->database->onTransactionResolution( $callback2, __METHOD__ );
+               $this->database->cancelAtomic( __METHOD__ );
+               $this->database->onTransactionResolution( $callback3, __METHOD__ );
+               $this->database->endAtomic( __METHOD__ . '_outer' );
+               $this->assertLastSql( implode( "; ", [
+                       'BEGIN',
+                       'SAVEPOINT wikimedia_rdbms_atomic1',
+                       'ROLLBACK TO SAVEPOINT wikimedia_rdbms_atomic1',
+                       'COMMIT',
+                       'SELECT 1, tCommit AS t',
+                       'SELECT 2, tRollback AS t',
+                       'SELECT 3, tCommit AS t'
+               ] ) );
+
+               $makeCallback = function ( $id ) use ( $fname, $triggerMap ) {
+                       return function ( $trigger = '-' ) use ( $id, $fname, $triggerMap ) {
+                               $this->database->query( "SELECT $id, {$triggerMap[$trigger]} AS t", $fname );
+                       };
+               };
+
+               $this->database->startAtomic( __METHOD__ . '_outer' );
+               $this->database->startAtomic( __METHOD__, IDatabase::ATOMIC_CANCELABLE );
+               $this->database->onTransactionResolution( $makeCallback( 1 ), __METHOD__ );
+               $this->database->cancelAtomic( __METHOD__ );
+               $this->database->endAtomic( __METHOD__ . '_outer' );
+               $this->assertLastSql( implode( "; ", [
+                       'BEGIN',
+                       'SAVEPOINT wikimedia_rdbms_atomic1',
+                       'ROLLBACK TO SAVEPOINT wikimedia_rdbms_atomic1',
+                       'COMMIT',
+                       'SELECT 1, tRollback AS t'
+               ] ) );
+
+               $this->database->startAtomic( __METHOD__ . '_level1', IDatabase::ATOMIC_CANCELABLE );
+               $this->database->onTransactionResolution( $makeCallback( 1 ), __METHOD__ );
+               $this->database->startAtomic( __METHOD__ . '_level2' );
+               $this->database->startAtomic( __METHOD__ . '_level3', IDatabase::ATOMIC_CANCELABLE );
+               $this->database->startAtomic( __METHOD__, IDatabase::ATOMIC_CANCELABLE );
+               $this->database->onTransactionResolution( $makeCallback( 2 ), __METHOD__ );
+               $this->database->endAtomic( __METHOD__ );
+               $this->database->onTransactionResolution( $makeCallback( 3 ), __METHOD__ );
+               $this->database->cancelAtomic( __METHOD__ . '_level3' );
+               $this->database->endAtomic( __METHOD__ . '_level2' );
+               $this->database->onTransactionResolution( $makeCallback( 4 ), __METHOD__ );
+               $this->database->endAtomic( __METHOD__ . '_level1' );
+               $this->assertLastSql( implode( "; ", [
+                       'BEGIN',
+                       'SAVEPOINT wikimedia_rdbms_atomic1',
+                       'SAVEPOINT wikimedia_rdbms_atomic2',
+                       'RELEASE SAVEPOINT wikimedia_rdbms_atomic2',
+                       'ROLLBACK TO SAVEPOINT wikimedia_rdbms_atomic1',
+                       'COMMIT; SELECT 1, tCommit AS t',
+                       'SELECT 2, tRollback AS t',
+                       'SELECT 3, tRollback AS t',
+                       'SELECT 4, tCommit AS t'
+               ] ) );
+       }
+
+       /**
+        * @covers \Wikimedia\Rdbms\Database::doSavepoint
+        * @covers \Wikimedia\Rdbms\Database::doReleaseSavepoint
+        * @covers \Wikimedia\Rdbms\Database::doRollbackToSavepoint
+        * @covers \Wikimedia\Rdbms\Database::startAtomic
+        * @covers \Wikimedia\Rdbms\Database::endAtomic
+        * @covers \Wikimedia\Rdbms\Database::cancelAtomic
+        * @covers \Wikimedia\Rdbms\Database::doAtomicSection
+        */
+       public function testAtomicSectionsRecovery() {
                $this->database->begin( __METHOD__ );
                try {
                        $this->database->doAtomicSection(
@@ -1460,10 +1594,169 @@ class DatabaseSQLTest extends PHPUnit\Framework\TestCase {
                } catch ( RuntimeException $ex ) {
                        $this->assertSame( 'Test exception', $ex->getMessage() );
                }
+               try {
+                       $this->database->commit( __METHOD__ );
+                       $this->fail( 'Test exception not thrown' );
+               } catch ( DBTransactionError $ex ) {
+                       $this->assertSame(
+                               'Cannot execute query from ' . __METHOD__ . ' while transaction status is ERROR.',
+                               $ex->getMessage()
+                       );
+               }
                $this->database->rollback( __METHOD__ );
                $this->assertLastSql( 'BEGIN; ROLLBACK' );
        }
 
+       /**
+        * @covers \Wikimedia\Rdbms\Database::doSavepoint
+        * @covers \Wikimedia\Rdbms\Database::doReleaseSavepoint
+        * @covers \Wikimedia\Rdbms\Database::doRollbackToSavepoint
+        * @covers \Wikimedia\Rdbms\Database::startAtomic
+        * @covers \Wikimedia\Rdbms\Database::endAtomic
+        * @covers \Wikimedia\Rdbms\Database::cancelAtomic
+        * @covers \Wikimedia\Rdbms\Database::doAtomicSection
+        */
+       public function testAtomicSectionsCallbackCancellation() {
+               $fname = __METHOD__;
+               $callback1Called = null;
+               $callback1 = function ( $trigger = '-' ) use ( $fname, &$callback1Called ) {
+                       $callback1Called = $trigger;
+                       $this->database->query( "SELECT 1", $fname );
+               };
+               $callback2Called = null;
+               $callback2 = function ( $trigger = '-' ) use ( $fname, &$callback2Called ) {
+                       $callback2Called = $trigger;
+                       $this->database->query( "SELECT 2", $fname );
+               };
+               $callback3Called = null;
+               $callback3 = function ( $trigger = '-' ) use ( $fname, &$callback3Called ) {
+                       $callback3Called = $trigger;
+                       $this->database->query( "SELECT 3", $fname );
+               };
+
+               $this->database->startAtomic( __METHOD__ . '_outer' );
+               $this->database->startAtomic( __METHOD__, IDatabase::ATOMIC_CANCELABLE );
+               $this->database->startAtomic( __METHOD__ . '_inner' );
+               $this->database->onTransactionIdle( $callback1, __METHOD__ );
+               $this->database->onTransactionPreCommitOrIdle( $callback2, __METHOD__ );
+               $this->database->onTransactionResolution( $callback3, __METHOD__ );
+               $this->database->endAtomic( __METHOD__ . '_inner' );
+               $this->database->cancelAtomic( __METHOD__ );
+               $this->database->endAtomic( __METHOD__ . '_outer' );
+               $this->assertNull( $callback1Called );
+               $this->assertNull( $callback2Called );
+               $this->assertEquals( IDatabase::TRIGGER_ROLLBACK, $callback3Called );
+               // phpcs:ignore Generic.Files.LineLength
+               $this->assertLastSql( 'BEGIN; SAVEPOINT wikimedia_rdbms_atomic1; ROLLBACK TO SAVEPOINT wikimedia_rdbms_atomic1; COMMIT; SELECT 3' );
+
+               $callback1Called = null;
+               $callback2Called = null;
+               $callback3Called = null;
+               $this->database->startAtomic( __METHOD__ . '_outer' );
+               $this->database->startAtomic( __METHOD__, IDatabase::ATOMIC_CANCELABLE );
+               $this->database->startAtomic( __METHOD__ . '_inner', IDatabase::ATOMIC_CANCELABLE );
+               $this->database->onTransactionIdle( $callback1, __METHOD__ );
+               $this->database->onTransactionPreCommitOrIdle( $callback2, __METHOD__ );
+               $this->database->onTransactionResolution( $callback3, __METHOD__ );
+               $this->database->endAtomic( __METHOD__ . '_inner' );
+               $this->database->cancelAtomic( __METHOD__ );
+               $this->database->endAtomic( __METHOD__ . '_outer' );
+               $this->assertNull( $callback1Called );
+               $this->assertNull( $callback2Called );
+               $this->assertEquals( IDatabase::TRIGGER_ROLLBACK, $callback3Called );
+               // phpcs:ignore Generic.Files.LineLength
+               $this->assertLastSql( 'BEGIN; SAVEPOINT wikimedia_rdbms_atomic1; SAVEPOINT wikimedia_rdbms_atomic2; RELEASE SAVEPOINT wikimedia_rdbms_atomic2; ROLLBACK TO SAVEPOINT wikimedia_rdbms_atomic1; COMMIT; SELECT 3' );
+
+               $callback1Called = null;
+               $callback2Called = null;
+               $callback3Called = null;
+               $this->database->startAtomic( __METHOD__ . '_outer' );
+               $atomicId = $this->database->startAtomic( __METHOD__, IDatabase::ATOMIC_CANCELABLE );
+               $this->database->startAtomic( __METHOD__ . '_inner' );
+               $this->database->onTransactionIdle( $callback1, __METHOD__ );
+               $this->database->onTransactionPreCommitOrIdle( $callback2, __METHOD__ );
+               $this->database->onTransactionResolution( $callback3, __METHOD__ );
+               $this->database->cancelAtomic( __METHOD__, $atomicId );
+               $this->database->endAtomic( __METHOD__ . '_outer' );
+               $this->assertNull( $callback1Called );
+               $this->assertNull( $callback2Called );
+               $this->assertEquals( IDatabase::TRIGGER_ROLLBACK, $callback3Called );
+
+               $callback1Called = null;
+               $callback2Called = null;
+               $callback3Called = null;
+               $this->database->startAtomic( __METHOD__ . '_outer' );
+               $atomicId = $this->database->startAtomic( __METHOD__, IDatabase::ATOMIC_CANCELABLE );
+               $this->database->startAtomic( __METHOD__ . '_inner' );
+               $this->database->onTransactionIdle( $callback1, __METHOD__ );
+               $this->database->onTransactionPreCommitOrIdle( $callback2, __METHOD__ );
+               $this->database->onTransactionResolution( $callback3, __METHOD__ );
+               try {
+                       $this->database->cancelAtomic( __METHOD__ . '_X', $atomicId );
+               } catch ( DBUnexpectedError $e ) {
+                       $m = __METHOD__;
+                       $this->assertSame(
+                               "Invalid atomic section ended (got {$m}_X but expected {$m}).",
+                               $e->getMessage()
+                       );
+               }
+               $this->database->cancelAtomic( __METHOD__ );
+               $this->database->endAtomic( __METHOD__ . '_outer' );
+               $this->assertNull( $callback1Called );
+               $this->assertNull( $callback2Called );
+               $this->assertEquals( IDatabase::TRIGGER_ROLLBACK, $callback3Called );
+
+               $this->database->startAtomic( __METHOD__ . '_outer' );
+               $this->database->startAtomic( __METHOD__, IDatabase::ATOMIC_CANCELABLE );
+               $this->database->startAtomic( __METHOD__ . '_inner' );
+               $this->database->onTransactionIdle( $callback1, __METHOD__ );
+               $this->database->onTransactionPreCommitOrIdle( $callback2, __METHOD__ );
+               $this->database->onTransactionResolution( $callback3, __METHOD__ );
+               $this->database->cancelAtomic( __METHOD__ . '_inner' );
+               $this->database->cancelAtomic( __METHOD__ );
+               $this->database->endAtomic( __METHOD__ . '_outer' );
+               $this->assertNull( $callback1Called );
+               $this->assertNull( $callback2Called );
+               $this->assertEquals( IDatabase::TRIGGER_ROLLBACK, $callback3Called );
+
+               $wrapper = TestingAccessWrapper::newFromObject( $this->database );
+               $callback1Called = null;
+               $callback2Called = null;
+               $callback3Called = null;
+               $this->database->startAtomic( __METHOD__ . '_outer' );
+               $this->database->startAtomic( __METHOD__, IDatabase::ATOMIC_CANCELABLE );
+               $this->database->startAtomic( __METHOD__ . '_inner' );
+               $this->database->onTransactionIdle( $callback1, __METHOD__ );
+               $this->database->onTransactionPreCommitOrIdle( $callback2, __METHOD__ );
+               $this->database->onTransactionResolution( $callback3, __METHOD__ );
+               $wrapper->trxStatus = Database::STATUS_TRX_ERROR;
+               $this->database->cancelAtomic( __METHOD__ . '_inner' );
+               $this->database->cancelAtomic( __METHOD__ );
+               $this->database->endAtomic( __METHOD__ . '_outer' );
+               $this->assertNull( $callback1Called );
+               $this->assertNull( $callback2Called );
+               $this->assertEquals( IDatabase::TRIGGER_ROLLBACK, $callback3Called );
+       }
+
+       /**
+        * @covers \Wikimedia\Rdbms\Database::doSavepoint
+        * @covers \Wikimedia\Rdbms\Database::doReleaseSavepoint
+        * @covers \Wikimedia\Rdbms\Database::doRollbackToSavepoint
+        * @covers \Wikimedia\Rdbms\Database::startAtomic
+        * @covers \Wikimedia\Rdbms\Database::endAtomic
+        * @covers \Wikimedia\Rdbms\Database::cancelAtomic
+        * @covers \Wikimedia\Rdbms\Database::doAtomicSection
+        */
+       public function testAtomicSectionsTrxRound() {
+               $this->database->setFlag( IDatabase::DBO_TRX );
+               $this->database->startAtomic( __METHOD__, IDatabase::ATOMIC_CANCELABLE );
+               $this->database->query( 'SELECT 1', __METHOD__ );
+               $this->database->endAtomic( __METHOD__ );
+               $this->database->commit( __METHOD__, IDatabase::FLUSHING_ALL_PEERS );
+               // phpcs:ignore Generic.Files.LineLength
+               $this->assertLastSql( 'BEGIN; SAVEPOINT wikimedia_rdbms_atomic1; SELECT 1; RELEASE SAVEPOINT wikimedia_rdbms_atomic1; COMMIT' );
+       }
+
        public static function provideAtomicSectionMethodsForErrors() {
                return [
                        [ 'endAtomic' ],
index 94b4e0d..e328cba 100644 (file)
@@ -310,14 +310,18 @@ class DatabaseTest extends PHPUnit\Framework\TestCase {
                $lb = $lbFactory->getMainLB();
                $conn = $lb->openConnection( $lb->getWriterIndex() );
                $this->assertSame( $db, $conn, 'Same DB instance' );
-               $this->assertTrue( $db->getFlag( DBO_TRX ), 'DBO_TRX is set' );
 
+               $this->assertFalse( $lb->hasMasterChanges() );
+               $this->assertTrue( $db->getFlag( DBO_TRX ), 'DBO_TRX is set' );
                $called = false;
                $callback = function () use ( &$called ) {
                        $called = true;
                };
                $db->onTransactionPreCommitOrIdle( $callback, __METHOD__ );
                $this->assertTrue( $called, 'Called when idle if DBO_TRX is set' );
+               $called = false;
+               $lbFactory->commitMasterChanges();
+               $this->assertFalse( $called );
 
                $called = false;
                $lbFactory->beginMasterChanges( __METHOD__ );
index 07956f1..ea3d199 100644 (file)
@@ -45,6 +45,7 @@ class ResourceLoaderClientHtmlTest extends PHPUnit\Framework\TestCase {
                        'test.private' => [ 'group' => 'private' ],
                        'test.shouldembed.empty' => [ 'shouldEmbed' => true, 'isKnownEmpty' => true ],
                        'test.shouldembed' => [ 'shouldEmbed' => true ],
+                       'test.user' => [ 'group' => 'user' ],
 
                        'test.styles.pure' => [ 'type' => ResourceLoaderModule::LOAD_STYLES ],
                        'test.styles.mixed' => [],
@@ -115,6 +116,7 @@ class ResourceLoaderClientHtmlTest extends PHPUnit\Framework\TestCase {
                        'test.private',
                        'test.shouldembed.empty',
                        'test.shouldembed',
+                       'test.user',
                        'test.unregistered',
                ] );
                $client->setModuleStyles( [
@@ -138,6 +140,7 @@ class ResourceLoaderClientHtmlTest extends PHPUnit\Framework\TestCase {
                                'test.private' => 'loading',
                                'test.shouldembed.empty' => 'ready',
                                'test.shouldembed' => 'loading',
+                               'test.user' => 'loading',
                                'test.styles.pure' => 'ready',
                                'test.styles.user.empty' => 'ready',
                                'test.styles.private' => 'ready',
@@ -163,6 +166,7 @@ class ResourceLoaderClientHtmlTest extends PHPUnit\Framework\TestCase {
                                'general' => [
                                        'test.private',
                                        'test.shouldembed',
+                                       'test.user',
                                ],
                        ],
                ];
@@ -319,6 +323,12 @@ class ResourceLoaderClientHtmlTest extends PHPUnit\Framework\TestCase {
                                'only' => ResourceLoaderModule::TYPE_SCRIPTS,
                                'output' => '<script>(window.RLQ=window.RLQ||[]).push(function(){mw.loader.load("/w/load.php?debug=false\u0026lang=nl\u0026modules=test.scripts.user\u0026only=scripts\u0026skin=fallback\u0026user=Example\u0026version=0a56zyi");});</script>',
                        ],
+                       [
+                               'context' => [],
+                               'modules' => [ 'test.user' ],
+                               'only' => ResourceLoaderModule::TYPE_COMBINED,
+                               'output' => '<script>(window.RLQ=window.RLQ||[]).push(function(){mw.loader.load("/w/load.php?debug=false\u0026lang=nl\u0026modules=test.user\u0026skin=fallback\u0026user=Example\u0026version=0a56zyi");});</script>',
+                       ],
                        [
                                'context' => [ 'debug' => true ],
                                'modules' => [ 'test.styles.pure', 'test.styles.mixed' ],
index 0aa37d2..d4b9c16 100644 (file)
@@ -15,6 +15,15 @@ class ResourceLoaderWikiModuleTest extends ResourceLoaderTestCase {
                $this->assertInstanceOf( ResourceLoaderWikiModule::class, $module );
        }
 
+       private function prepareTitleInfo( array $mockInfo ) {
+               $module = TestingAccessWrapper::newFromClass( ResourceLoaderWikiModule::class );
+               $info = [];
+               foreach ( $mockInfo as $key => $val ) {
+                       $info[ $module->makeTitleKey( Title::newFromText( $key ) ) ] = $val;
+               }
+               return $info;
+       }
+
        public static function provideConstructor() {
                return [
                        // Nothing
@@ -102,7 +111,7 @@ class ResourceLoaderWikiModuleTest extends ResourceLoaderTestCase {
                        ->getMock();
                $module->expects( $this->any() )
                        ->method( 'getTitleInfo' )
-                       ->will( $this->returnValue( $titleInfo ) );
+                       ->will( $this->returnValue( $this->prepareTitleInfo( $titleInfo ) ) );
                $module->expects( $this->any() )
                        ->method( 'getGroup' )
                        ->will( $this->returnValue( $group ) );
@@ -151,10 +160,10 @@ class ResourceLoaderWikiModuleTest extends ResourceLoaderTestCase {
                        'MediaWiki:Common.css' => [ 'type' => 'styles' ],
                        'mediawiki: fallback.css' => [ 'type' => 'styles' ],
                ];
-               $titleInfo = [
+               $titleInfo = $this->prepareTitleInfo( [
                        'MediaWiki:Common.css' => [ 'page_len' => 1234 ],
                        'MediaWiki:Fallback.css' => [ 'page_len' => 0 ],
-               ];
+               ] );
                $expected = $titleInfo;
 
                $module = $this->getMockBuilder( TestResourceLoaderWikiModule::class )
@@ -186,10 +195,10 @@ class ResourceLoaderWikiModuleTest extends ResourceLoaderTestCase {
                        // doing an intersect on the canonical result, producing an empty array.
                        'mediawiki: fallback.css' => [ 'type' => 'styles' ],
                ];
-               $titleInfo = [
+               $titleInfo = $this->prepareTitleInfo( [
                        'MediaWiki:Common.css' => [ 'page_len' => 1234 ],
                        'MediaWiki:Fallback.css' => [ 'page_len' => 0 ],
-               ];
+               ] );
                $expected = $titleInfo;
 
                $module = $this->getMockBuilder( TestResourceLoaderWikiModule::class )
index 23ef26f..74caf5c 100644 (file)
                        'detectParserForColumn() detect parser.id "number" for second column'
                );
        } );
+       QUnit.test( 'T29745 - References ignored in sortkey', function ( assert ) {
+               var $table, parsers;
+               $table = $(
+                       '<table class="sortable">' +
+                               '<tr><th>A</th></tr>' +
+                               '<tr><td>10</td></tr>' +
+                               '<tr><td>2<sup class="reference"><a href="#cite_note-1">[1]</a></sup></td></tr>' +
+                               '</table>'
+               );
+               $table.tablesorter();
+               $table.find( '.headerSort:eq(0)' ).click();
+
+               assert.deepEqual(
+                       tableExtract( $table ),
+                       [
+                               [ '2[1]' ],
+                               [ '10' ]
+                       ],
+                       'References ignored in sortkey'
+               );
+
+               parsers = $table.data( 'tablesorter' ).config.parsers;
+               assert.equal(
+                       parsers[ 0 ].id,
+                       'number',
+                       'detectParserForColumn() detect parser.id "number"'
+               );
+       } );
 
 }( jQuery, mediaWiki ) );
index 519b7be..6b71019 100755 (executable)
@@ -6,4 +6,4 @@ function kill_chromedriver() {
     killall chromedriver > /dev/null
 }
 trap kill_chromedriver EXIT
-./node_modules/.bin/grunt webdriver:test
+npm run selenium-test