Merge "Give TestCase::checkHasDiff3 a better name"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Sun, 31 Jan 2016 11:39:46 +0000 (11:39 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Sun, 31 Jan 2016 11:39:46 +0000 (11:39 +0000)
304 files changed:
RELEASE-NOTES-1.27
autoload.php
docs/deferred.txt
docs/hooks.txt
includes/DefaultSettings.php
includes/EditPage.php
includes/MediaWiki.php
includes/Sanitizer.php
includes/Setup.php
includes/Title.php
includes/WatchedItem.php
includes/api/ApiBase.php
includes/api/ApiCheckToken.php
includes/api/ApiCreateAccount.php
includes/api/ApiLogin.php
includes/api/ApiMain.php
includes/api/ApiQuerySiteinfo.php
includes/api/ApiQueryTokens.php
includes/api/ApiStashEdit.php
includes/api/ApiTokens.php
includes/api/i18n/de.json
includes/api/i18n/fr.json
includes/api/i18n/he.json
includes/api/i18n/it.json
includes/api/i18n/ksh.json
includes/api/i18n/nl.json
includes/api/i18n/zh-hans.json
includes/cache/MessageCache.php
includes/context/RequestContext.php
includes/db/DBConnRef.php
includes/db/Database.php
includes/db/DatabaseMysqlBase.php
includes/db/DatabasePostgres.php
includes/db/IDatabase.php
includes/db/loadbalancer/LBFactory.php
includes/db/loadbalancer/LoadBalancer.php
includes/debug/logger/monolog/KafkaHandler.php
includes/htmlform/HTMLUserTextField.php
includes/installer/DatabaseUpdater.php
includes/installer/MysqlUpdater.php
includes/installer/i18n/el.json
includes/installer/i18n/ja.json
includes/installer/i18n/mk.json
includes/installer/i18n/nl.json
includes/installer/i18n/zh-hans.json
includes/jobqueue/JobRunner.php
includes/jobqueue/jobs/ActivityUpdateJob.php
includes/jobqueue/jobs/CategoryMembershipChangeJob.php
includes/jobqueue/jobs/HTMLCacheUpdateJob.php
includes/jobqueue/jobs/RecentChangesUpdateJob.php
includes/logging/LogFormatter.php
includes/logging/TagLogFormatter.php
includes/mail/EmailNotification.php
includes/media/Bitmap.php
includes/media/TransformationalImageHandler.php
includes/objectcache/SqlBagOStuff.php
includes/page/Article.php
includes/page/WikiPage.php
includes/resourceloader/ResourceLoaderModule.php
includes/session/CookieSessionProvider.php
includes/session/Session.php
includes/session/SessionBackend.php
includes/session/SessionManager.php
includes/session/Token.php [new file with mode: 0644]
includes/session/UserInfo.php
includes/specials/SpecialChangePassword.php
includes/specials/SpecialMovepage.php
includes/specials/SpecialRecentchanges.php
includes/specials/SpecialUserlogin.php
includes/specials/SpecialVersion.php
includes/specials/SpecialWatchlist.php
includes/user/LoggedOutEditToken.php [new file with mode: 0644]
includes/user/User.php
includes/utils/BatchRowWriter.php
languages/classes/LanguageGan.php
languages/classes/LanguageIu.php
languages/classes/LanguageKk.php
languages/classes/LanguageKu.php
languages/classes/LanguageShi.php
languages/classes/LanguageSr.php
languages/classes/LanguageTg.php
languages/classes/LanguageUz.php
languages/classes/LanguageZh.php
languages/i18n/ar.json
languages/i18n/azb.json
languages/i18n/be-tarask.json
languages/i18n/bn.json
languages/i18n/bs.json
languages/i18n/ce.json
languages/i18n/ckb.json
languages/i18n/cs.json
languages/i18n/cu.json
languages/i18n/da.json
languages/i18n/de.json
languages/i18n/diq.json
languages/i18n/el.json
languages/i18n/en.json
languages/i18n/eo.json
languages/i18n/fa.json
languages/i18n/fi.json
languages/i18n/fur.json
languages/i18n/gl.json
languages/i18n/gu.json
languages/i18n/hak.json
languages/i18n/hi.json
languages/i18n/hr.json
languages/i18n/it.json
languages/i18n/ja.json
languages/i18n/jam.json
languages/i18n/ka.json
languages/i18n/ko.json
languages/i18n/lt.json
languages/i18n/lzh.json
languages/i18n/mk.json
languages/i18n/mn.json
languages/i18n/nl.json
languages/i18n/nn.json
languages/i18n/pl.json
languages/i18n/pt.json
languages/i18n/qqq.json
languages/i18n/ro.json
languages/i18n/ru.json
languages/i18n/sr-ec.json
languages/i18n/sr-el.json
languages/i18n/sv.json
languages/i18n/th.json
languages/i18n/tt-cyrl.json
languages/i18n/ur.json
languages/i18n/vo.json
languages/i18n/wuu.json
languages/i18n/zh-hans.json
languages/i18n/zh-hant.json
maintenance/Maintenance.php
maintenance/attachLatest.php
maintenance/benchmarks/bench_HTTP_HTTPS.php
maintenance/benchmarks/bench_Wikimedia_base_convert.php
maintenance/benchmarks/bench_delete_truncate.php
maintenance/benchmarks/bench_if_switch.php
maintenance/benchmarks/bench_strtr_str_replace.php
maintenance/benchmarks/bench_utf8_title_check.php
maintenance/benchmarks/bench_wfIsWindows.php
maintenance/benchmarks/benchmarkHooks.php
maintenance/benchmarks/benchmarkPurge.php
maintenance/changePassword.php
maintenance/checkBadRedirects.php
maintenance/checkComposerLockUpToDate.php
maintenance/checkImages.php
maintenance/checkLess.php
maintenance/checkSyntax.php
maintenance/checkUsernames.php
maintenance/cleanupAncientTables.php
maintenance/cleanupBlocks.php
maintenance/cleanupCaps.php
maintenance/cleanupImages.php
maintenance/cleanupRemovedModules.php
maintenance/cleanupSpam.php
maintenance/cleanupTitles.php
maintenance/cleanupUploadStash.php
maintenance/cleanupWatchlist.php
maintenance/clearInterwikiCache.php
maintenance/compareParserCache.php
maintenance/compareParsers.php
maintenance/convertExtensionToRegistration.php
maintenance/convertLinks.php
maintenance/convertUserOptions.php
maintenance/copyFileBackend.php
maintenance/copyJobQueue.php
maintenance/createAndPromote.php
maintenance/createCommonPasswordCdb.php
maintenance/deleteArchivedFiles.php
maintenance/deleteArchivedRevisions.php
maintenance/deleteBatch.php
maintenance/deleteDefaultMessages.php
maintenance/deleteEqualMessages.php
maintenance/deleteOldRevisions.php
maintenance/deleteOrphanedRevisions.php
maintenance/deleteRevision.php
maintenance/deleteSelfExternals.php
maintenance/dumpBackup.php
maintenance/dumpIterator.php
maintenance/dumpLinks.php
maintenance/dumpTextPass.php
maintenance/dumpUploads.php
maintenance/edit.php
maintenance/eraseArchivedFile.php
maintenance/exportSites.php
maintenance/fetchText.php
maintenance/fileOpPerfTest.php
maintenance/findDeprecated.php
maintenance/findHooks.php
maintenance/findMissingFiles.php
maintenance/findOrphanedFiles.php
maintenance/fixDefaultJsonContentPages.php
maintenance/fixDoubleRedirects.php
maintenance/fixExtLinksProtocolRelative.php
maintenance/fixTimestamps.php
maintenance/fixUserRegistration.php
maintenance/generateJsonI18n.php
maintenance/generateSitemap.php
maintenance/getConfiguration.php
maintenance/getLagTimes.php
maintenance/getSlaveServer.php
maintenance/getText.php
maintenance/importDump.php
maintenance/importSiteScripts.php
maintenance/importSites.php
maintenance/importTextFiles.php
maintenance/initEditCount.php
maintenance/initSiteStats.php
maintenance/jsparse.php
maintenance/lag.php
maintenance/language/alltrans.php
maintenance/language/date-formats.php
maintenance/language/digit2html.php
maintenance/language/dumpMessages.php
maintenance/language/generateNormalizerDataAr.php
maintenance/language/generateNormalizerDataMl.php
maintenance/language/generateUtf8Case.php
maintenance/language/langmemusage.php
maintenance/language/listVariants.php
maintenance/makeTestEdits.php
maintenance/mctest.php
maintenance/mergeMessageFileList.php
maintenance/migrateFileRepoLayout.php
maintenance/migrateUserGroup.php
maintenance/minify.php
maintenance/moveBatch.php
maintenance/mwdocgen.php
maintenance/namespaceDupes.php
maintenance/nukeNS.php
maintenance/nukePage.php
maintenance/oracle/alterSharedConstraints.php
maintenance/orphans.php
maintenance/pageExists.php
maintenance/parse.php
maintenance/patchSql.php
maintenance/populateBacklinkNamespace.php
maintenance/populateCategory.php
maintenance/populateContentModel.php
maintenance/populateFilearchiveSha1.php
maintenance/populateImageSha1.php
maintenance/populateLogSearch.php
maintenance/populateLogUsertext.php
maintenance/populateParentId.php
maintenance/populateRecentChangesSource.php
maintenance/populateRevisionLength.php
maintenance/populateRevisionSha1.php
maintenance/protect.php
maintenance/pruneFileCache.php
maintenance/purgeChangedFiles.php
maintenance/purgeChangedPages.php
maintenance/purgeList.php
maintenance/purgeOldText.php
maintenance/reassignEdits.php
maintenance/rebuildFileCache.php
maintenance/rebuildImages.php
maintenance/rebuildLocalisationCache.php
maintenance/rebuildSitesCache.php
maintenance/rebuildall.php
maintenance/rebuildmessages.php
maintenance/rebuildrecentchanges.php
maintenance/rebuildtextindex.php
maintenance/refreshFileHeaders.php
maintenance/refreshImageMetadata.php
maintenance/refreshLinks.php
maintenance/renderDump.php
maintenance/resetUserEmail.php [new file with mode: 0644]
maintenance/resetUserTokens.php
maintenance/rollbackEdits.php
maintenance/runBatchedQuery.php
maintenance/runJobs.php
maintenance/showJobs.php
maintenance/showSiteStats.php
maintenance/sql.php
maintenance/sqlite.php
maintenance/storage/compressOld.php
maintenance/storage/fixBug20757.php
maintenance/storage/orphanStats.php
maintenance/syncFileBackend.php
maintenance/undelete.php
maintenance/update.php
maintenance/updateArticleCount.php
maintenance/updateCollation.php
maintenance/updateDoubleWidthSearch.php
maintenance/updateRestrictions.php
maintenance/updateSearchIndex.php
maintenance/wrapOldPasswords.php
resources/src/mediawiki/mediawiki.js
tests/phpunit/includes/EditPageTest.php
tests/phpunit/includes/SanitizerTest.php
tests/phpunit/includes/api/ApiCreateAccountTest.php
tests/phpunit/includes/api/ApiLoginTest.php
tests/phpunit/includes/api/ApiTestCase.php
tests/phpunit/includes/context/RequestContextTest.php
tests/phpunit/includes/media/BitmapScalingTest.php
tests/phpunit/includes/session/CookieSessionProviderTest.php
tests/phpunit/includes/session/ImmutableSessionProviderWithCookieTest.php
tests/phpunit/includes/session/PHPSessionHandlerTest.php
tests/phpunit/includes/session/SessionBackendTest.php
tests/phpunit/includes/session/SessionManagerTest.php
tests/phpunit/includes/session/SessionTest.php
tests/phpunit/includes/session/TokenTest.php [new file with mode: 0644]
tests/phpunit/includes/session/UserInfoTest.php
tests/qunit/suites/resources/mediawiki/mediawiki.test.js

index 50d40a6..a79a7b2 100644 (file)
@@ -81,6 +81,8 @@ production.
    MediaWiki\Session\SessionProvider.
 ** The User cannot be loaded from session until after Setup.php completes.
    Attempts to do so will be ignored and the User will remain unloaded.
+** CSRF tokens may be fetched from the MediaWiki\Session\Session, which uses
+   the MediaWiki\Session\Token class.
 * MediaWiki will now auto-create users as necessary, removing the need for
   extensions to do so. An 'autocreateaccount' right is added to allow
   auto-creation when 'createaccount' is not granted to all users.
@@ -88,11 +90,15 @@ production.
 * Most cookie-handling methods in User are deprecated.
 * $wgAllowAsyncCopyUploads and $CopyUploadAsyncTimeout were removed. This was an
   experimental feature that has never worked.
+* Login and createaccount tokens now vary by timestamp.
+* LoginForm::getLoginToken() and LoginForm::getCreateaccountToken()
+  return a MediaWiki\Session\Token, and tokens must be checked using that
+  class's methods.
+* $wgEnotifUseJobQ was removed and the job queue is always used.
 
 === New features in 1.27 ===
-* $wgDataCenterId and $wgDataCenterRoles where added, which will serve as
-  basic configuration settings needed for multi-datacenter setups.
-  $wgDataCenterUpdateStickTTL was also added.
+* $wgDataCenterUpdateStickTTL was also added. This decides how long a user
+  sticks to the primary DC (via cookies) after they make changes to the site.
 * Added a new hook, 'UserMailerTransformContent', to transform the contents
   of an email. This is similar to the EmailUser hook but applies to all mail
   sent via UserMailer.
@@ -146,6 +152,10 @@ production.
 * Added MWRestrictions as a class to check restrictions on a WebRequest, e.g.
   to assert that the request comes from a particular IP range.
 * Added bot passwords, a rights-restricted login mechanism for API-using bots.
+* Whitelisted the following HTML attributes for all elements in wikitext:
+  aria-describedby, aria-flowto, aria-label, aria-labelledby, aria-owns.
+* Removed "presentation" restriction on the HTML role attribute in wikitext.
+  All values are now allowed for the role attribute.
 
 === External library changes in 1.27 ===
 
@@ -199,6 +209,7 @@ production.
 * ApiQueryBase::getDirectionDescription() was removed (deprecated since 1.25).
 * ApiQuery::getModules() was removed (deprecated since 1.21).
 * ApiMain::getModules() was removed (deprecated since 1.21).
+* ApiBase::getVersion() was removed (deprecated since 1.21).
 
 === Languages updated in 1.27 ===
 
@@ -294,6 +305,8 @@ changes to languages because of Phabricator reports.
   together but instead pick the final one, similar to image syntax.
 * XML-like parser tags (such as <gallery>), when unclosed, will be left unparsed
   rather than consume everything until the end of the page.
+* New maintenance script resetUserEmail.php allows sysadmins to reset user emails in case
+  a user forgot password/account was stolen.
 
 == Compatibility ==
 
index 2f23924..685b5c1 100644 (file)
@@ -721,6 +721,7 @@ $wgAutoloadLocalClasses = array(
        'LogFormatter' => __DIR__ . '/includes/logging/LogFormatter.php',
        'LogPage' => __DIR__ . '/includes/logging/LogPage.php',
        'LogPager' => __DIR__ . '/includes/logging/LogPager.php',
+       'LoggedOutEditToken' => __DIR__ . '/includes/user/LoggedOutEditToken.php',
        'LoggedUpdateMaintenance' => __DIR__ . '/maintenance/Maintenance.php',
        'LoginForm' => __DIR__ . '/includes/specials/SpecialUserlogin.php',
        'LonelyPagesPage' => __DIR__ . '/includes/specials/SpecialLonelypages.php',
@@ -797,6 +798,7 @@ $wgAutoloadLocalClasses = array(
        'MediaWiki\\Session\\SessionManagerInterface' => __DIR__ . '/includes/session/SessionManagerInterface.php',
        'MediaWiki\\Session\\SessionProvider' => __DIR__ . '/includes/session/SessionProvider.php',
        'MediaWiki\\Session\\SessionProviderInterface' => __DIR__ . '/includes/session/SessionProviderInterface.php',
+       'MediaWiki\\Session\\Token' => __DIR__ . '/includes/session/Token.php',
        'MediaWiki\\Session\\UserInfo' => __DIR__ . '/includes/session/UserInfo.php',
        'MediaWiki\\Site\\MediaWikiPageNameNormalizer' => __DIR__ . '/includes/site/MediaWikiPageNameNormalizer.php',
        'MediaWiki\\Tidy\\Html5Depurate' => __DIR__ . '/includes/tidy/Html5Depurate.php',
@@ -1048,6 +1050,7 @@ $wgAutoloadLocalClasses = array(
        'ReplicatedBagOStuff' => __DIR__ . '/includes/libs/objectcache/ReplicatedBagOStuff.php',
        'RepoGroup' => __DIR__ . '/includes/filerepo/RepoGroup.php',
        'RequestContext' => __DIR__ . '/includes/context/RequestContext.php',
+       'ResetUserEmail' => __DIR__ . '/maintenance/resetUserEmail.php',
        'ResetUserTokens' => __DIR__ . '/maintenance/resetUserTokens.php',
        'ResourceFileCache' => __DIR__ . '/includes/cache/ResourceFileCache.php',
        'ResourceLoader' => __DIR__ . '/includes/resourceloader/ResourceLoader.php',
index 495e659..b8ec76b 100644 (file)
@@ -33,4 +33,4 @@ Currently there are a few different types of jobs:
     Each job clears $wgUpdateRowsPerJob pages (500 by default).
 
   enotifNotify
-    Used when $wgEnotifUseJobQ is true to send mail using the job queue.
+    Used to send mail using the job queue.
index 2b5e1e0..bc03714 100644 (file)
@@ -513,7 +513,8 @@ sites statistics information.
 'ApiQueryTokensRegisterTypes': Use this hook to add additional token types to
 action=query&meta=tokens. Note that most modules will probably be able to use
 the 'csrf' token instead of creating their own token types.
-&$salts: array( type => salt to pass to User::getEditToken() )
+&$salts: array( type => salt to pass to User::getEditToken() or array of salt
+  and key to pass to Session::getToken() )
 
 'APIQueryUsersTokens': DEPRECATED! Use ApiQueryTokensRegisterTypes instead.
 Use this hook to add custom token to list=users. Every token has an action,
@@ -2346,6 +2347,11 @@ run. Use when page save hooks require the presence of custom tables to ensure
 that tests continue to run properly.
 &$tables: array of table names
 
+'ParserOutputStashForEdit': Called when an edit stash parse finishes, before the output is cached.
+$page: the WikiPage of the candidate edit
+$content: the Content object of the candidate edit
+$output: the ParserOutput result of the candidate edit
+
 'PasswordPoliciesForUser': Alter the effective password policy for a user.
 $user: User object whose policy you are modifying
 &$effectivePolicy: Array of policy statements that apply to this user
index 00a5709..c892629 100644 (file)
@@ -943,6 +943,12 @@ $wgUseImageMagick = false;
  */
 $wgImageMagickConvertCommand = '/usr/bin/convert';
 
+/**
+ * Array of max pixel areas for interlacing per MIME type
+ * @since 1.27
+ */
+$wgMaxInterlacingAreas = array();
+
 /**
  * Sharpening parameter to ImageMagick
  */
@@ -1622,12 +1628,6 @@ $wgEnotifImpersonal = false;
  */
 $wgEnotifMaxRecips = 500;
 
-/**
- * Send mails via the job queue. This can be useful to reduce the time it
- * takes to save a page that a lot of people are watching.
- */
-$wgEnotifUseJobQ = false;
-
 /**
  * Use real name instead of username in e-mail "from" field.
  */
@@ -1865,24 +1865,6 @@ $wgDBservers = false;
  */
 $wgLBFactoryConf = array( 'class' => 'LBFactorySimple' );
 
-/**
- * The ID of the current data center
- * @since 1.27
- */
-$wgDataCenterId = 'default';
-
-/**
- * Map of data center IDs to their role ("master" or "slave")
- *
- * Multiple data centers can be setup to handle MediaWiki, with HTTP
- * POSTs routed to the master data center and GET/HEAD/OPTION routed to
- * any data center (usually the closest to the end user). In such setups,
- * this setting should be set to the appropriate value in the site
- * config for each data center.
- * @since 1.27
- */
-$wgDataCenterRoles = array( 'default' => 'master' );
-
 /**
  * After a state-changing request is done by a client, this determines
  * how many seconds that client should keep using the master datacenter.
@@ -7684,7 +7666,6 @@ $wgHTTPConnectTimeout = 5e0;
 
 /************************************************************************//**
  * @name   Job queue
- * See also $wgEnotifUseJobQ.
  * @{
  */
 
index 47912cb..277a6cc 100644 (file)
@@ -3457,6 +3457,9 @@ HTML
                global $wgOut;
 
                if ( Hooks::run( 'EditPageBeforeConflictDiff', array( &$this, &$wgOut ) ) ) {
+                       $stats = $wgOut->getContext()->getStats();
+                       $stats->increment( 'edit.failures.conflict' );
+
                        $wgOut->wrapWikiMsg( '<h2>$1</h2>', "yourdiff" );
 
                        $content1 = $this->toEditContent( $this->textbox1 );
index 6342d71..8385a06 100644 (file)
@@ -551,21 +551,12 @@ class MediaWiki {
                $config = $context->getConfig();
 
                $factory = wfGetLBFactory();
-               // Check if any transaction was too big
-               $limit = $config->get( 'MaxUserDBWriteDuration' );
-               $factory->forEachLB( function ( LoadBalancer $lb ) use ( $limit ) {
-                       $lb->forEachOpenConnection( function ( IDatabase $db ) use ( $limit ) {
-                               $time = $db->pendingWriteQueryDuration();
-                               if ( $limit > 0 && $time > $limit ) {
-                                       throw new DBTransactionError(
-                                               $db,
-                                               wfMessage( 'transaction-duration-limit-exceeded', $time, $limit )->text()
-                                       );
-                               }
-                       } );
-               } );
                // Commit all changes
-               $factory->commitMasterChanges( __METHOD__ );
+               $factory->commitMasterChanges(
+                       __METHOD__,
+                       // Abort if any transaction was too big
+                       array( 'maxWriteDuration' => $config->get( 'MaxUserDBWriteDuration' ) )
+               );
                // Record ChronologyProtector positions
                $factory->shutdown();
                wfDebug( __METHOD__ . ': all transactions committed' );
index d41e559..60c9498 100644 (file)
@@ -721,7 +721,7 @@ class Sanitizer {
         * Take an array of attribute names and values and normalize or discard
         * illegal values for the given whitelist.
         *
-        * - Discards attributes not the given whitelist
+        * - Discards attributes not on the given whitelist
         * - Unsafe style attributes are discarded
         * - Invalid id attributes are re-encoded
         *
@@ -770,18 +770,18 @@ class Sanitizer {
                                $value = Sanitizer::checkCss( $value );
                        }
 
+                       # Escape HTML id attributes
                        if ( $attribute === 'id' ) {
                                $value = Sanitizer::escapeId( $value, 'noninitial' );
                        }
 
-                       # WAI-ARIA
-                       # http://www.w3.org/TR/wai-aria/
-                       # http://www.whatwg.org/html/elements.html#wai-aria
-                       # For now we only support role="presentation" until we work out what roles should be
-                       # usable by content and we ensure that our code explicitly rejects patterns that
-                       # violate HTML5's ARIA restrictions.
-                       if ( $attribute === 'role' && $value !== 'presentation' ) {
-                               continue;
+                       # Escape HTML id reference lists
+                       if ( $attribute === 'aria-describedby'
+                               || $attribute === 'aria-flowto'
+                               || $attribute === 'aria-labelledby'
+                               || $attribute === 'aria-owns'
+                       ) {
+                               $value = Sanitizer::escapeIdReferenceList( $value, 'noninitial' );
                        }
 
                        // RDFa and microdata properties allow URLs, URIs and/or CURIs.
@@ -1163,6 +1163,39 @@ class Sanitizer {
                return $id;
        }
 
+       /**
+        * Given a string containing a space delimited list of ids, escape each id
+        * to match ids escaped by the escapeId() function.
+        *
+        * @since 1.27
+        *
+        * @param string $referenceString Space delimited list of ids
+        * @param string|array $options String or array of strings (default is array()):
+        *   'noninitial': This is a non-initial fragment of an id, not a full id,
+        *       so don't pay attention if the first character isn't valid at the
+        *       beginning of an id.  Only matters if $wgExperimentalHtmlIds is
+        *       false.
+        *   'legacy': Behave the way the old HTML 4-based ID escaping worked even
+        *       if $wgExperimentalHtmlIds is used, so we can generate extra
+        *       anchors and links won't break.
+        * @return string
+        */
+       static function escapeIdReferenceList( $referenceString, $options = array() ) {
+               # Explode the space delimited list string into an array of tokens
+               $references = preg_split( '/\s+/', "{$referenceString}", -1, PREG_SPLIT_NO_EMPTY );
+
+               # Escape each token as an id
+               foreach ( $references as &$ref ) {
+                       $ref = Sanitizer::escapeId( $ref, $options );
+               }
+
+               # Merge the array back to a space delimited list string
+               # If the array is empty, the result will be an empty string ('')
+               $referenceString = implode( ' ', $references );
+
+               return $referenceString;
+       }
+
        /**
         * Given a value, escape it so that it can be used as a CSS class and
         * return it.
@@ -1208,7 +1241,7 @@ class Sanitizer {
 
        /**
         * Return an associative array of attribute names and values from
-        * a partial tag string. Attribute names are forces to lowercase,
+        * a partial tag string. Attribute names are forced to lowercase,
         * character references are decoded to UTF-8 text.
         *
         * @param string $text
@@ -1546,6 +1579,11 @@ class Sanitizer {
                        'title',
 
                        # WAI-ARIA
+                       'aria-describedby',
+                       'aria-flowto',
+                       'aria-label',
+                       'aria-labelledby',
+                       'aria-owns',
                        'role',
                );
 
index 9bf05e0..6c85638 100644 (file)
@@ -357,7 +357,6 @@ if ( $wgEnableEmail ) {
        $wgEnotifMaxRecips = 0;
        $wgEnotifMinorEdits = false;
        $wgEnotifRevealEditorAddress = false;
-       $wgEnotifUseJobQ = false;
        $wgEnotifUseRealName = false;
        $wgEnotifUserTalk = false;
        $wgEnotifWatchlist = false;
@@ -505,6 +504,7 @@ if ( !$wgSessionsInObjectCache && !$wgSessionsInMemcached ) {
        }
        $cacheType = get_class( ObjectCache::getInstance( $wgSessionCacheType ) );
        wfDebugLog(
+               'caches',
                "Session data will be stored in \"$cacheType\" cache with " .
                        "expiry $wgObjectCacheSessionExpiry seconds"
        );
index e549037..882b7dd 100644 (file)
@@ -246,7 +246,7 @@ class Title {
         * Create a new Title from text, such as what one would find in a link. De-
         * codes any HTML entities in the text.
         *
-        * @param string|null $text The link text; spaces, prefixes, and an
+        * @param string|int|null $text The link text; spaces, prefixes, and an
         *   initial ':' indicating the main namespace are accepted.
         * @param int $defaultNamespace The namespace to use if none is specified
         *   by a prefix.  If you want to force a specific namespace even if
@@ -259,7 +259,8 @@ class Title {
                if ( is_object( $text ) ) {
                        throw new InvalidArgumentException( '$text must be a string.' );
                }
-               if ( $text !== null && !is_string( $text ) ) {
+               // DWIM: Integers can be passed in here when page titles are used as array keys.
+               if ( $text !== null && !is_string( $text ) && !is_int( $text ) ) {
                        wfDebugLog( 'T76305', wfGetAllCallers( 5 ) );
                        return null;
                }
@@ -268,7 +269,7 @@ class Title {
                }
 
                try {
-                       return Title::newFromTextThrow( $text, $defaultNamespace );
+                       return Title::newFromTextThrow( strval( $text ), $defaultNamespace );
                } catch ( MalformedTitleException $ex ) {
                        return null;
                }
index 0ef2373..49aca0c 100644 (file)
  */
 class WatchedItem {
        /** @var Title */
-       public $mTitle;
+       private $mTitle;
 
        /** @var User */
-       public $mUser;
+       private $mUser;
 
        /** @var int */
-       public $mCheckRights;
+       private $mCheckRights;
 
        /** @var bool */
        private $loaded = false;
@@ -59,17 +59,6 @@ class WatchedItem {
         */
        const CHECK_USER_RIGHTS = 1;
 
-       /**
-        * Do DB master updates right now
-        * @since 1.26
-        */
-       const IMMEDIATE = 0;
-       /**
-        * Do DB master updates via the job queue
-        * @since 1.26
-        */
-       const DEFERRED = 1;
-
        /**
         * Create a WatchedItem object with the given user and title
         * @since 1.22 $checkRights parameter added
@@ -219,10 +208,9 @@ class WatchedItem {
         * @param bool $force Whether to force the write query to be executed even if the
         *    page is not watched or the notification timestamp is already NULL.
         * @param int $oldid The revision id being viewed. If not given or 0, latest revision is assumed.
-        * @mode int $mode WatchedItem::DEFERRED/IMMEDIATE
         */
        public function resetNotificationTimestamp(
-               $force = '', $oldid = 0, $mode = self::IMMEDIATE
+               $force = '', $oldid = 0
        ) {
                // Only loggedin user can have a watchlist
                if ( wfReadOnly() || $this->mUser->isAnon() || !$this->isAllowed( 'editmywatchlist' ) ) {
@@ -273,28 +261,19 @@ class WatchedItem {
                }
 
                // If the page is watched by the user (or may be watched), update the timestamp
-               if ( $mode === self::DEFERRED ) {
-                       $job = new ActivityUpdateJob(
-                               $title,
-                               array(
-                                       'type'      => 'updateWatchlistNotification',
-                                       'userid'    => $this->getUserId(),
-                                       'notifTime' => $notificationTimestamp,
-                                       'curTime'   => time()
-                               )
-                       );
-                       // Try to run this post-send
-                       DeferredUpdates::addCallableUpdate( function() use ( $job ) {
-                               $job->run();
-                       } );
-               } else {
-                       $dbw = wfGetDB( DB_MASTER );
-                       $dbw->update( 'watchlist',
-                               array( 'wl_notificationtimestamp' => $dbw->timestampOrNull( $notificationTimestamp ) ),
-                               $this->dbCond(),
-                               __METHOD__
-                       );
-               }
+               $job = new ActivityUpdateJob(
+                       $title,
+                       array(
+                               'type'      => 'updateWatchlistNotification',
+                               'userid'    => $this->getUserId(),
+                               'notifTime' => $notificationTimestamp,
+                               'curTime'   => time()
+                       )
+               );
+               // Try to run this post-send
+               DeferredUpdates::addCallableUpdate( function() use ( $job ) {
+                       $job->run();
+               } );
 
                $this->timestamp = null;
        }
index 13d13a6..02720c0 100644 (file)
@@ -1260,11 +1260,10 @@ abstract class ApiBase extends ContextSource {
                        );
                }
 
-               if ( $this->getUser()->matchEditToken(
-                       $token,
-                       $salts[$tokenType],
-                       $this->getRequest()
-               ) ) {
+               $tokenObj = ApiQueryTokens::getToken(
+                       $this->getUser(), $this->getRequest()->getSession(), $salts[$tokenType]
+               );
+               if ( $tokenObj->match( $token ) ) {
                        return true;
                }
 
@@ -2523,19 +2522,6 @@ abstract class ApiBase extends ContextSource {
        /// @deprecated since 1.24
        const PROP_NULLABLE = 1;
 
-       /**
-        * Formerly returned a string that identifies the version of the extending
-        * class. Typically included the class name, the svn revision, timestamp,
-        * and last author. Usually done with SVN's Id keyword
-        *
-        * @deprecated since 1.21, version string is no longer supported
-        * @return string
-        */
-       public function getVersion() {
-               wfDeprecated( __METHOD__, '1.21' );
-               return '';
-       }
-
        /**
         * Formerly used to fetch a list of possible properites in the result,
         * somehow organized with respect to the prop parameter that causes them to
index 28c6ece..dfcbaf8 100644 (file)
@@ -32,21 +32,22 @@ class ApiCheckToken extends ApiBase {
                $params = $this->extractRequestParams();
                $token = $params['token'];
                $maxage = $params['maxtokenage'];
-               $request = $this->getRequest();
                $salts = ApiQueryTokens::getTokenTypeSalts();
-               $salt = $salts[$params['type']];
 
                $res = array();
 
-               if ( $this->getUser()->matchEditToken( $token, $salt, $request, $maxage ) ) {
+               $tokenObj = ApiQueryTokens::getToken(
+                       $this->getUser(), $this->getRequest()->getSession(), $salts[$params['type']]
+               );
+               if ( $tokenObj->match( $token, $maxage ) ) {
                        $res['result'] = 'valid';
-               } elseif ( $maxage !== null && $this->getUser()->matchEditToken( $token, $salt, $request ) ) {
+               } elseif ( $maxage !== null && $tokenObj->match( $token ) ) {
                        $res['result'] = 'expired';
                } else {
                        $res['result'] = 'invalid';
                }
 
-               $ts = User::getEditTokenTimestamp( $token );
+               $ts = MediaWiki\Session\Token::getTimestamp( $token );
                if ( $ts !== null ) {
                        $mwts = new MWTimestamp();
                        $mwts->timestamp->setTimestamp( $ts );
index a044be2..d6baf34 100644 (file)
@@ -149,8 +149,11 @@ class ApiCreateAccount extends ApiBase {
                        // Token was incorrect, so add it to result, but don't throw an exception
                        // since not having the correct token is part of the normal
                        // flow of events.
-                       $result['token'] = LoginForm::getCreateaccountToken();
+                       $result['token'] = LoginForm::getCreateaccountToken()->toString();
                        $result['result'] = 'NeedToken';
+                       $this->setWarning( 'Fetching a token via action=createaccount is deprecated. ' .
+                               'Use action=query&meta=tokens&type=createaccount instead.' );
+                       $this->logFeatureUsage( 'action=createaccount&!token' );
                } elseif ( !$status->isOK() ) {
                        // There was an error. Die now.
                        $this->dieStatus( $status );
@@ -200,7 +203,11 @@ class ApiCreateAccount extends ApiBase {
                                ApiBase::PARAM_TYPE => 'password',
                        ),
                        'domain' => null,
-                       'token' => null,
+                       'token' => array(
+                               ApiBase::PARAM_TYPE => 'string',
+                               ApiBase::PARAM_REQUIRED => false, // for BC
+                               ApiBase::PARAM_HELP_MSG => array( 'api-help-param-token', 'createaccount' ),
+                       ),
                        'email' => array(
                                ApiBase::PARAM_TYPE => 'string',
                                ApiBase::PARAM_REQUIRED => $this->getConfig()->get( 'EmailConfirmToEdit' ),
index 860e3b2..03cd666 100644 (file)
@@ -84,12 +84,9 @@ class ApiLogin extends ApiBase {
 
                // Check login token
                $token = LoginForm::getLoginToken();
-               if ( !$token ) {
-                       LoginForm::setLoginToken();
+               if ( $token->wasNew() || !$params['token'] ) {
                        $authRes = LoginForm::NEED_TOKEN;
-               } elseif ( !$params['token'] ) {
-                       $authRes = LoginForm::NEED_TOKEN;
-               } elseif ( $token !== $params['token'] ) {
+               } elseif ( !$token->match( $params['token'] ) ) {
                        $authRes = LoginForm::WRONG_TOKEN;
                }
 
@@ -159,7 +156,10 @@ class ApiLogin extends ApiBase {
 
                        case LoginForm::NEED_TOKEN:
                                $result['result'] = 'NeedToken';
-                               $result['token'] = LoginForm::getLoginToken();
+                               $result['token'] = LoginForm::getLoginToken()->toString();
+                               $this->setWarning( 'Fetching a token via action=login is deprecated. ' .
+                                  'Use action=query&meta=tokens&type=login instead.' );
+                               $this->logFeatureUsage( 'action=login&!lgtoken' );
 
                                // @todo: See above about deprecation
                                $result['cookieprefix'] = $this->getConfig()->get( 'CookiePrefix' );
@@ -254,7 +254,11 @@ class ApiLogin extends ApiBase {
                                ApiBase::PARAM_TYPE => 'password',
                        ),
                        'domain' => null,
-                       'token' => null,
+                       'token' => array(
+                               ApiBase::PARAM_TYPE => 'string',
+                               ApiBase::PARAM_REQUIRED => false, // for BC
+                               ApiBase::PARAM_HELP_MSG => array( 'api-help-param-token', 'login' ),
+                       ),
                );
        }
 
index 6ddc28a..458fd18 100644 (file)
@@ -1231,7 +1231,8 @@ class ApiMain extends ApiBase {
         * @param array $params An array with the request parameters
         */
        protected function setupExternalResponse( $module, $params ) {
-               if ( !$this->getRequest()->wasPosted() && $module->mustBePosted() ) {
+               $request = $this->getRequest();
+               if ( !$request->wasPosted() && $module->mustBePosted() ) {
                        // Module requires POST. GET request might still be allowed
                        // if $wgDebugApi is true, otherwise fail.
                        $this->dieUsageMsgOrDebug( array( 'mustbeposted', $this->mAction ) );
@@ -1243,6 +1244,15 @@ class ApiMain extends ApiBase {
                        // Create an appropriate printer
                        $this->mPrinter = $this->createPrinterByName( $params['format'] );
                }
+
+               if ( $request->getProtocol() === 'http' && (
+                       $request->getSession()->shouldForceHTTPS() ||
+                       ( $this->getUser()->isLoggedIn() &&
+                               $this->getUser()->requiresHTTPS() )
+               ) ) {
+                       $this->logFeatureUsage( 'https-expected' );
+                       $this->setWarning( 'HTTP used when HTTPS was expected' );
+               }
        }
 
        /**
index ca9ceca..196c1fa 100644 (file)
@@ -184,11 +184,6 @@ class ApiQuerySiteinfo extends ApiQueryBase {
                        $data['git-hash'] = $git;
                        $data['git-branch'] =
                                SpecialVersion::getGitCurrentBranch( $GLOBALS['IP'] );
-               } else {
-                       $svn = SpecialVersion::getSvnRevision( $IP );
-                       if ( $svn ) {
-                               $data['rev'] = $svn;
-                       }
                }
 
                // 'case-insensitive' option is reserved for future
@@ -602,11 +597,6 @@ class ApiQuerySiteinfo extends ApiQueryBase {
                                }
                                if ( isset( $ext['version'] ) ) {
                                        $ret['version'] = $ext['version'];
-                               } elseif ( isset( $ext['svn-revision'] ) &&
-                                       preg_match( '/\$(?:Rev|LastChangedRevision|Revision): *(\d+)/',
-                                               $ext['svn-revision'], $m )
-                               ) {
-                                       $ret['version'] = 'r' . $m[1];
                                }
                                if ( isset( $ext['path'] ) ) {
                                        $extensionPath = dirname( $ext['path'] );
@@ -620,13 +610,6 @@ class ApiQuerySiteinfo extends ApiQueryBase {
                                                if ( $vcsDate !== false ) {
                                                        $ret['vcs-date'] = wfTimestamp( TS_ISO_8601, $vcsDate );
                                                }
-                                       } else {
-                                               $svnInfo = SpecialVersion::getSvnInfo( $extensionPath );
-                                               if ( $svnInfo !== false ) {
-                                                       $ret['vcs-system'] = 'svn';
-                                                       $ret['vcs-version'] = $svnInfo['checkout-rev'];
-                                                       $ret['vcs-url'] = isset( $svnInfo['viewvc-url'] ) ? $svnInfo['viewvc-url'] : '';
-                                               }
                                        }
 
                                        if ( SpecialVersion::getExtLicenseFileName( $extensionPath ) ) {
index f887664..3f3464b 100644 (file)
@@ -44,16 +44,24 @@ class ApiQueryTokens extends ApiQueryBase {
                        return;
                }
 
+               $user = $this->getUser();
+               $session = $this->getRequest()->getSession();
                $salts = self::getTokenTypeSalts();
                foreach ( $params['type'] as $type ) {
-                       $salt = $salts[$type];
-                       $val = $this->getUser()->getEditToken( $salt, $this->getRequest() );
-                       $res[$type . 'token'] = $val;
+                       $res[$type . 'token'] = self::getToken( $user, $session, $salts[$type] )->toString();
                }
 
                $this->getResult()->addValue( 'query', $this->getModuleName(), $res );
        }
 
+       /**
+        * Get the salts for known token types
+        * @return (string|array)[] Returning a string will use that as the salt
+        *  for User::getEditTokenObject() to fetch the token, which will give a
+        *  LoggedOutEditToken (always "+\\") for anonymous users. Returning an
+        *  array will use it as parameters to MediaWiki\\Session\\Session::getToken(),
+        *  which will always return a full token even for anonymous users.
+        */
        public static function getTokenTypeSalts() {
                static $salts = null;
                if ( !$salts ) {
@@ -63,6 +71,8 @@ class ApiQueryTokens extends ApiQueryBase {
                                'patrol' => 'patrol',
                                'rollback' => 'rollback',
                                'userrights' => 'userrights',
+                               'login' => array( '', 'login' ),
+                               'createaccount' => array( '', 'createaccount' ),
                        );
                        Hooks::run( 'ApiQueryTokensRegisterTypes', array( &$salts ) );
                        ksort( $salts );
@@ -71,6 +81,27 @@ class ApiQueryTokens extends ApiQueryBase {
                return $salts;
        }
 
+       /**
+        * Get a token from a salt
+        * @param User $user
+        * @param MediaWiki\\Session\\Session $session
+        * @param string|array $salt A string will be used as the salt for
+        *  User::getEditTokenObject() to fetch the token, which will give a
+        *  LoggedOutEditToken (always "+\\") for anonymous users. An array will
+        *  be used as parameters to MediaWiki\\Session\\Session::getToken(), which
+        *  will always return a full token even for anonymous users. An array will
+        *  also persist the session.
+        * @return MediaWiki\\Session\\Token
+        */
+       public static function getToken( User $user, MediaWiki\Session\Session $session, $salt ) {
+               if ( is_array( $salt ) ) {
+                       $session->persist();
+                       return call_user_func_array( array( $session, 'getToken' ), $salt );
+               } else {
+                       return $user->getEditTokenObject( $salt, $session->getRequest() );
+               }
+       }
+
        public function getAllowedParams() {
                return array(
                        'type' => array(
@@ -90,6 +121,11 @@ class ApiQueryTokens extends ApiQueryBase {
                );
        }
 
+       public function isReadMode() {
+               // So login tokens can be fetched on private wikis
+               return false;
+       }
+
        public function getCacheMode( $params ) {
                return 'private';
        }
index 8822750..00675f4 100644 (file)
@@ -141,6 +141,9 @@ class ApiStashEdit extends ApiBase {
                if ( $editInfo && $editInfo->output ) {
                        $key = self::getStashKey( $page->getTitle(), $content, $user );
 
+                       // Let extensions add ParserOutput metadata or warm other caches
+                       Hooks::run( 'ParserOutputStashForEdit', array( $page, $content, $editInfo->output ) );
+
                        list( $stashInfo, $ttl ) = self::buildStashValue(
                                $editInfo->pstContent, $editInfo->output, $editInfo->timestamp
                        );
@@ -148,6 +151,7 @@ class ApiStashEdit extends ApiBase {
                        if ( $stashInfo ) {
                                $ok = $cache->set( $key, $stashInfo, $ttl );
                                if ( $ok ) {
+
                                        $logger->debug( "Cached parser output for key '$key'." );
                                        return self::ERROR_NONE;
                                } else {
index f92526d..c10c938 100644 (file)
@@ -81,7 +81,7 @@ class ApiTokens extends ApiBase {
                foreach ( ApiQueryTokens::getTokenTypeSalts() as $name => $salt ) {
                        if ( !isset( $types[$name] ) ) {
                                $types[$name] = function () use ( $salt, $user, $request ) {
-                                       return $user->getEditToken( $salt, $request );
+                                       return ApiQueryTokens::getToken( $user, $request->getSession(), $salt )->toString();
                                };
                        }
                }
index 037e381..1680544 100644 (file)
        "apihelp-query+links-param-dir": "Die Auflistungsrichtung.",
        "apihelp-query+links-example-simple": "Links von der <kbd>Hauptseite</kbd> abrufen",
        "apihelp-query+linkshere-description": "Alle Seiten finden, die auf die angegebenen Seiten verlinken.",
+       "apihelp-query+linkshere-paramvalue-prop-pageid": "Die Seitenkennung jeder Seite.",
        "apihelp-query+logevents-description": "Ereignisse von den Logbüchern abrufen.",
        "apihelp-query+logevents-example-simple": "Listet die letzten Logbuch-Ereignisse auf.",
        "apihelp-query+pageswithprop-paramvalue-prop-ids": "Fügt die Seitenkennung hinzu.",
index 7c54805..01cc1f7 100644 (file)
        "apihelp-query+info-paramvalue-prop-talkid": "L’ID de la page de discussion de chaque page qui n’est pas de discussion.",
        "apihelp-query+info-paramvalue-prop-watched": "Lister l’état de suivi de chaque page.",
        "apihelp-query+info-paramvalue-prop-watchers": "Le nombre d’observateurs, si c’est autorisé.",
+       "apihelp-query+info-paramvalue-prop-visitingwatchers": "Le nombre de personnes suivant chaque page qui ont regardé les modifications récentes de cette page, si c’est autorisé.",
        "apihelp-query+info-paramvalue-prop-notificationtimestamp": "L’horodatage de notification de la liste de suivi de chaque page.",
        "apihelp-query+info-paramvalue-prop-subjectid": "L’ID de page de la page parent de chaque page de discussion.",
        "apihelp-query+info-paramvalue-prop-url": "Fournit une URL complète, une URL de modification, et l’URL canonique de chaque page.",
index 7651551..bb8a074 100644 (file)
        "apihelp-query+info-paramvalue-prop-talkid": "מזהה הדף של דף השיחה עבור כל דף שאינו דף שיחה.",
        "apihelp-query+info-paramvalue-prop-watched": "לרשום את מצב המעקב של כל דף.",
        "apihelp-query+info-paramvalue-prop-watchers": "מספר העוקבים, אם קיבלת הרשאה.",
+       "apihelp-query+info-paramvalue-prop-visitingwatchers": "מספר העוקבים אחרי כל דף שביקרו עריכות אחרונות לאותו הדף, אם זה מותר.",
        "apihelp-query+info-paramvalue-prop-notificationtimestamp": "חותם־זמן של הודעת רשימת מעקב של כל דף.",
        "apihelp-query+info-paramvalue-prop-subjectid": "מזהה הדף של הדף העיקרי של כל דף שיחה.",
        "apihelp-query+info-paramvalue-prop-url": "נותן URL מלא, URL לעריכה ו־URL קנוני לכל דף.",
index 5730655..dd3c80c 100644 (file)
        "apihelp-query+imageusage-description": "Trova tutte le pagine che utilizzano il titolo dell'immagine specificato.",
        "apihelp-query+imageusage-param-dir": "La direzione in cui elencare.",
        "apihelp-query+imageusage-param-redirect": "Se la pagina collegata è un redirect, trova tutte le pagine che puntano al redirect. Il limite massimo è dimezzato.",
+       "apihelp-query+info-paramvalue-prop-visitingwatchers": "Il numero di osservatori di ogni pagina che hanno visitato le ultime modifiche alla pagina, se consentito.",
        "apihelp-query+iwbacklinks-param-prop": "Quali proprietà ottenere:",
        "apihelp-query+iwbacklinks-paramvalue-prop-iwtitle": "Aggiunge il titolo dell'interwiki.",
        "apihelp-query+iwbacklinks-param-dir": "La direzione in cui elencare.",
index c6b08c1..f7468b4 100644 (file)
        "apihelp-query+info-paramvalue-prop-talkid": "De Kännong för de Klaafsigg för jehde Nit-Klaafsigg.",
        "apihelp-query+info-paramvalue-prop-watched": "Donn der Zohschtand vum Oppaße för jehde Sigg opleßte.",
        "apihelp-query+info-paramvalue-prop-watchers": "De Aanzahl Oppaßer, wann zohjelohße.",
+       "apihelp-query+info-paramvalue-prop-visitingwatchers": "De Aanzahl Oppaßer pro Sigg, di woh zohjelohße, de neußte Änderonge aan dä Sigg belohrt hann.",
        "apihelp-query+info-paramvalue-prop-subjectid": "De Kännong för de övverje'odente Sigg för jehde Klaafsigg.",
        "apihelp-query+info-paramvalue-prop-url": "Jidd en kumplätte <i lang=\"en\" xml:lang=\"en\" dir=\"ltr\" title=\"Uniform Ressource Locator\">URL</i>, en <i lang=\"en\" xml:lang=\"en\" dir=\"ltr\" title=\"Uniform Ressource Locator\">URL</i> för et Beärbeide, un en kannohnesche <i lang=\"en\" xml:lang=\"en\" dir=\"ltr\" title=\"Uniform Ressource Locator\">URL</i> för jehde Sigg uß.",
        "apihelp-query+info-paramvalue-prop-readable": "Ov dä Metmaacher heh di Sigg lässe kann.",
        "apihelp-upload-param-url": "Der <i lang=\"en\" xml:lang=\"en\" dir=\"ltr\" title=\"Uniform Ressource Locator\">URL</i>, öm di Dattei dervun ze holle.",
        "apihelp-upload-param-sessionkey": "Et sälve wi „<code lang=\"en\" xml:lang=\"en\" dir=\"ltr\">$1filekey</code>“, wat mer emmer noch noch bruche kann, weil mer et fröhjer alld ens esu hatte.",
        "apihelp-upload-param-filesize": "De Datteijrühße vum jannze Huhlahde.",
-       "apihelp-upload-param-asyncdownload": "Maach dat Holle vun ene <i lang=\"en\" xml:lang=\"en\" dir=\"ltr\" title=\"Uniform Ressource Locator\">URL</i> zoh ene andere Zigg.",
        "apihelp-upload-example-url": "Vun enem <i lang=\"en\" xml:lang=\"en\" dir=\"ltr\" title=\"Uniform Ressource Locator\">URL</i> huhlahde.",
        "apihelp-upload-example-filekey": "Don et Huhlahde fähdesch maace, wat wähje Warnonge nit johd jejange wohr.",
        "apihelp-userrights-param-user": "Metmaacher_Nahme.",
index c2c6d7e..89dcaaa 100644 (file)
@@ -11,7 +11,8 @@
                        "SPQRobin",
                        "HanV",
                        "Rangekill",
-                       "Robin van der Vliet"
+                       "Robin van der Vliet",
+                       "Edoderoo"
                ]
        },
        "apihelp-main-description": "<div class=\"hlist plainlinks api-main-links\">\n* [[mw:API:Main_page|Documentatie]]\n* [[mw:API:FAQ|FAQ]]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api E-maillijst]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce API-aankondigingen]\n* [https://phabricator.wikimedia.org/maniphest/query/GebfyV4uCaLd/#R Bugs & verzoeken]\n</div>\n<strong>Status:</strong> Alle functies die op deze pagina worden weergegeven horen te werken. Aan de API wordt actief gewerkt, en deze kan gewijzigd worden. Abonneer u op  de [https://lists.wikimedia.org/pipermail/mediawiki-api-announce/ e-maillijst mediawiki-api-announce] voor meldingen over aanpassingen.\n\n<strong>Foutieve verzoeken:</strong> als de API foutieve verzoeken ontvangt, wordt er geantwoord met een HTTP-header met de sleutel \"MediaWiki-API-Error\" en daarna worden de waarde van de header en de foutcode op dezelfde waarde ingesteld. Zie [[mw:API:Errors_and_warnings|API: Errors and warnings]] voor meer informatie.",
        "apihelp-block-param-nocreate": "Voorkom registeren van accounts.",
        "apihelp-block-param-autoblock": "Blokkeer automatisch het laatst gebruikte IP-adres en ieder volgend IP-adres van waaruit ze proberen aan te melden.",
        "apihelp-block-param-reblock": "De huidige blokkade aanpassen als de gebruiker al geblokkeerd is.",
+       "apihelp-compare-param-fromtitle": "Eerste titel om te vergelijken.",
+       "apihelp-compare-param-fromid": "Eerste pagina-ID om te vergelijken.",
+       "apihelp-compare-param-fromrev": "Eerste versie om te vergelijken.",
+       "apihelp-compare-param-totitle": "Tweede titel om te vergelijken.",
+       "apihelp-compare-param-toid": "Andere pagina-ID om te vergelijken.",
+       "apihelp-compare-param-torev": "Tweede versie om te vergelijken.",
        "apihelp-createaccount-description": "Een nieuw gebruikersaccount aanmaken.",
        "apihelp-createaccount-param-name": "Gebruikersnaam.",
        "apihelp-createaccount-param-email": "E-mailadres van de gebruikers (optioneel).",
        "apihelp-createaccount-param-realname": "Echte naam van de gebruiker (optioneel).",
        "apihelp-delete-description": "Verwijder een pagina.",
+       "apihelp-delete-param-reason": "Reden voor verwijdering. Wanneer dit niet is opgegeven wordt een automatisch gegenereerde reden gebruikt.",
        "apihelp-delete-param-watch": "De pagina aan de volglijst van de huidige gebruiker toevoegen.",
        "apihelp-delete-param-unwatch": "De pagina van de volglijst van de huidige gebruiker verwijderen.",
        "apihelp-delete-example-simple": "Verwijder <kbd>Main Page</kbd>.",
@@ -53,7 +61,8 @@
        "apihelp-edit-param-watch": "Voeg de pagina toe aan de volglijst van de huidige gebruiker.",
        "apihelp-edit-param-unwatch": "Verwijder de pagina van de volglijst van de huidige gebruiker.",
        "apihelp-edit-param-redirect": "Automatisch doorverwijzingen oplossen.",
-       "apihelp-edit-example-edit": "Pagina bewerken",
+       "apihelp-edit-example-edit": "Een pagina bewerken.",
+       "apihelp-edit-example-undo": "Revisies 13579 tot 13585 ongedaan maken met automatische beschrijving.",
        "apihelp-emailuser-description": "Gebruiker e-mailen.",
        "apihelp-emailuser-param-target": "Gebruiker naar wie de e-mail moet worden gestuurd.",
        "apihelp-emailuser-param-subject": "Onderwerpkoptekst.",
        "apihelp-emailuser-param-ccme": "Stuur mij een kopie van deze e-mail.",
        "apihelp-expandtemplates-param-title": "Paginanaam.",
        "apihelp-expandtemplates-param-text": "Wikitekst om om te zetten.",
+       "apihelp-expandtemplates-paramvalue-prop-wikitext": "De uitgevulde wikitekst.",
+       "apihelp-expandtemplates-paramvalue-prop-ttl": "De maximum tijdsduur waarna cache van het resultaat moet worden weggegooid.",
        "apihelp-feedcontributions-description": "Haalt de feed van de gebruikersbijdragen op.",
+       "apihelp-feedcontributions-param-feedformat": "De opmaak van de feed.",
        "apihelp-feedcontributions-param-year": "Van jaar (en eerder).",
        "apihelp-feedcontributions-param-month": "Van maand (en eerder).",
        "apihelp-feedcontributions-param-deletedonly": "Alleen verwijderde bijdragen weergeven.",
@@ -76,6 +88,8 @@
        "apihelp-feedrecentchanges-example-simple": "Recente wijzigingen weergeven.",
        "apihelp-feedrecentchanges-example-30days": "Recente wijzigingen van de afgelopen 30 dagen weergeven.",
        "apihelp-filerevert-description": "Een oude versie van een bestand herplaatsen.",
+       "apihelp-imagerotate-description": "Een of meerdere afbeeldingen draaien.",
+       "apihelp-import-param-xml": "Geüpload XML-bestand.",
        "apihelp-import-param-namespace": "Importeren in deze naamruimte. Can niet samen gebruikt worden met <var>$1rootpage</var>.",
        "apihelp-import-param-rootpage": "Importeren als subpagina van deze pagina. Kan niet samen met <var>$1namespace</var> gebruikt worden.",
        "apihelp-login-param-name": "Gebruikersnaam.",
        "apihelp-logout-example-logout": "Meldt de huidige gebruiker af.",
        "apihelp-managetags-param-tag": "Label om aan te maken, te activeren of te deactiveren. Voor het aanmaken van een label, mag het niet bestaan. Voor het verwijderen van een label, moet het bestaan. Voor het activeren van een label, moet het bestaan en mag het niet gebruikt worden door een uitbreiding. Voor het deactiveren van een label, moet het gebruikt worden en handmatig gedefinieerd zijn.",
        "apihelp-move-description": "Pagina hernoemen.",
+       "apihelp-move-param-to": "Titel om de pagina naar te hernoemen.",
        "apihelp-move-param-reason": "Reden voor de naamswijziging.",
        "apihelp-move-param-noredirect": "Geen doorverwijzing achterlaten.",
        "apihelp-move-param-watch": "Pagina en de omleiding toevoegen aan de volglijst van de huidige gebruiker.",
index d235209..6b36dd8 100644 (file)
        "apihelp-query+allrevisions-param-generatetitles": "当作为生成器使用时,生成标题而不是修订ID。",
        "apihelp-query+allrevisions-example-user": "列出由用户<kbd>Example</kbd>作出的最近50次贡献。",
        "apihelp-query+allrevisions-example-ns-main": "列举主名字空间中的前50次修订。",
+       "apihelp-query+mystashedfiles-description": "获取当前用户的上传藏匿中的文件列表。",
        "apihelp-query+mystashedfiles-param-prop": "要检索文件的属性。",
        "apihelp-query+mystashedfiles-paramvalue-prop-type": "检索文件的MIME类型和媒体类型。",
        "apihelp-query+mystashedfiles-param-limit": "获取多少文件。",
        "apihelp-query+watchlist-param-allrev": "将同一页面的多个修订包含于指定的时间表内。",
        "apihelp-query+watchlist-param-start": "枚举的起始时间戳。",
        "apihelp-query+watchlist-param-end": "枚举的结束时间戳。",
+       "apihelp-query+watchlist-param-namespace": "过滤更改为仅限指定的名字空间。",
        "apihelp-query+watchlist-param-user": "只列出此用户的更改。",
        "apihelp-query+watchlist-param-excludeuser": "不要列出此用户的更改。",
        "apihelp-query+watchlist-param-limit": "根据结果返回的结果总数。",
index 24df574..6b938f1 100644 (file)
@@ -168,7 +168,18 @@ class MessageCache {
         * @return ParserOptions
         */
        function getParserOptions() {
+               global $wgFullyInitialised, $wgContLang;
+
                if ( !$this->mParserOptions ) {
+                       if ( !$wgFullyInitialised ) {
+                               // $wgUser isn't unstubbable yet, so don't try to get a
+                               // ParserOptions for it. And don't cache this ParserOptions
+                               // either.
+                               $po = new ParserOptions( new User, $wgContLang );
+                               $po->setEditSection( false );
+                               return $po;
+                       }
+
                        $this->mParserOptions = new ParserOptions;
                        $this->mParserOptions->setEditSection( false );
                }
index 3b868a1..73e11b5 100644 (file)
@@ -510,10 +510,11 @@ class RequestContext implements IContextSource, MutableContext {
         * @since 1.21
         */
        public function exportSession() {
+               $session = MediaWiki\Session\SessionManager::getGlobalSession();
                return array(
                        'ip' => $this->getRequest()->getIP(),
                        'headers' => $this->getRequest()->getAllHeaders(),
-                       'sessionId' => MediaWiki\Session\SessionManager::getGlobalSession()->getId(),
+                       'sessionId' => $session->isPersistent() ? $session->getId() : '',
                        'userId' => $this->getUser()->getId()
                );
        }
index f09de4f..264ee11 100644 (file)
@@ -505,6 +505,10 @@ class DBConnRef implements IDatabase {
                return $this->__call( __FUNCTION__, func_get_args() );
        }
 
+       public function getScopedLockAndFlush( $lockKey, $fname, $timeout ) {
+               return $this->__call( __FUNCTION__, func_get_args() );
+       }
+
        public function namedLocksEnqueue() {
                return $this->__call( __FUNCTION__, func_get_args() );
        }
index 1835958..a4d0ad0 100644 (file)
@@ -155,6 +155,9 @@ abstract class DatabaseBase implements IDatabase {
         */
        private $mTrxWriteDuration = 0.0;
 
+       /** @var array Map of (name => 1) for locks obtained via lock() */
+       private $mNamedLocksHeld = array();
+
        /** @var IDatabase|null Lazy handle to the master DB this server replicates from */
        private $lazyMasterHandle;
 
@@ -871,7 +874,7 @@ abstract class DatabaseBase implements IDatabase {
                                $msg = __METHOD__ . ": lost connection to $server; reconnected";
                                wfDebugLog( 'DBPerformance', "$msg:\n" . wfBacktrace( true ) );
 
-                               if ( $hadTrx ) {
+                               if ( $hadTrx || $this->mNamedLocksHeld ) {
                                        # Leave $ret as false and let an error be reported.
                                        # Callers may catch the exception and continue to use the DB.
                                        $this->reportQueryError( $lastError, $lastErrno, $sql, $fname, $tempIgnore );
@@ -3160,13 +3163,33 @@ abstract class DatabaseBase implements IDatabase {
        }
 
        public function lock( $lockName, $method, $timeout = 5 ) {
+               $this->mNamedLocksHeld[$lockName] = 1;
+
                return true;
        }
 
        public function unlock( $lockName, $method ) {
+               unset( $this->mNamedLocksHeld[$lockName] );
+
                return true;
        }
 
+       public function getScopedLockAndFlush( $lockKey, $fname, $timeout ) {
+               if ( !$this->lock( $lockKey, $fname, $timeout ) ) {
+                       return null;
+               }
+
+               $that = $this;
+               $unlocker = new ScopedCallback( function () use ( $that, $lockKey, $fname ) {
+                       $that->commit( __METHOD__, 'flush' );
+                       $that->unlock( $lockKey, $fname );
+               } );
+
+               $this->commit( __METHOD__, 'flush' );
+
+               return $unlocker;
+       }
+
        public function namedLocksEnqueue() {
                return false;
        }
index 3a8f737..29106ab 100644 (file)
@@ -932,12 +932,13 @@ abstract class DatabaseMysqlBase extends Database {
                $row = $this->fetchObject( $result );
 
                if ( $row->lockstatus == 1 ) {
+                       parent::lock( $lockName, $method, $timeout ); // record
                        return true;
-               } else {
-                       wfDebug( __METHOD__ . " failed to acquire lock\n" );
-
-                       return false;
                }
+
+               wfDebug( __METHOD__ . " failed to acquire lock\n" );
+
+               return false;
        }
 
        /**
@@ -952,7 +953,14 @@ abstract class DatabaseMysqlBase extends Database {
                $result = $this->query( "SELECT RELEASE_LOCK($lockName) as lockstatus", $method );
                $row = $this->fetchObject( $result );
 
-               return ( $row->lockstatus == 1 );
+               if ( $row->lockstatus == 1 ) {
+                       parent::unlock( $lockName, $method ); // record
+                       return true;
+               }
+
+               wfDebug( __METHOD__ . " failed to release lock\n" );
+
+               return false;
        }
 
        private function makeLockName( $lockName ) {
index 4d9891e..e84f264 100644 (file)
@@ -1581,11 +1581,13 @@ SQL;
                                "SELECT pg_try_advisory_lock($key) AS lockstatus", $method );
                        $row = $this->fetchObject( $result );
                        if ( $row->lockstatus === 't' ) {
+                               parent::lock( $lockName, $method, $timeout ); // record
                                return true;
                        } else {
                                sleep( 1 );
                        }
                }
+
                wfDebug( __METHOD__ . " failed to acquire lock\n" );
 
                return false;
@@ -1603,7 +1605,14 @@ SQL;
                $result = $this->query( "SELECT pg_advisory_unlock($key) as lockstatus", $method );
                $row = $this->fetchObject( $result );
 
-               return ( $row->lockstatus === 't' );
+               if ( $row->lockstatus === 't' ) {
+                       parent::unlock( $lockName, $method ); // record
+                       return true;
+               }
+
+               wfDebug( __METHOD__ . " failed to release lock\n" );
+
+               return false;
        }
 
        /**
index c72218a..1e728d8 100644 (file)
@@ -1219,6 +1219,8 @@ interface IDatabase {
         * after the database is updated so that the jobs will see the data when they actually run.
         * It can also be used for updates that easily cause deadlocks if locks are held too long.
         *
+        * Updates will execute in the order they were enqueued.
+        *
         * @param callable $callback
         * @since 1.20
         */
@@ -1232,6 +1234,8 @@ interface IDatabase {
         * This is useful for updates that easily cause deadlocks if locks are held too long
         * but where atomicity is strongly desired for these updates and some related updates.
         *
+        * Updates will execute in the order they were enqueued.
+        *
         * @param callable $callback
         * @since 1.22
         */
@@ -1489,8 +1493,8 @@ interface IDatabase {
         * Named locks are not related to transactions
         *
         * @param string $lockName Name of lock to aquire
-        * @param string $method Name of method calling us
-        * @param int $timeout
+        * @param string $method Name of the calling method
+        * @param int $timeout Acquisition timeout in seconds
         * @return bool
         */
        public function lock( $lockName, $method, $timeout = 5 );
@@ -1501,7 +1505,7 @@ interface IDatabase {
         * Named locks are not related to transactions
         *
         * @param string $lockName Name of lock to release
-        * @param string $method Name of method calling us
+        * @param string $method Name of the calling method
         *
         * @return int Returns 1 if the lock was released, 0 if the lock was not established
         * by this thread (in which case the lock is not released), and NULL if the named
@@ -1509,6 +1513,25 @@ interface IDatabase {
         */
        public function unlock( $lockName, $method );
 
+       /**
+        * Acquire a named lock, flush any transaction, and return an RAII style unlocker object
+        *
+        * This is suitiable for transactions that need to be serialized using cooperative locks,
+        * where each transaction can see each others' changes. Any transaction is flushed to clear
+        * out stale REPEATABLE-READ snapshot data. Once the returned object falls out of PHP scope,
+        * any transaction will be committed and the lock will be released.
+        *
+        * If the lock acquisition failed, then no transaction flush happens, and null is returned.
+        *
+        * @param string $lockKey Name of lock to release
+        * @param string $fname Name of the calling method
+        * @param int $timeout Acquisition timeout in seconds
+        * @return ScopedCallback|null
+        * @throws DBUnexpectedError
+        * @since 1.27
+        */
+       public function getScopedLockAndFlush( $lockKey, $fname, $timeout );
+
        /**
         * Check to see if a named lock used by lock() use blocking queues
         *
index 25fdea9..606f4f4 100644 (file)
@@ -228,9 +228,24 @@ abstract class LBFactory {
        /**
         * Commit changes on all master connections
         * @param string $fname Caller name
+        * @param array $options Options map:
+        *   - maxWriteDuration: abort if more than this much time was spent in write queries
         */
-       public function commitMasterChanges( $fname = __METHOD__ ) {
+       public function commitMasterChanges( $fname = __METHOD__, array $options = array() ) {
+               $limit = isset( $options['maxWriteDuration'] ) ? $options['maxWriteDuration'] : 0;
+
                $this->logMultiDbTransaction();
+               $this->forEachLB( function ( LoadBalancer $lb ) use ( $limit ) {
+                       $lb->forEachOpenConnection( function ( IDatabase $db ) use ( $limit ) {
+                               $time = $db->pendingWriteQueryDuration();
+                               if ( $limit > 0 && $time > $limit ) {
+                                       throw new DBTransactionError(
+                                               $db,
+                                               wfMessage( 'transaction-duration-limit-exceeded', $time, $limit )->text()
+                                       );
+                               }
+                       } );
+               } );
 
                $start = microtime( true );
                $this->forEachLBCallMethod( 'commitMasterChanges', array( $fname ) );
index b5a79a9..32999f5 100644 (file)
@@ -1363,10 +1363,10 @@ class LoadBalancer {
         * function instead of Database::getLag() avoids a fatal error in this
         * case on many installations.
         *
-        * @param DatabaseBase $conn
-        * @return int
+        * @param IDatabase $conn
+        * @return int|bool Returns false on error
         */
-       public function safeGetLag( $conn ) {
+       public function safeGetLag( IDatabase $conn ) {
                if ( $this->getServerCount() == 1 ) {
                        return 0;
                } else {
@@ -1374,6 +1374,41 @@ class LoadBalancer {
                }
        }
 
+       /**
+        * Wait for a slave DB to reach a specified master position
+        *
+        * This will connect to the master to get an accurate position if $pos is not given
+        *
+        * @param IDatabase $conn Slave DB
+        * @param DBMasterPos|bool $pos Master position; default: current position
+        * @param integer $timeout Timeout in seconds
+        * @return bool Success
+        * @since 1.27
+        */
+       public function safeWaitForMasterPos( IDatabase $conn, $pos = false, $timeout = 10 ) {
+               if ( $this->getServerCount() == 1 || !$conn->getLBInfo( 'slave' ) ) {
+                       return true; // server is not a slave DB
+               }
+
+               $pos = $pos ?: $this->getConnection( DB_MASTER )->getMasterPos();
+               if ( !$pos ) {
+                       return false; // something is misconfigured
+               }
+
+               $result = $conn->masterPosWait( $pos, $timeout );
+               if ( $result == -1 || is_null( $result ) ) {
+                       $msg = __METHOD__ . ": Timed out waiting on {$conn->getServer()} pos {$pos}";
+                       wfDebugLog( 'replication', "$msg\n" );
+                       wfDebugLog( 'DBPerformance', "$msg:\n" . wfBacktrace( true ) );
+                       $ok = false;
+               } else {
+                       wfDebugLog( 'replication', __METHOD__ . ": Done\n" );
+                       $ok = true;
+               }
+
+               return $ok;
+       }
+
        /**
         * Clear the cache for slag lag delay times
         *
index 4e8e65b..2465918 100644 (file)
@@ -99,9 +99,25 @@ class KafkaHandler extends AbstractProcessingHandler {
        ) {
                $metadata = new MetaDataFromKafka( $kafkaServers );
                $produce = new Produce( $metadata );
+
+               if ( isset( $options['sendTimeout'] ) ) {
+                       $timeOut = $options['sendTimeout'];
+                       $produce->getClient()->setStreamOption( 'SendTimeoutSec', 0 );
+                       $produce->getClient()->setStreamOption( 'SendTimeoutUSec',
+                               intval( $timeOut * 1000000 )
+                       );
+               }
+               if ( isset( $options['recvTimeout'] ) ) {
+                       $timeOut = $options['recvTimeout'];
+                       $produce->getClient()->setStreamOption( 'RecvTimeoutSec', 0 );
+                       $produce->getClient()->setStreamOption( 'RecvTimeoutUSec',
+                               intval( $timeOut * 1000000 )
+                       );
+               }
                if ( isset( $options['logExceptions'] ) && is_string( $options['logExceptions'] ) ) {
                        $options['logExceptions'] = LoggerFactory::getInstance( $options['logExceptions'] );
                }
+
                return new self( $produce, $options, $level, $bubble );
        }
 
index 9617c0a..8816d37 100644 (file)
@@ -44,4 +44,13 @@ class HTMLUserTextField extends HTMLTextField {
 
                return new UserInputWidget( $params );
        }
+
+       public function getInputHtml( $value ) {
+               // add the required module and css class for user suggestions in non-OOUI mode
+               $this->mParent->getOutput()->addModules( 'mediawiki.userSuggest' );
+               $this->mClass .= ' mw-autocomplete-user';
+
+               // return parent html
+               return parent::getInputHtml( $value );
+       }
 }
index 904fde8..61c3002 100644 (file)
@@ -456,7 +456,7 @@ abstract class DatabaseUpdater {
                        flush();
                        if ( $ret !== false ) {
                                $updatesDone[] = $origParams;
-                               wfWaitForSlaves();
+                               wfGetLBFactory()->waitForReplication();
                        } else {
                                $updatesSkipped[] = array( $func, $params, $origParams );
                        }
index 4813bea..10fed31 100644 (file)
@@ -836,7 +836,7 @@ class MysqlUpdater extends DatabaseUpdater {
                        foreach ( $res as $row ) {
                                $count = ( $count + 1 ) % 100;
                                if ( $count == 0 ) {
-                                       wfWaitForSlaves();
+                                       wfGetLBFactory()->waitForReplication( array( 'wiki' => wfWikiID() ) );
                                }
                                $this->db->insert( 'templatelinks',
                                        array(
index ad7c627..ee46d90 100644 (file)
@@ -18,7 +18,7 @@
        "config-localsettings-upgrade": "Εντοπίστηκε αρχείο <code>LocalSettings.php</code>.\nΓια να αναβαθμίσετε αυτή την εγκατάσταση, παρακαλούμε να εισαγάγετε την τιμή του <code>$wgUpgradeKey</code> στο παρακάτω πλαίσιο.\nΘα το βρείτε στο <code>LocalSettings.php</code>.",
        "config-localsettings-cli-upgrade": "Ένα αρχείο <code>LocalSettings.php</code> έχει εντοπιστεί.\nΓια να αναβαθμίσετε αυτή την εγκατάσταση, εκτελέστε το <code>update.php</code> αντ' αυτού.",
        "config-localsettings-key": "Κλειδί αναβάθμισης:",
-       "config-localsettings-badkey": "Το κλειδί που δώσατε είναι εσφαλμένο.",
+       "config-localsettings-badkey": "Το κλειδί αναβάθμισης που δώσατε είναι εσφαλμένο.",
        "config-upgrade-key-missing": "Έχει εντοπιστεί μια υπάρχουσα εγκατάσταση του MediaWiki.\nΓια να αναβαθμίσετε αυτήν την εγκατάσταση, παρακαλούμε να βάλετε την ακόλουθη γραμμή στο κάτω μέρος του <code>LocalSettings.php</code> σας:\n\n$1",
        "config-localsettings-incomplete": "Το υπάρχον <code>LocalSettings.php</code> φαίνεται να είναι ελλιπές.\nΤο $1 μεταβλητή δεν έχει οριστεί.\nΠαρακαλούμε να αλλάξετε  το <code>LocalSettings.php</code> έτσι ώστε αυτή η μεταβλητή έχει οριστεί, και κάντε κλικ στο \"{{int:Config-continue}}\".",
        "config-localsettings-connection-error": "Ένα σφάλμα παρουσιάστηκε κατά τη σύνδεση με τη βάση δεδομένων και με τη χρήση των ρυθμίσεων που ορίστηκαν στο <code>LocalSettings.php</code>. Παρακαλούμε διορθώστε αυτές τις ρυθμίσεις και δοκιμάστε ξανά.\n\n$1",
index e468b00..8c0ade9 100644 (file)
@@ -15,7 +15,8 @@
                        "Shield-9",
                        "Takot",
                        "Sujiniku",
-                       "Macofe"
+                       "Macofe",
+                       "2nd-player"
                ]
        },
        "config-desc": "MediaWiki のインストーラー",
        "config-instantcommons-help": "[//www.mediawiki.org/wiki/InstantCommons Instant Commons] は、[//commons.wikimedia.org/ ウィキメディア・コモンズ]のサイトにある画像、音声、その他のメディアをウィキ上で利用できるようにする機能です。\nこれを使用するには、MediaWiki がインターネットに接続できる必要があります。\n\nウィキメディア・コモンズ以外のウィキを同様に設定する手順など、この機能に関する詳細な情報は、[//www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgForeignFileRepos マニュアル]をご覧ください。",
        "config-cc-error": "クリエイティブ・コモンズ・ライセンスの選択器から結果が得られませんでした。\nライセンスの名前を手動で入力してください。",
        "config-cc-again": "もう一度選択してください...",
-       "config-cc-not-chosen": "希望するクリエイティブ・コモンズのライセンスを選択して、「続行」をクリックしてください。",
+       "config-cc-not-chosen": "希望するクリエイティブ・コモンズのライセンスを選択して、「proceed」をクリックしてください。",
        "config-advanced-settings": "高度な設定",
        "config-cache-options": "オブジェクトのキャッシュの設定:",
        "config-cache-help": "オブジェクトのキャッシュを使用すると、頻繁に使用するデータをキャッシュするため MediaWiki の動作速度を改善できます。\n中〜大規模サイトではこれを有効にすることを強くお勧めします。小規模サイトでも同様に効果があります。",
index 6a607b6..3377afb 100644 (file)
@@ -12,7 +12,7 @@
        "config-localsettings-upgrade": "Востановена е податотека <code>LocalSettings.php</code>.\nЗа да ја надградите инсталцијава, внесете ја вредноста на <code>$wgUpgradeKey</code> во полето подолу.\nТоа е го најдете во <code>LocalSettings.php</code>.",
        "config-localsettings-cli-upgrade": "Утврдено е присуството на податотеката „<code>LocalSettings.php</code>“.\nЗа да ја надградите воспоставката, пуштете ја „<code>update.php</code>“ наместо горенаведената.",
        "config-localsettings-key": "Надградбен клуч:",
-       "config-localsettings-badkey": "Ð\9aлÑ\83Ñ\87оÑ\82 Ñ\88Ñ\82о Ð³Ð¾ Ð½Ð°Ð²ÐµÐ´Ð¾Ð²Ñ\82е Ðµ Ð¿Ð¾Ð³Ñ\80еÑ\88ен",
+       "config-localsettings-badkey": "Ð\9dадгÑ\80адбениоÑ\82 ÐºÐ»Ñ\83Ñ\87 Ñ\88Ñ\82о Ð³Ð¾ Ð½Ð°Ð²ÐµÐ´Ð¾Ð²Ñ\82е Ðµ Ð¿Ð¾Ð³Ñ\80еÑ\88ен.",
        "config-upgrade-key-missing": "Востановена е постоечка воспоставка на МедијаВики.\nЗа да ја надградите, вметнете го следниов ред на дното од вашата страница <code>LocalSettings.php</code>:\n\n$1",
        "config-localsettings-incomplete": "Постоечката страница <code>LocalSettings.php</code> е нецелосна.\nНе е поставена променливата $1.\nИзменете ја страницата <code>LocalSettings.php</code> така што ќе ѝ зададете вредност на променливата, па стиснете на „{{int:Config-continue}}“.",
        "config-localsettings-connection-error": "Се појави грешка при поврзувањето со базата користејќи ги поставките назначени во <code>LocalSettings.php</code>. Исправете ги овие поставки и обидете се повторно.\n\n$1",
index a9a8b2b..4c71d39 100644 (file)
@@ -25,7 +25,7 @@
        "config-localsettings-upgrade": "Er is een bestaand instellingenbestand <code>LocalSettings.php</code> gevonden.\nVoer de waarde van <code>$wgUpgradeKey</code> in in onderstaande invoerveld om deze installatie bij te werken.\nDe instelling is terug te vinden in <code>LocalSettings.php</code>.",
        "config-localsettings-cli-upgrade": "Het bestand <code>LocalSettings.php</code> is al aanwezig.\nVoer <code>update.php</code> uit om deze installatie bij te werken.",
        "config-localsettings-key": "Upgradesleutel:",
-       "config-localsettings-badkey": "De sleutel die u hebt opgegeven is onjuist.",
+       "config-localsettings-badkey": "De upgrade-sleutel die u hebt opgegeven is onjuist.",
        "config-upgrade-key-missing": "Er is een bestaande installatie van MediaWiki aangetroffen.\nPlaats de volgende regel onderaan uw <code>LocalSettings.php</code> om deze installatie bij te werken:\n\n$1",
        "config-localsettings-incomplete": "De bestaande inhoud van <code>LocalSettings.php</code> lijkt incompleet.\nDe variabele $1 is niet ingesteld.\nWijzig <code>LocalSettings.php</code> zodat deze variabele is ingesteld en klik op \"{{int:Config-continue}}\".",
        "config-localsettings-connection-error": "Er is een fout opgetreden tijdens het verbinden met de database met de instellingen uit <code>LocalSettings.php</code>. Los het probleem met de instellingen op en probeer het daarna opnieuw.\n\n$1",
@@ -86,6 +86,7 @@
        "config-apc": "[http://www.php.net/apc APC] is op dit moment geïnstalleerd",
        "config-wincache": "[http://www.iis.net/download/WinCacheForPhp WinCache] is op dit moment geïnstalleerd",
        "config-no-cache": "'''Waarschuwing:''' [http://www.php.net/apc APC], [http://xcache.lighttpd.net/ XCache] of [http://www.iis.net/download/WinCacheForPhp WinCache] is niet aangetroffen.\nHet cachen van objecten is niet ingeschakeld.",
+       "config-no-cache-apcu": "<strong>Waarschuwing:</strong> [http://www.php.net/apcu APCu], [http://xcache.lighttpd.net/ XCache] of [http://www.iis.net/download/WinCacheForPhp WinCache] is niet aangetroffen.\nHet cachen van objecten is niet ingeschakeld.",
        "config-mod-security": "'''Waarschuwing:''' uw webserver heeft de module [http://modsecurity.org/ mod_security] ingeschakeld. Als deze onjuist is ingesteld, kan dit problemen geven in combinatie met MediaWiki of andere software die gebruikers in staat stelt willekeurige inhoud te posten.\nLees de [http://modsecurity.org/documentation/ documentatie over mod_security] of neem contact op met de helpdesk van uw provider als u tegen problemen aanloopt.",
        "config-diff3-bad": "GNU diff3 niet aangetroffen.",
        "config-git": "Versiecontrolesoftware git is aangetroffen: <code>$1</code>",
index dcfd69a..b57bc78 100644 (file)
        "config-unicode-pure-php-warning": "<strong>警告:</strong>因为尚未安装 [http://pecl.php.net/intl intl PECL 扩展]以处理 Unicode 正常化,故只能退而采用运行较慢的纯 PHP 实现的方法。\n如果您运行着一个高流量的网站,请参阅 [//www.mediawiki.org/wiki/Special:MyLanguage/Unicode_normalization_considerations Unicode标准化]一文。",
        "config-unicode-update-warning": "'''警告''':Unicode正常化封装器的已安装版本使用了旧版本的[http://site.icu-project.org/ ICU项目]库。如果您需要使用Unicode,请将其[//www.mediawiki.org/wiki/Special:MyLanguage/Unicode_normalization_considerations 升级]。",
        "config-no-db": "无法找到合适的数据库驱动!您需要为PHP安装数据库驱动。目前支持以下数据库{{PLURAL:$2|类型}}:$1。\n\n如果您自己编译了PHP,请通过启用数据库客户端重新配置它,例如使用 <code>./configure --with-mysqli</code>。如果您从 Debian 或 Ubuntu 安装包安装了PHP,那么您也需要安装,例如 <code>php5-mysql</code> 安装包。",
-       "config-outdated-sqlite": "'''警告''':您已安装SQLite $1,但是它的版本低于最低要求版本$2。因此您无法选择SQLite。",
-       "config-no-fts3": "'''警告''':已编译的SQLite不包含[//sqlite.org/fts3.html FTS3模块],后台搜索功能将不可用。",
+       "config-outdated-sqlite": "<strong>警告:</strong>您已安装SQLite $1,但是它的版本低于最低要求版本$2。因此您无法选择SQLite。",
+       "config-no-fts3": "<strong>警告:</strong>已编译的SQLite不包含[//sqlite.org/fts3.html FTS3模块],后台搜索功能将不可用。",
        "config-register-globals-error": "<strong>错误:PHP<code>[http://php.net/register_globals register_globals]</code>选项被启用。必须禁用它才能继续安装。</strong>关于如何禁用,参见[https://www.mediawiki.org/wiki/register_globals mediawiki.org此页]。",
        "config-magic-quotes-gpc": "<strong>致命错误:[http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-gpc magic_quotes_gpc]已启用!</strong>此选项会无法挽回的破坏输入数据。除非此选项被禁用否则您不能安装或使用MediaWiki。",
-       "config-magic-quotes-runtime": "'''毁灭性错误:[http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-runtime magic_quotes_runtime]已启用!'''\n此选项会无法预测地破坏输入的数据,请将其禁用,否则您将不能安装或使用MediaWiki。",
-       "config-magic-quotes-sybase": "'''毁灭性错误:[http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-runtime magic_quotes_sybase]已启用!'''\n此选项会无法预测地破坏输入的数据,请将其禁用,否则您将不能安装或使用MediaWiki。",
-       "config-mbstring": "'''毁灭性错误:[http://www.php.net/manual/en/ref.mbstring.php#mbstring.overload mbstring.func_overload]已启用!'''\n此选项会导致错误并不可预测地破坏数据,请将其禁用,否则您将不能安装或使用MediaWiki。",
-       "config-safe-mode": "'''警告:'''PHP的[http://www.php.net/features.safe-mode 安全模式]已启用。它可能会导致一些问题,尤其在对文件上传和数学公式<code>math</code>的支持方面。",
+       "config-magic-quotes-runtime": "<strong>致命错误:[http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-runtime magic_quotes_runtime]已启用!</strong>\n此选项会无法预测地破坏输入的数据,请将其禁用,否则您将不能安装或使用MediaWiki。",
+       "config-magic-quotes-sybase": "<strong>致命错误:[http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-sybase magic_quotes_sybase]已启用!</strong>\n此选项会无法预测地破坏输入的数据,请将其禁用,否则您将不能安装或使用MediaWiki。",
+       "config-mbstring": "<strong>致命错误:[http://www.php.net/manual/en/ref.mbstring.php#mbstring.overload mbstring.func_overload]已启用!</strong>\n此选项会导致错误并不可预测地破坏数据,请将其禁用,否则您将不能安装或使用MediaWiki。",
+       "config-safe-mode": "<strong>警告:</strong>PHP的[http://www.php.net/features.safe-mode 安全模式]已启用。\n它可能会导致一些问题,尤其在对文件上传和数学公式<code>math</code>的支持方面。",
        "config-xml-bad": "缺少PHP的XML模块。MediaWiki需要使用该模块提供的函数,在当前配置下将无法工作。您可能需要安装php-xml RPM包。",
-       "config-pcre-old": "'' 致命错误: ''需要PCRE $1 或更高版本。\n您的 PHP 二进制文件与 PCRE $2 链接。\n[https://www.mediawiki.org/wiki/Manual:Errors_and_symptoms/PCRE 详细信息]。",
-       "config-pcre-no-utf8": "'''毁灭性错误''':PHP的PCRE模块在编译时可能没有包含PCRE_UTF8支持。MediaWiki需要UTF-8支持才能正常工作。",
+       "config-pcre-old": "<strong>致命错误:</strong>需要PCRE $1 或更高版本。\n您的 PHP 二进制文件与 PCRE $2 链接。\n[https://www.mediawiki.org/wiki/Manual:Errors_and_symptoms/PCRE 详细信息]。",
+       "config-pcre-no-utf8": "<strong>致命错误:</strong>PHP的PCRE模块在编译时可能没有包含PCRE_UTF8支持。\nMediaWiki需要UTF-8支持才能正常工作。",
        "config-memory-raised": "PHP的内存使用上限<code>memory_limit</code>为$1,自动提升到$2。",
-       "config-memory-bad": "'''警告:'''PHP的内存使用上限<code>memory_limit</code>为$1。该设定可能过低,并导致安装失败!",
-       "config-ctype": "'''毁灭性错误''':PHP必须有[http://www.php.net/manual/en/ctype.installation.php Ctype 扩展]来支持编译。",
+       "config-memory-bad": "<strong>警告:</strong>PHP的内存使用上限<code>memory_limit</code>为$1。\n该设定可能过低,并导致安装失败!",
+       "config-ctype": "<strong>致命错误:</strong>PHP必须有[http://www.php.net/manual/en/ctype.installation.php Ctype 扩展]来支持编译。",
        "config-iconv": "<strong>致命错误:</strong>PHP必须编译支持[http://www.php.net/manual/en/iconv.installation.php iconv拓展]。",
-       "config-json": "'''致命问题:''' PHP编译没有附带JSON支持。\n在安装MediaWiki前,你必须安装PHP JSON扩展或者[http://pecl.php.net/package/jsonc PECL jsonc]扩展。\n* PHP扩展已包含在Red Hat Enterprise Linux (CentOS) 5和6中,但必须在<code>/etc/php.ini</code>或<code>/etc/php.d/json.ini</code>中启用。\n* 部分在2013年5月后发行的Linux发行版省略了PHP扩展,而将PECL扩展打包成了<code>php5-json</code>或<code>php-pecl-jsonc</code>。",
+       "config-json": "<strong>致命错误:</strong>PHP编译没有附带JSON支持。\n在安装MediaWiki前,你必须安装PHP JSON扩展或者[http://pecl.php.net/package/jsonc PECL jsonc]扩展。\n* PHP扩展已包含在Red Hat Enterprise Linux (CentOS) 5和6中,但必须在<code>/etc/php.ini</code>或<code>/etc/php.d/json.ini</code>中启用。\n* 部分在2013年5月后发行的Linux发行版省略了PHP扩展,而将PECL扩展打包成了<code>php5-json</code>或<code>php-pecl-jsonc</code>。",
        "config-xcache": "[http://xcache.lighttpd.net/ XCache]已安装",
        "config-apc": "[http://www.php.net/apc APC]已安装",
        "config-wincache": "[http://www.iis.net/download/WinCacheForPhp WinCache]已安装",
-       "config-no-cache": "'''警告:'''找不到[http://www.php.net/apc APC]、[http://xcache.lighttpd.net/ XCache]或[http://www.iis.net/download/WinCacheForPhp WinCache],无法启用对象缓存。\nObject caching is not enabled.",
+       "config-no-cache": "<strong>警告:</strong>找不到[http://www.php.net/apc APC]、[http://xcache.lighttpd.net/ XCache]或[http://www.iis.net/download/WinCacheForPhp WinCache]。\n对象缓冲未启用。",
        "config-no-cache-apcu": "<strong>警告:</strong>找不到[http://www.php.net/apcu APCu]、[http://xcache.lighttpd.net/ XCache]或[http://www.iis.net/download/WinCacheForPhp WinCache]。\n对象缓存未启用。",
-       "config-mod-security": "'''警告''':您的服务器已启动[http://modsecurity.org/ mod_security]。若其配置错误, 会导致MediaWiki和其他软件的错误并允许用户任意发布内容。如果您遇到任何错误,请查阅[http://modsecurity.org/documentation/ mod_security文档]或联系您的客服。",
+       "config-mod-security": "<strong>警告:</strong>您的web服务器已启用[http://modsecurity.org/ mod_security]/mod_security2。它的很多常见配置可能导致MediaWiki及其他软件允许用户发布任意内容的问题。如果可能,这应当被禁用。否则,当您遭遇随机错误时,请参考[http://modsecurity.org/documentation/ mod_security 文档]或联络您的主机支持。",
        "config-diff3-bad": "找不到GNU diff3。",
        "config-git": "发现Git版本控制软件:<code>$1</code>",
        "config-git-bad": "Git版本控制软件未找到。",
        "config-imagemagick": "已找到ImageMagick:<code>$1</code>。如果你启用了上传功能,缩略图功能也将被启用。",
        "config-gd": "已找到内建的GD图形库。如果你启用了上传功能,缩略图功能也将被启用。",
        "config-no-scaling": "找不到GD库或ImageMagick。缩略图功能将不可用。",
-       "config-no-uri": "'''错误:'''无法确定当前的URI。安装已中断。",
+       "config-no-uri": "<strong>错误:</strong>无法确定当前的URI。\n安装已中断。",
        "config-no-cli-uri": "<strong>警告:</strong>未指定<code>--scriptpath</code>参数,使用默认值:<code>$1</code>。",
        "config-using-server": "使用服务器名“<nowiki>$1</nowiki>”。",
        "config-using-uri": "使用服务器URL“<nowiki>$1$2</nowiki>”。",
-       "config-uploads-not-safe": "'''警告:'''您的默认上传目录<code>$1</code>存在允许执行任意脚本的漏洞。尽管MediaWiki会对所有已上传的文件进行安全检查,但我们仍然强烈建议您在启用上传功能前[//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Security#Upload_security 关闭该安全漏洞]。",
-       "config-no-cli-uploads-check": "'''警告''':在CLI安装过程中,没有对您的默认上传目录(<code>$1</code>)进行执行任意脚本的漏洞检查。",
+       "config-uploads-not-safe": "<strong>警告:</strong>您的默认上传目录<code>$1</code>存在允许执行任意脚本的漏洞。\n尽管MediaWiki会对所有已上传的文件进行安全检查,但我们仍然强烈建议您在启用上传功能前[//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Security#Upload_security 关闭该安全漏洞]。",
+       "config-no-cli-uploads-check": "<strong>警告:</strong>在CLI安装过程中,没有对您的默认上传目录(<code>$1</code>)进行执行任意脚本的漏洞检查。",
        "config-brokenlibxml": "您的系统安装的PHP和libxml2版本组合存在故障,并可能在MediaWiki和其他web应用程序中造成隐藏的数据损坏。请将libxml2升级到2.7.3或以上([https://bugs.php.net/bug.php?id=45996 PHP的故障报告])。安装已中断。",
        "config-suhosin-max-value-length": "Suhosin已经安装并将GET请求的参数长度限制在$1字节。MediaWiki的ResourceLoader部件可以在此限制下正常工作,但其性能会被降低。如果可能,请在<code>php.ini</code>中将<code>suhosin.get.max_value_length</code>设为1024或更高值,并在LocalSettings.php中将<code>$wgResourceLoaderMaxQueryLength</code>设为同一值。",
        "config-db-type": "数据库类型:",
        "config-charset-mysql5-binary": "MySQL 4.1/5.0 二进制",
        "config-charset-mysql5": "MySQL 4.1/5.0 UTF-8",
        "config-charset-mysql4": "MySQL 4.0 UTF-8(向后兼容)",
-       "config-charset-help": "'''警告:'''如果您在MySQL 4.1+中使用'''向后兼容的UTF-8'''字符集,并在之后使用<code>mysqldump</code>备份了数据库,则可能损坏所有的非ASCII字符,从而不可逆地破坏您的备份!\n\n在'''二进制模式'''下,MediaWiki会将UTF-8编码的文本存于数据库的二进制字段中。相对于MySQL的UTF-8模式,这种方法效率更高,并允许您使用全范围的Unicode字符。\n\n在'''UTF-8模式'''下,MySQL将知道您数据使用的字符集,并能适当地提供和转换内容。但这样做您将无法在数据库中存储[//zh.wikipedia.org/wiki/基本多文种平面 基本多文种平面]以外的字符。",
+       "config-charset-help": "<strong>警告:</strong>如果您在MySQL 4.1+中使用<strong>向后兼容的UTF-8</strong>字符集,并在之后使用<code>mysqldump</code>备份了数据库,则可能损坏所有的非ASCII字符,从而不可逆地破坏您的备份!\n\n在<strong>二进制模式</strong>下,MediaWiki会将UTF-8编码的文本存于数据库的二进制字段中。相对于MySQL的UTF-8模式,这种方法效率更高,并允许您使用全范围的Unicode字符。\n\n在<strong>UTF-8模式</strong>下,MySQL将知道您数据使用的字符集,并能适当地提供和转换内容。但这样做您将无法在数据库中存储[//zh.wikipedia.org/wiki/基本多文种平面 基本多文种平面]以外的字符。",
        "config-mysql-old": "需要MySQL $1或更新的版本,您的版本为$2。",
        "config-db-port": "数据库端口:",
        "config-db-schema": "MediaWiki的数据库模式",
        "config-db-schema-help": "此数据库模式通常是正确的,请在有明确需求时才改动之。",
-       "config-pg-test-error": "无法连接到数据库'''$1''':$2",
+       "config-pg-test-error": "无法连接到数据库<strong>$1</strong>:$2",
        "config-sqlite-dir": "SQLite数据目录:",
-       "config-sqlite-dir-help": "SQLite会将所有的数据存储于单一文件中。\n\n您所提供的目录必须在安装过程中对网页服务器可写。\n\n该目录'''不应'''允许通过web访问,因此我们不会将数据文件和PHP文件放在一起。\n\n安装程序在创建数据文件时,亦会在相同目录下创建<code>.htaccess</code>以控制权限。假若此等控制失效,则可能会将您的数据文件暴露于公共空间,让他人可以获取用户数据(电子邮件地址、杂凑后的密码)、被删除的版本以及其他在wiki上被限制访问的数据。\n\n请考虑将数据库统一放置在某处,如<code>/var/lib/mediawiki/yourwiki</code>下。",
+       "config-sqlite-dir-help": "SQLite会将所有的数据存储于单一文件中。\n\n您所提供的目录必须在安装过程中对网页服务器可写。\n\n该目录<strong>不应</strong>允许通过web访问,因此我们不会将数据文件和PHP文件放在一起。\n\n安装程序在创建数据文件时,亦会在相同目录下创建<code>.htaccess</code>以控制权限。假若此等控制失效,则可能会将您的数据文件暴露于公共空间,让他人可以获取用户数据(电子邮件地址、杂凑后的密码)、被删除的版本以及其他在wiki上被限制访问的数据。\n\n请考虑将数据库统一放置在某处,如<code>/var/lib/mediawiki/yourwiki</code>下。",
        "config-oracle-def-ts": "默认表空间:",
        "config-oracle-temp-ts": "临时表空间:",
        "config-type-mysql": "MySQL(或兼容程序)",
        "config-sqlite-readonly": "文件<code>$1</code>不可写。",
        "config-sqlite-cant-create-db": "无法创建数据文件<code>$1</code>。",
        "config-sqlite-fts3-downgrade": "PHP缺少FTS3支持,正在降级数据表",
-       "config-can-upgrade": "在数据库中发现了MediaWiki的数据表。要将它们升级至MediaWiki $1,请点击'''继续'''。",
-       "config-upgrade-done": "升级完成。\n\n现在您可以[$1 开始使用您的wiki]了。\n\n如果您需要重新生成<code>LocalSettings.php</code>文件,请点击下面的按钮。除非您的wiki出现了问题,我们'''不推荐'''您执行此操作。",
+       "config-can-upgrade": "在数据库中发现了MediaWiki的数据表。要将它们升级至MediaWiki $1,请点击<strong>继续</strong>。",
+       "config-upgrade-done": "升级完成。\n\n现在您可以[$1 开始使用您的wiki]了。\n\n如果您需要重新生成<code>LocalSettings.php</code>文件,请点击下面的按钮。除非您的wiki出现了问题,我们<strong>不推荐</strong>您执行此操作。",
        "config-upgrade-done-no-regenerate": "升级完成。\n\n现在您可以[$1 开始使用您的wiki]了。",
        "config-regenerate": "重新生成LocalSettings.php →",
        "config-show-table-status": "<code>SHOW TABLE STATUS</code>语句执行失败!",
-       "config-unknown-collation": "'''警告:'''数据库使用了无法识别的整理。",
+       "config-unknown-collation": "<strong>警告:</strong>数据库使用了无法识别的整理。",
        "config-db-web-account": "供网页访问使用的数据库帐号",
        "config-db-web-help": "请指定在wiki执行普通操作时,网页服务器用于连接数据库服务器的用户名和密码。",
        "config-db-web-account-same": "使用和安装程序相同的帐号",
        "config-mysql-engine": "存储引擎:",
        "config-mysql-innodb": "InnoDB",
        "config-mysql-myisam": "MyISAM",
-       "config-mysql-myisam-dep": "'''警告''':您选择了MyISAM作为MySQL的存储引擎,MediaWiki并不推荐您这么做,因为:\n* 它仅能通过表锁定来勉强支持并发\n* 与其他引擎相比,它更容易被损坏\n* MediaWiki代码库并不总会去处理MyISAM\n\n如果您的MySQL程序支持InnoDB,我们高度推荐您使用该引擎替代MyISAM。\n如果您的MySQL程序不支持InnoDB,请考虑升级。",
+       "config-mysql-myisam-dep": "<strong>警告:</strong>您选择了MyISAM作为MySQL的存储引擎,MediaWiki并不推荐您这么做,因为:\n* 它仅能通过表锁定来勉强支持并发\n* 与其他引擎相比,它更容易被损坏\n* MediaWiki代码库并不总会去处理MyISAM\n\n如果您的MySQL程序支持InnoDB,我们高度推荐您使用该引擎替代MyISAM。\n如果您的MySQL程序不支持InnoDB,请考虑升级。",
        "config-mysql-only-myisam-dep": "<strong>警告:</strong>MyISAM是MySQL在此机器上唯一可用的存储引擎,但它不适合用于MediaWiki,因为:\n*因为表级锁定,它几乎不支持并发。\n*它相比其他引擎更容易损坏。\n*MediaWiki代码不能总是按照预期操作MyISAM。\n\n你的MySQL不支持InnoDB,是时候升级了。",
-       "config-mysql-engine-help": "'''InnoDB'''通常是最佳选项,因为它对并发操作有着良好的支持。\n\n'''MyISAM'''在单用户或只读环境下可能会有更快的性能表现。但MyISAM数据库出错的概率一般要大于InnoDB数据库。",
+       "config-mysql-engine-help": "<strong>InnoDB</strong>通常是最佳选项,因为它对并发操作有着良好的支持。\n\n<strong>MyISAM</strong>在单用户或只读环境下可能会有更快的性能表现。但MyISAM数据库出错的概率一般要大于InnoDB数据库。",
        "config-mysql-charset": "数据库字符集:",
        "config-mysql-binary": "二进制",
        "config-mysql-utf8": "UTF-8",
-       "config-mysql-charset-help": "在'''二进制模式'''下,MediaWiki会将UTF-8编码的文本存于数据库的二进制字段中。相对于MySQL的UTF-8模式,这种方法效率更高,并允许您使用全范围的Unicode字符。\n\n在'''UTF-8模式'''下,MySQL将知道您数据使用的字符集,并能适当地提供和转换内容。但这样做您将无法在数据库中存储[//zh.wikipedia.org/wiki/基本多文种平面 基本多文种平面]以外的字符。",
+       "config-mysql-charset-help": "在<strong>二进制模式</strong>下,MediaWiki会将UTF-8编码的文本存于数据库的二进制字段中。相对于MySQL的UTF-8模式,这种方法效率更高,并允许您使用全范围的Unicode字符。\n\n在<strong>UTF-8模式</strong>下,MySQL将知道您数据使用的字符集,并能适当地提供和转换内容。但这样做您将无法在数据库中存储[//zh.wikipedia.org/wiki/基本多文种平面 基本多文种平面]以外的字符。",
        "config-mssql-auth": "身份验证类型:",
        "config-mssql-install-auth": "选择安装过程中链接数据库时将采用的身份验证方式。\n如果您选择“{{int:config-mssql-windowsauth}}”,将使用运行服务器的用户的身份凭据。",
        "config-mssql-web-auth": "选择Web服务器在通常wiki操作期间用来连接数据库服务器的身份验证方式。\n如果您选择“{{int:config-mssql-windowsauth}}”,将使用运行Web服务器的用户的凭据。",
index 4ab9f5a..3919318 100644 (file)
@@ -208,7 +208,12 @@ class JobRunner implements LoggerAwareInterface {
                                // other wikis in the farm (on different masters) get a chance.
                                $timePassed = microtime( true ) - $lastCheckTime;
                                if ( $timePassed >= self::LAG_CHECK_PERIOD || $timePassed < 0 ) {
-                                       if ( !wfWaitForSlaves( $lastCheckTime, false, '*', self::MAX_ALLOWED_LAG ) ) {
+                                       try {
+                                               wfGetLBFactory()->waitForReplication( array(
+                                                       'ifWritesSince' => $lastCheckTime,
+                                                       'timeout' => self::MAX_ALLOWED_LAG
+                                               ) );
+                                       } catch ( DBReplicationWaitError $e ) {
                                                $response['reached'] = 'slave-lag-limit';
                                                break;
                                        }
index f146e6e..13e36d8 100644 (file)
@@ -41,7 +41,8 @@ class ActivityUpdateJob extends Job {
                if ( $this->params['type'] === 'updateWatchlistNotification' ) {
                        $this->updateWatchlistNotification();
                } else {
-                       throw new Exception( "Invalid 'type' parameter '{$this->params['type']}'." );
+                       throw new InvalidArgumentException(
+                               "Invalid 'type' parameter '{$this->params['type']}'." );
                }
 
                return true;
index c9e20a9..5dc2acb 100644 (file)
@@ -49,21 +49,22 @@ class CategoryMembershipChangeJob extends Job {
                }
 
                $dbw = wfGetDB( DB_MASTER );
-
                // Use a named lock so that jobs for this page see each others' changes
-               $fname = __METHOD__;
                $lockKey = "CategoryMembershipUpdates:{$page->getId()}";
-               if ( !$dbw->lock( $lockKey, $fname, 10 ) ) {
+               $scopedLock = $dbw->getScopedLockAndFlush( $lockKey, __METHOD__, 10 );
+               if ( !$scopedLock ) {
                        $this->setLastError( "Could not acquire lock '$lockKey'" );
                        return false;
                }
 
-               $unlocker = new ScopedCallback( function () use ( $dbw, $lockKey, $fname ) {
-                       $dbw->unlock( $lockKey, $fname );
-               } );
-
-               // Sanity: clear any DB transaction snapshot
-               $dbw->commit( __METHOD__, 'flush' );
+               $dbr = wfGetDB( DB_SLAVE, array( 'recentchanges' ) );
+               // Wait till the slave is caught up so that jobs for this page see each others' changes
+               if ( !wfGetLB()->safeWaitForMasterPos( $dbr ) ) {
+                       $this->setLastError( "Timed out while waiting for slave to catch up" );
+                       return false;
+               }
+               // Clear any stale REPEATABLE-READ snapshot
+               $dbr->commit( __METHOD__, 'flush' );
 
                $cutoffUnix = wfTimestamp( TS_UNIX, $this->params['revTimestamp'] );
                // Using ENQUEUE_FUDGE_SEC handles jobs inserted out of revision order due to the delay
@@ -71,12 +72,12 @@ class CategoryMembershipChangeJob extends Job {
                $cutoffUnix -= self::ENQUEUE_FUDGE_SEC;
 
                // Get the newest revision that has a SRC_CATEGORIZE row...
-               $row = $dbw->selectRow(
+               $row = $dbr->selectRow(
                        array( 'revision', 'recentchanges' ),
                        array( 'rev_timestamp', 'rev_id' ),
                        array(
                                'rev_page' => $page->getId(),
-                               'rev_timestamp >= ' . $dbw->addQuotes( $dbw->timestamp( $cutoffUnix ) )
+                               'rev_timestamp >= ' . $dbr->addQuotes( $dbr->timestamp( $cutoffUnix ) )
                        ),
                        __METHOD__,
                        array( 'ORDER BY' => 'rev_timestamp DESC, rev_id DESC' ),
@@ -103,8 +104,8 @@ class CategoryMembershipChangeJob extends Job {
 
                // Find revisions to this page made around and after this revision which lack category
                // notifications in recent changes. This lets jobs pick up were the last one left off.
-               $encCutoff = $dbw->addQuotes( $dbw->timestamp( $cutoffUnix ) );
-               $res = $dbw->select(
+               $encCutoff = $dbr->addQuotes( $dbr->timestamp( $cutoffUnix ) );
+               $res = $dbr->select(
                        'revision',
                        Revision::selectFields(),
                        array(
@@ -121,8 +122,6 @@ class CategoryMembershipChangeJob extends Job {
                        $this->notifyUpdatesForRevision( $page, Revision::newFromRow( $row ) );
                }
 
-               ScopedCallback::consume( $unlocker );
-
                return true;
        }
 
@@ -169,7 +168,7 @@ class CategoryMembershipChangeJob extends Job {
                        $catMembChange->triggerCategoryAddedNotification( $categoryTitle );
                        if ( $insertCount++ && ( $insertCount % $batchSize ) == 0 ) {
                                $dbw->commit( __METHOD__, 'flush' );
-                               wfWaitForSlaves();
+                               wfGetLBFactory()->waitForReplication();
                        }
                }
 
@@ -178,7 +177,7 @@ class CategoryMembershipChangeJob extends Job {
                        $catMembChange->triggerCategoryRemovedNotification( $categoryTitle );
                        if ( $insertCount++ && ( $insertCount++ % $batchSize ) == 0 ) {
                                $dbw->commit( __METHOD__, 'flush' );
-                               wfWaitForSlaves();
+                               wfGetLBFactory()->waitForReplication();
                        }
                }
        }
index df0a66e..0d48cb3 100644 (file)
@@ -120,7 +120,7 @@ class HTMLCacheUpdateJob extends Job {
                // Check $wgUpdateRowsPerQuery for sanity; batch jobs are sized by that already.
                foreach ( array_chunk( $pageIds, $wgUpdateRowsPerQuery ) as $batch ) {
                        $dbw->commit( __METHOD__, 'flush' );
-                       wfWaitForSlaves();
+                       wfGetLBFactory()->waitForReplication();
 
                        $dbw->update( 'page',
                                array( 'page_touched' => $dbw->timestamp( $touchTimestamp ) ),
index d6fa26b..0685299 100644 (file)
@@ -98,7 +98,9 @@ class RecentChangesUpdateJob extends Job {
 
                        if ( count( $rcIds ) === $batchSize ) {
                                // There might be more, so try waiting for slaves
-                               if ( !wfWaitForSlaves( null, false, false, /* $timeout = */ 3 ) ) {
+                               try {
+                                       wfGetLBFactory()->waitForReplication( array( 'timeout' => 3 ) );
+                               } catch ( DBReplicationWaitError $e ) {
                                        // Another job will continue anyway
                                        break;
                                }
@@ -125,7 +127,7 @@ class RecentChangesUpdateJob extends Job {
 
                        $lockKey = wfWikiID() . '-activeusers';
                        if ( !$dbw->lock( $lockKey, __METHOD__, 1 ) ) {
-                               return false; // exclusive update (avoids duplicate entries)
+                               return; // exclusive update (avoids duplicate entries)
                        }
 
                        $nowUnix = time();
@@ -203,7 +205,7 @@ class RecentChangesUpdateJob extends Job {
                                }
                                foreach ( array_chunk( $newRows, 500 ) as $rowBatch ) {
                                        $dbw->insert( 'querycachetwo', $rowBatch, __METHOD__ );
-                                       wfWaitForSlaves();
+                                       wfGetLBFactory()->waitForReplication();
                                }
                        }
 
index e2d9946..b99cb41 100644 (file)
@@ -67,7 +67,7 @@ class LogFormatter {
        /**
         * Handy shortcut for constructing a formatter directly from
         * database row.
-        * @param object $row
+        * @param stdClass|array $row
         * @see DatabaseLogEntry::getSelectQueryData
         * @return LogFormatter
         */
@@ -237,7 +237,7 @@ class LogFormatter {
                                        // @codingStandardsIgnoreStart Long line
                                        //case 'revision': // Revision deletion
                                        //case 'event': // Log deletion
-                                       // see https://svn.wikimedia.org/viewvc/mediawiki/trunk/phase3/includes/LogPage.php?&pathrev=97044&r1=97043&r2=97044
+                                       // see https://github.com/wikimedia/mediawiki/commit/a9c243b7b5289dad204278dbe7ed571fd914e395
                                        //default:
                                        // @codingStandardsIgnoreEnd
                                }
@@ -245,7 +245,7 @@ class LogFormatter {
 
                        case 'patrol':
                                // @codingStandardsIgnoreStart Long line
-                               // https://svn.wikimedia.org/viewvc/mediawiki/trunk/phase3/includes/PatrolLog.php?&pathrev=97495&r1=97494&r2=97495
+                               // https://github.com/wikimedia/mediawiki/commit/1a05f8faf78675dc85984f27f355b8825b43efff
                                // @codingStandardsIgnoreEnd
                                // Create a diff link to the patrolled revision
                                if ( $entry->getSubtype() === 'patrol' ) {
index 5a58c33..b62bcb4 100644 (file)
@@ -38,10 +38,10 @@ class TagLogFormatter extends LogFormatter {
                $remove = ( isset( $params[8] ) && isset( $params[8]['num'] ) && $params[8]['num'] );
                $key .= ( $remove ? ( $add ? '' : '-remove' ) : '-add' );
 
-               if ( isset( $params[4] ) && $params[4] ) {
-                       $key .= '-logentry';
-               } else {
+               if ( isset( $params[3] ) && $params[3] ) {
                        $key .= '-revision';
+               } else {
+                       $key .= '-logentry';
                }
 
                return $key;
index f557c1a..8bac6b8 100644 (file)
@@ -138,7 +138,7 @@ class EmailNotification {
        public function notifyOnPageChange( $editor, $title, $timestamp, $summary,
                $minorEdit, $oldid = false, $pageStatus = 'changed'
        ) {
-               global $wgEnotifUseJobQ, $wgEnotifMinorEdits, $wgUsersNotifiedOnAllChanges, $wgEnotifUserTalk;
+               global $wgEnotifMinorEdits, $wgUsersNotifiedOnAllChanges, $wgEnotifUserTalk;
 
                if ( $title->getNamespace() < 0 ) {
                        return;
@@ -166,34 +166,20 @@ class EmailNotification {
                        }
                }
 
-               if ( !$sendEmail ) {
-                       return;
-               }
-
-               if ( $wgEnotifUseJobQ ) {
-                       $params = array(
-                               'editor' => $editor->getName(),
-                               'editorID' => $editor->getID(),
-                               'timestamp' => $timestamp,
-                               'summary' => $summary,
-                               'minorEdit' => $minorEdit,
-                               'oldid' => $oldid,
-                               'watchers' => $watchers,
-                               'pageStatus' => $pageStatus
-                       );
-                       $job = new EnotifNotifyJob( $title, $params );
-                       JobQueueGroup::singleton()->lazyPush( $job );
-               } else {
-                       $this->actuallyNotifyOnPageChange(
-                               $editor,
+               if ( $sendEmail ) {
+                       JobQueueGroup::singleton()->lazyPush( new EnotifNotifyJob(
                                $title,
-                               $timestamp,
-                               $summary,
-                               $minorEdit,
-                               $oldid,
-                               $watchers,
-                               $pageStatus
-                       );
+                               array(
+                                       'editor' => $editor->getName(),
+                                       'editorID' => $editor->getID(),
+                                       'timestamp' => $timestamp,
+                                       'summary' => $summary,
+                                       'minorEdit' => $minorEdit,
+                                       'oldid' => $oldid,
+                                       'watchers' => $watchers,
+                                       'pageStatus' => $pageStatus
+                               )
+                       ) );
                }
        }
 
index faf40b3..9ac5e6b 100644 (file)
@@ -59,6 +59,43 @@ class BitmapHandler extends TransformationalImageHandler {
                return $scaler;
        }
 
+       function makeParamString( $params ) {
+               $res = parent::makeParamString( $params );
+               if ( isset( $params['interlace'] ) && $params['interlace'] ) {
+                       return "interlaced-{$res}";
+               } else {
+                       return $res;
+               }
+       }
+
+       function parseParamString( $str ) {
+               $remainder = preg_replace( '/^interlaced-/', '', $str );
+               $params = parent::parseParamString( $remainder );
+               if ( $params === false ) {
+                       return false;
+               }
+               $params['interlace'] = $str !== $remainder;
+               return $params;
+       }
+
+       /**
+        * @param File $image
+        * @param array $params
+        * @return bool
+        */
+       function normaliseParams( $image, &$params ) {
+               global $wgMaxInterlacingAreas;
+               if ( !parent::normaliseParams( $image, $params ) ) {
+                       return false;
+               }
+               $mimeType = $image->getMimeType();
+               $interlace = isset( $params['interlace'] ) && $params['interlace']
+                       && isset( $wgMaxInterlacingAreas[$mimeType] )
+                       && $this->getImageArea( $image ) <= $wgMaxInterlacingAreas[$mimeType];
+               $params['interlace'] = $interlace;
+               return true;
+       }
+
        /**
         * Transform an image using ImageMagick
         *
@@ -70,7 +107,7 @@ class BitmapHandler extends TransformationalImageHandler {
        protected function transformImageMagick( $image, $params ) {
                # use ImageMagick
                global $wgSharpenReductionThreshold, $wgSharpenParameter, $wgMaxAnimatedGifArea,
-                       $wgImageMagickTempDir, $wgImageMagickConvertCommand;
+                       $wgImageMagickTempDir, $wgImageMagickConvertCommand, $wgMaxInterlacingAreas;
 
                $quality = array();
                $sharpen = array();
@@ -78,9 +115,13 @@ class BitmapHandler extends TransformationalImageHandler {
                $animation_pre = array();
                $animation_post = array();
                $decoderHint = array();
+
                if ( $params['mimeType'] == 'image/jpeg' ) {
                        $qualityVal = isset( $params['quality'] ) ? (string)$params['quality'] : null;
                        $quality = array( '-quality', $qualityVal ?: '80' ); // 80%
+                       if ( $params['interlace'] ) {
+                               $animation_post = array( '-interlace', 'JPEG' );
+                       }
                        # Sharpening, see bug 6193
                        if ( ( $params['physicalWidth'] + $params['physicalHeight'] )
                                / ( $params['srcWidth'] + $params['srcHeight'] )
@@ -92,7 +133,12 @@ class BitmapHandler extends TransformationalImageHandler {
                                // JPEG decoder hint to reduce memory, available since IM 6.5.6-2
                                $decoderHint = array( '-define', "jpeg:size={$params['physicalDimensions']}" );
                        }
-               } elseif ( $params['mimeType'] == 'image/png' || $params['mimeType'] == 'image/webp' ) {
+               } elseif ( $params['mimeType'] == 'image/png' ) {
+                       $quality = array( '-quality', '95' ); // zlib 9, adaptive filtering
+                       if ( $params['interlace'] ) {
+                               $animation_post = array( '-interlace', 'PNG' );
+                       }
+               } elseif ( $params['mimeType'] == 'image/webp' ) {
                        $quality = array( '-quality', '95' ); // zlib 9, adaptive filtering
                } elseif ( $params['mimeType'] == 'image/gif' ) {
                        if ( $this->getImageArea( $image ) > $wgMaxAnimatedGifArea ) {
@@ -108,6 +154,11 @@ class BitmapHandler extends TransformationalImageHandler {
                                        $animation_post = array( '-fuzz', '5%', '-layers', 'optimizeTransparency' );
                                }
                        }
+                       if ( $params['interlace'] && version_compare( $this->getMagickVersion(), "6.3.4" ) >= 0
+                               && !$this->isAnimatedImage( $image ) ) { // interlacing animated GIFs is a bad idea
+                               $animation_post[] = '-interlace';
+                               $animation_post[] = 'GIF';
+                       }
                } elseif ( $params['mimeType'] == 'image/x-xcf' ) {
                        // Before merging layers, we need to set the background
                        // to be transparent to preserve alpha, as -layers merge
@@ -191,7 +242,8 @@ class BitmapHandler extends TransformationalImageHandler {
         * @return MediaTransformError Error object if error occurred, false (=no error) otherwise
         */
        protected function transformImageMagickExt( $image, $params ) {
-               global $wgSharpenReductionThreshold, $wgSharpenParameter, $wgMaxAnimatedGifArea;
+               global $wgSharpenReductionThreshold, $wgSharpenParameter, $wgMaxAnimatedGifArea,
+                       $wgMaxInterlacingAreas;
 
                try {
                        $im = new Imagick();
@@ -209,8 +261,14 @@ class BitmapHandler extends TransformationalImageHandler {
                                }
                                $qualityVal = isset( $params['quality'] ) ? (string)$params['quality'] : null;
                                $im->setCompressionQuality( $qualityVal ?: 80 );
+                               if ( $params['interlace'] ) {
+                                       $im->setInterlaceScheme( Imagick::INTERLACE_JPEG );
+                               }
                        } elseif ( $params['mimeType'] == 'image/png' ) {
                                $im->setCompressionQuality( 95 );
+                               if ( $params['interlace'] ) {
+                                       $im->setInterlaceScheme( Imagick::INTERLACE_PNG );
+                               }
                        } elseif ( $params['mimeType'] == 'image/gif' ) {
                                if ( $this->getImageArea( $image ) > $wgMaxAnimatedGifArea ) {
                                        // Extract initial frame only; we're so big it'll
@@ -220,6 +278,13 @@ class BitmapHandler extends TransformationalImageHandler {
                                        // Coalesce is needed to scale animated GIFs properly (bug 1017).
                                        $im = $im->coalesceImages();
                                }
+                               // GIF interlacing is only available since 6.3.4
+                               $v = Imagick::getVersion();
+                               preg_match( '/ImageMagick ([0-9]+\.[0-9]+\.[0-9]+)/', $v['versionString'], $v );
+
+                               if ( $params['interlace'] && version_compare( $v[1], '6.3.4' ) >= 0 ) {
+                                       $im->setInterlaceScheme( Imagick::INTERLACE_GIF );
+                               }
                        }
 
                        $rotation = isset( $params['disableRotation'] ) ? 0 : $this->getRotation( $image );
index f72df19..597ac26 100644 (file)
@@ -126,6 +126,7 @@ abstract class TransformationalImageHandler extends ImageHandler {
                        'mimeType' => $image->getMimeType(),
                        'dstPath' => $dstPath,
                        'dstUrl' => $dstUrl,
+                       'interlace' => isset( $params['interlace'] ) ? $params['interlace'] : false,
                );
 
                if ( isset( $params['quality'] ) && $params['quality'] === 'low' ) {
index 5776519..0e3c9eb 100644 (file)
@@ -735,7 +735,12 @@ class SqlBagOStuff extends BagOStuff {
        protected function waitForSlaves() {
                if ( !$this->serverInfos ) {
                        // Main LB is used; wait for any slaves to catch up
-                       return wfWaitForSlaves( null, false, false, $this->syncTimeout );
+                       try {
+                               wfGetLBFactory()->waitForReplication( array( 'wiki' => wfWikiID() ) );
+                               return true;
+                       } catch ( DBReplicationWaitError $e ) {
+                               return false;
+                       }
                } else {
                        // Custom DB server list; probably doesn't use replication
                        return true;
index f16158b..938c049 100644 (file)
@@ -2084,22 +2084,574 @@ class Article implements Page {
        }
 
        /**
-        * Use PHP's magic __call handler to transform instance calls to
-        * WikiPage functions for backwards compatibility.
-        *
-        * @param string $fname Name of called method
-        * @param array $args Arguments to the method
-        * @return mixed
+        * Call to WikiPage function for backwards compatibility.
+        * @see WikiPage::checkFlags
         */
-       public function __call( $fname, $args ) {
-               if ( is_callable( array( $this->mPage, $fname ) ) ) {
-                       # wfWarn( "Call to " . __CLASS__ . "::$fname; please use WikiPage instead" );
-                       return call_user_func_array( array( $this->mPage, $fname ), $args );
-               }
-               trigger_error( 'Inaccessible function via __call(): ' . $fname, E_USER_ERROR );
+       public function checkFlags( $flags ) {
+               return $this->mPage->checkFlags( $flags );
+       }
+
+       /**
+        * Call to WikiPage function for backwards compatibility.
+        * @see WikiPage::checkTouched
+        */
+       public function checkTouched() {
+               return $this->mPage->checkTouched();
+       }
+
+       /**
+        * Call to WikiPage function for backwards compatibility.
+        * @see WikiPage::clearPreparedEdit
+        */
+       public function clearPreparedEdit() {
+               return $this->mPage->clearPreparedEdit();
+       }
+
+       /**
+        * Call to WikiPage function for backwards compatibility.
+        * @see WikiPage::doDeleteArticleReal
+        */
+       public function doDeleteArticleReal(
+               $reason, $suppress = false, $u1 = null, $u2 = null, &$error = '', User $user = null
+       ) {
+               return $this->mPage->doDeleteArticleReal(
+                       $reason, $suppress, $u1, $u2, $error, $user
+               );
+       }
+
+       /**
+        * Call to WikiPage function for backwards compatibility.
+        * @see WikiPage::doDeleteUpdates
+        */
+       public function doDeleteUpdates( $id, Content $content = null ) {
+               return $this->mPage->doDeleteUpdates( $id, $content );
+       }
+
+       /**
+        * Call to WikiPage function for backwards compatibility.
+        * @see WikiPage::doEdit
+        */
+       public function doEdit( $text, $summary, $flags = 0, $baseRevId = false, $user = null ) {
+               ContentHandler::deprecated( __METHOD__, '1.21' );
+               return $this->mPage->doEdit( $text, $summary, $flags, $baseRevId, $user );
+       }
+
+       /**
+        * Call to WikiPage function for backwards compatibility.
+        * @see WikiPage::doEditContent
+        */
+       public function doEditContent( Content $content, $summary, $flags = 0, $baseRevId = false,
+               User $user = null, $serialFormat = null
+       ) {
+               return $this->mPage->doEditContent( $content, $summary, $flags, $baseRevId,
+                       $user, $serialFormat
+               );
+       }
+
+       /**
+        * Call to WikiPage function for backwards compatibility.
+        * @see WikiPage::doEditUpdates
+        */
+       public function doEditUpdates( Revision $revision, User $user, array $options = array() ) {
+               return $this->mPage->doEditUpdates( $revision, $user, $options );
        }
 
-       // ****** B/C functions to work-around PHP silliness with __call and references ****** //
+       /**
+        * Call to WikiPage function for backwards compatibility.
+        * @see WikiPage::doPurge
+        */
+       public function doPurge() {
+               return $this->mPage->doPurge();
+       }
+
+       /**
+        * Call to WikiPage function for backwards compatibility.
+        * @see WikiPage::doQuickEditContent
+        */
+       public function doQuickEditContent(
+               Content $content, User $user, $comment = '', $minor = false, $serialFormat = null
+       ) {
+               return $this->mPage->doQuickEditContent(
+                       $content, $user, $comment, $minor, $serialFormat
+               );
+       }
+
+       /**
+        * Call to WikiPage function for backwards compatibility.
+        * @see WikiPage::doViewUpdates
+        */
+       public function doViewUpdates( User $user, $oldid = 0 ) {
+               return $this->mPage->doViewUpdates( $user, $oldid );
+       }
+
+       /**
+        * Call to WikiPage function for backwards compatibility.
+        * @see WikiPage::exists
+        */
+       public function exists() {
+               return $this->mPage->exists();
+       }
+
+       /**
+        * Call to WikiPage function for backwards compatibility.
+        * @see WikiPage::followRedirect
+        */
+       public function followRedirect() {
+               return $this->mPage->followRedirect();
+       }
+
+       /**
+        * Call to WikiPage function for backwards compatibility.
+        * @see WikiPage::getActionOverrides
+        */
+       public function getActionOverrides() {
+               return $this->mPage->getActionOverrides();
+       }
+
+       /**
+        * Call to WikiPage function for backwards compatibility.
+        * @see WikiPage::getAutoDeleteReason
+        */
+       public function getAutoDeleteReason( &$hasHistory ) {
+               return $this->mPage->getAutoDeleteReason( $hasHistory );
+       }
+
+       /**
+        * Call to WikiPage function for backwards compatibility.
+        * @see WikiPage::getCategories
+        */
+       public function getCategories() {
+               return $this->mPage->getCategories();
+       }
+
+       /**
+        * Call to WikiPage function for backwards compatibility.
+        * @see WikiPage::getComment
+        */
+       public function getComment( $audience = Revision::FOR_PUBLIC, User $user = null ) {
+               return $this->mPage->getComment( $audience, $user );
+       }
+
+       /**
+        * Call to WikiPage function for backwards compatibility.
+        * @see WikiPage::getContentHandler
+        */
+       public function getContentHandler() {
+               return $this->mPage->getContentHandler();
+       }
+
+       /**
+        * Call to WikiPage function for backwards compatibility.
+        * @see WikiPage::getContentModel
+        */
+       public function getContentModel() {
+               return $this->mPage->getContentModel();
+       }
+
+       /**
+        * Call to WikiPage function for backwards compatibility.
+        * @see WikiPage::getContributors
+        */
+       public function getContributors() {
+               return $this->mPage->getContributors();
+       }
+
+       /**
+        * Call to WikiPage function for backwards compatibility.
+        * @see WikiPage::getCreator
+        */
+       public function getCreator( $audience = Revision::FOR_PUBLIC, User $user = null ) {
+               return $this->mPage->getCreator( $audience, $user );
+       }
+
+       /**
+        * Call to WikiPage function for backwards compatibility.
+        * @see WikiPage::getDeletionUpdates
+        */
+       public function getDeletionUpdates( Content $content = null ) {
+               return $this->mPage->getDeletionUpdates( $content );
+       }
+
+       /**
+        * Call to WikiPage function for backwards compatibility.
+        * @see WikiPage::getHiddenCategories
+        */
+       public function getHiddenCategories() {
+               return $this->mPage->getHiddenCategories();
+       }
+
+       /**
+        * Call to WikiPage function for backwards compatibility.
+        * @see WikiPage::getId
+        */
+       public function getId() {
+               return $this->mPage->getId();
+       }
+
+       /**
+        * Call to WikiPage function for backwards compatibility.
+        * @see WikiPage::getLatest
+        */
+       public function getLatest() {
+               return $this->mPage->getLatest();
+       }
+
+       /**
+        * Call to WikiPage function for backwards compatibility.
+        * @see WikiPage::getLinksTimestamp
+        */
+       public function getLinksTimestamp() {
+               return $this->mPage->getLinksTimestamp();
+       }
+
+       /**
+        * Call to WikiPage function for backwards compatibility.
+        * @see WikiPage::getMinorEdit
+        */
+       public function getMinorEdit() {
+               return $this->mPage->getMinorEdit();
+       }
+
+       /**
+        * Call to WikiPage function for backwards compatibility.
+        * @see WikiPage::getOldestRevision
+        */
+       public function getOldestRevision() {
+               return $this->mPage->getOldestRevision();
+       }
+
+       /**
+        * Call to WikiPage function for backwards compatibility.
+        * @see WikiPage::getRedirectTarget
+        */
+       public function getRedirectTarget() {
+               return $this->mPage->getRedirectTarget();
+       }
+
+       /**
+        * Call to WikiPage function for backwards compatibility.
+        * @see WikiPage::getRedirectURL
+        */
+       public function getRedirectURL( $rt ) {
+               return $this->mPage->getRedirectURL( $rt );
+       }
+
+       /**
+        * Call to WikiPage function for backwards compatibility.
+        * @see WikiPage::getRevision
+        */
+       public function getRevision() {
+               return $this->mPage->getRevision();
+       }
+
+       /**
+        * Call to WikiPage function for backwards compatibility.
+        * @see WikiPage::getText
+        */
+       public function getText( $audience = Revision::FOR_PUBLIC, User $user = null ) {
+               ContentHandler::deprecated( __METHOD__, '1.21' );
+               return $this->mPage->getText( $audience, $user );
+       }
+
+       /**
+        * Call to WikiPage function for backwards compatibility.
+        * @see WikiPage::getTimestamp
+        */
+       public function getTimestamp() {
+               return $this->mPage->getTimestamp();
+       }
+
+       /**
+        * Call to WikiPage function for backwards compatibility.
+        * @see WikiPage::getTouched
+        */
+       public function getTouched() {
+               return $this->mPage->getTouched();
+       }
+
+       /**
+        * Call to WikiPage function for backwards compatibility.
+        * @see WikiPage::getUndoContent
+        */
+       public function getUndoContent( Revision $undo, Revision $undoafter = null ) {
+               return $this->mPage->getUndoContent( $undo, $undoafter );
+       }
+
+       /**
+        * Call to WikiPage function for backwards compatibility.
+        * @see WikiPage::getUndoText
+        */
+       public function getUndoText( Revision $undo, Revision $undoafter = null ) {
+               ContentHandler::deprecated( __METHOD__, '1.21' );
+               return $this->mPage->getUndoText( $undo, $undoafter );
+       }
+
+       /**
+        * Call to WikiPage function for backwards compatibility.
+        * @see WikiPage::getUser
+        */
+       public function getUser( $audience = Revision::FOR_PUBLIC, User $user = null ) {
+               return $this->mPage->getUser( $audience, $user );
+       }
+
+       /**
+        * Call to WikiPage function for backwards compatibility.
+        * @see WikiPage::getUserText
+        */
+       public function getUserText( $audience = Revision::FOR_PUBLIC, User $user = null ) {
+               return $this->mPage->getUserText( $audience, $user );
+       }
+
+       /**
+        * Call to WikiPage function for backwards compatibility.
+        * @see WikiPage::hasViewableContent
+        */
+       public function hasViewableContent() {
+               return $this->mPage->hasViewableContent();
+       }
+
+       /**
+        * Call to WikiPage function for backwards compatibility.
+        * @see WikiPage::insertOn
+        */
+       public function insertOn( $dbw, $pageId = null ) {
+               return $this->mPage->insertOn( $dbw, $pageId );
+       }
+
+       /**
+        * Call to WikiPage function for backwards compatibility.
+        * @see WikiPage::insertProtectNullRevision
+        */
+       public function insertProtectNullRevision( $revCommentMsg, array $limit,
+               array $expiry, $cascade, $reason, $user = null
+       ) {
+               return $this->mPage->insertProtectNullRevision( $revCommentMsg, $limit,
+                       $expiry, $cascade, $reason, $user
+               );
+       }
+
+       /**
+        * Call to WikiPage function for backwards compatibility.
+        * @see WikiPage::insertRedirect
+        */
+       public function insertRedirect() {
+               return $this->mPage->insertRedirect();
+       }
+
+       /**
+        * Call to WikiPage function for backwards compatibility.
+        * @see WikiPage::insertRedirectEntry
+        */
+       public function insertRedirectEntry( Title $rt, $oldLatest = null ) {
+               return $this->mPage->insertRedirectEntry( $rt, $oldLatest );
+       }
+
+       /**
+        * Call to WikiPage function for backwards compatibility.
+        * @see WikiPage::isCountable
+        */
+       public function isCountable( $editInfo = false ) {
+               return $this->mPage->isCountable( $editInfo );
+       }
+
+       /**
+        * Call to WikiPage function for backwards compatibility.
+        * @see WikiPage::isRedirect
+        */
+       public function isRedirect() {
+               return $this->mPage->isRedirect();
+       }
+
+       /**
+        * Call to WikiPage function for backwards compatibility.
+        * @see WikiPage::loadFromRow
+        */
+       public function loadFromRow( $data, $from ) {
+               return $this->mPage->loadFromRow( $data, $from );
+       }
+
+       /**
+        * Call to WikiPage function for backwards compatibility.
+        * @see WikiPage::loadPageData
+        */
+       public function loadPageData( $from = 'fromdb' ) {
+               return $this->mPage->loadPageData( $from );
+       }
+
+       /**
+        * Call to WikiPage function for backwards compatibility.
+        * @see WikiPage::lockAndGetLatest
+        */
+       public function lockAndGetLatest() {
+               return $this->mPage->lockAndGetLatest();
+       }
+
+       /**
+        * Call to WikiPage function for backwards compatibility.
+        * @see WikiPage::makeParserOptions
+        */
+       public function makeParserOptions( $context ) {
+               return $this->mPage->makeParserOptions( $context );
+       }
+
+       /**
+        * Call to WikiPage function for backwards compatibility.
+        * @see WikiPage::pageDataFromId
+        */
+       public function pageDataFromId( $dbr, $id, $options = array() ) {
+               return $this->mPage->pageDataFromId( $dbr, $id, $options );
+       }
+
+       /**
+        * Call to WikiPage function for backwards compatibility.
+        * @see WikiPage::pageDataFromTitle
+        */
+       public function pageDataFromTitle( $dbr, $title, $options = array() ) {
+               return $this->mPage->pageDataFromTitle( $dbr, $title, $options );
+       }
+
+       /**
+        * Call to WikiPage function for backwards compatibility.
+        * @see WikiPage::prepareContentForEdit
+        */
+       public function prepareContentForEdit(
+               Content $content, $revision = null, User $user = null,
+               $serialFormat = null, $useCache = true
+       ) {
+               return $this->mPage->prepareContentForEdit(
+                       $content, $revision, $user,
+                       $serialFormat, $useCache
+               );
+       }
+
+       /**
+        * Call to WikiPage function for backwards compatibility.
+        * @see WikiPage::prepareTextForEdit
+        */
+       public function prepareTextForEdit( $text, $revid = null, User $user = null ) {
+               return $this->mPage->prepareTextForEdit( $text, $revid, $user );
+       }
+
+       /**
+        * Call to WikiPage function for backwards compatibility.
+        * @see WikiPage::protectDescription
+        */
+       public function protectDescription( array $limit, array $expiry ) {
+               return $this->mPage->protectDescription( $limit, $expiry );
+       }
+
+       /**
+        * Call to WikiPage function for backwards compatibility.
+        * @see WikiPage::protectDescriptionLog
+        */
+       public function protectDescriptionLog( array $limit, array $expiry ) {
+               return $this->mPage->protectDescriptionLog( $limit, $expiry );
+       }
+
+       /**
+        * Call to WikiPage function for backwards compatibility.
+        * @see WikiPage::replaceSection
+        */
+       public function replaceSection( $sectionId, $text, $sectionTitle = '',
+               $edittime = null
+       ) {
+               ContentHandler::deprecated( __METHOD__, '1.21' );
+               return $this->mPage->replaceSection( $sectionId, $text, $sectionTitle,
+                       $edittime
+               );
+       }
+
+       /**
+        * Call to WikiPage function for backwards compatibility.
+        * @see WikiPage::replaceSectionAtRev
+        */
+       public function replaceSectionAtRev( $sectionId, Content $sectionContent,
+               $sectionTitle = '', $baseRevId = null
+       ) {
+               return $this->mPage->replaceSectionAtRev( $sectionId, $sectionContent,
+                       $sectionTitle, $baseRevId
+               );
+       }
+
+       /**
+        * Call to WikiPage function for backwards compatibility.
+        * @see WikiPage::replaceSectionContent
+        */
+       public function replaceSectionContent(
+               $sectionId, Content $sectionContent, $sectionTitle = '', $edittime = null
+       ) {
+               return $this->mPage->replaceSectionContent(
+                       $sectionId, $sectionContent, $sectionTitle, $edittime
+               );
+       }
+
+       /**
+        * Call to WikiPage function for backwards compatibility.
+        * @see WikiPage::setTimestamp
+        */
+       public function setTimestamp( $ts ) {
+               return $this->mPage->setTimestamp( $ts );
+       }
+
+       /**
+        * Call to WikiPage function for backwards compatibility.
+        * @see WikiPage::shouldCheckParserCache
+        */
+       public function shouldCheckParserCache( ParserOptions $parserOptions, $oldId ) {
+               return $this->mPage->shouldCheckParserCache( $parserOptions, $oldId );
+       }
+
+       /**
+        * Call to WikiPage function for backwards compatibility.
+        * @see WikiPage::supportsSections
+        */
+       public function supportsSections() {
+               return $this->mPage->supportsSections();
+       }
+
+       /**
+        * Call to WikiPage function for backwards compatibility.
+        * @see WikiPage::triggerOpportunisticLinksUpdate
+        */
+       public function triggerOpportunisticLinksUpdate( ParserOutput $parserOutput ) {
+               return $this->mPage->triggerOpportunisticLinksUpdate( $parserOutput );
+       }
+
+       /**
+        * Call to WikiPage function for backwards compatibility.
+        * @see WikiPage::updateCategoryCounts
+        */
+       public function updateCategoryCounts( array $added, array $deleted ) {
+               return $this->mPage->updateCategoryCounts( $added, $deleted );
+       }
+
+       /**
+        * Call to WikiPage function for backwards compatibility.
+        * @see WikiPage::updateIfNewerOn
+        */
+       public function updateIfNewerOn( $dbw, $revision ) {
+               return $this->mPage->updateIfNewerOn( $dbw, $revision );
+       }
+
+       /**
+        * Call to WikiPage function for backwards compatibility.
+        * @see WikiPage::updateRedirectOn
+        */
+       public function updateRedirectOn( $dbw, $redirectTitle, $lastRevIsRedirect = null ) {
+               return $this->mPage->updateRedirectOn( $dbw, $redirectTitle, $lastRevIsRedirect = null );
+       }
+
+       /**
+        * Call to WikiPage function for backwards compatibility.
+        * @see WikiPage::updateRevisionOn
+        */
+       public function updateRevisionOn( $dbw, $revision, $lastRevision = null,
+               $lastRevIsRedirect = null
+       ) {
+               return $this->mPage->updateRevisionOn( $dbw, $revision, $lastRevision,
+                       $lastRevIsRedirect
+               );
+       }
 
        /**
         * @param array $limit
@@ -2185,8 +2737,6 @@ class Article implements Page {
                return $handler->getAutoDeleteReason( $title, $hasHistory );
        }
 
-       // ****** B/C functions for static methods ( __callStatic is PHP>=5.3 ) ****** //
-
        /**
         * @return array
         *
index 6f4c296..c02f975 100644 (file)
@@ -1823,7 +1823,7 @@ class WikiPage implements Page, IDBAccessObject {
                        $revisionId = $revision->insertOn( $dbw );
                        // Update page_latest and friends to reflect the new revision
                        if ( !$this->updateRevisionOn( $dbw, $revision, null, $meta['oldIsRedirect'] ) ) {
-                               $dbw->rollback( __METHOD__ );
+                               $dbw->rollback( __METHOD__ ); // sanity; this should never happen
                                throw new MWException( "Failed to update page row to use new revision." );
                        }
 
@@ -1921,12 +1921,12 @@ class WikiPage implements Page, IDBAccessObject {
                }
 
                $dbw = wfGetDB( DB_MASTER );
-               $dbw->begin( __METHOD__ );
+               $dbw->startAtomic( __METHOD__ );
 
                // Add the page record unless one already exists for the title
                $newid = $this->insertOn( $dbw );
                if ( $newid === false ) {
-                       $dbw->commit( __METHOD__ ); // nothing inserted
+                       $dbw->endAtomic( __METHOD__ ); // nothing inserted
                        $status->fatal( 'edit-already-exists' );
 
                        return $status; // nothing done
@@ -1956,7 +1956,7 @@ class WikiPage implements Page, IDBAccessObject {
                $revisionId = $revision->insertOn( $dbw );
                // Update the page record with revision data
                if ( !$this->updateRevisionOn( $dbw, $revision, 0 ) ) {
-                       $dbw->rollback( __METHOD__ );
+                       $dbw->rollback( __METHOD__ ); // sanity; this should never happen
                        throw new MWException( "Failed to update page row to use new revision." );
                }
 
@@ -1984,25 +1984,34 @@ class WikiPage implements Page, IDBAccessObject {
 
                $user->incEditCount();
 
-               $dbw->commit( __METHOD__ );
+               $dbw->endAtomic( __METHOD__ );
                $this->mTimestamp = $now;
 
-               // Update links, etc.
-               $this->doEditUpdates( $revision, $user, array( 'created' => true ) );
-
-               $hook_args = array( &$this, &$user, $content, $summary,
-                       $flags & EDIT_MINOR, null, null, &$flags, $revision );
-               ContentHandler::runLegacyHooks( 'ArticleInsertComplete', $hook_args );
-               Hooks::run( 'PageContentInsertComplete', $hook_args );
-
                // Return the new revision to the caller
                $status->value['revision'] = $revision;
 
-               // Trigger post-save hook
-               $hook_args = array( &$this, &$user, $content, $summary,
-                       $flags & EDIT_MINOR, null, null, &$flags, $revision, &$status, $meta['baseRevId'] );
-               ContentHandler::runLegacyHooks( 'ArticleSaveComplete', $hook_args );
-               Hooks::run( 'PageContentSaveComplete', $hook_args );
+               // Do secondary updates once the main changes have been committed...
+               $that = $this;
+               $dbw->onTransactionIdle(
+                       function () use (
+                               &$that, $dbw, $revision, &$user, $content, $summary, &$flags, $meta, &$status
+                       ) {
+                               // Do per-page updates in a transaction
+                               $dbw->setFlag( DBO_TRX );
+                               // Update links, etc.
+                               $that->doEditUpdates( $revision, $user, array( 'created' => true ) );
+                               // Trigger post-create hook
+                               $params = array( &$that, &$user, $content, $summary,
+                                       $flags & EDIT_MINOR, null, null, &$flags, $revision );
+                               ContentHandler::runLegacyHooks( 'ArticleInsertComplete', $params );
+                               Hooks::run( 'PageContentInsertComplete', $params );
+                               // Trigger post-save hook
+                               $params = array_merge( $params, array( &$status, $meta['baseRevId'] ) );
+                               ContentHandler::runLegacyHooks( 'ArticleSaveComplete', $params );
+                               Hooks::run( 'PageContentSaveComplete', $params );
+
+                       }
+               );
 
                return $status;
        }
index 113fc84..bcd159f 100644 (file)
@@ -180,6 +180,7 @@ abstract class ResourceLoaderModule implements LoggerAwareInterface {
        /**
         * @since 1.27
         * @param LoggerInterface $logger
+        * @return null
         */
        public function setLogger( LoggerInterface $logger ) {
                $this->logger = $logger;
@@ -410,8 +411,8 @@ abstract class ResourceLoaderModule implements LoggerAwareInterface {
         * This is used to retrieve data in batches. See ResourceLoader::preloadModuleInfo().
         * To save the data, use saveFileDependencies().
         *
-        * @param string $skin Skin name
-        * @param array $deps Array of file names
+        * @param ResourceLoaderContext $context
+        * @param string[] $files Array of file names
         */
        public function setFileDependencies( ResourceLoaderContext $context, $files ) {
                $vary = $context->getSkin() . '|' . $context->getLanguage();
index 2d01d1d..f989cbc 100644 (file)
@@ -104,11 +104,14 @@ class CookieSessionProvider extends SessionProvider {
 
        public function provideSessionInfo( WebRequest $request ) {
                $info = array(
-                       'id' => $this->getCookie( $request, $this->params['sessionName'], '' )
+                       'id' => $this->getCookie( $request, $this->params['sessionName'], '' ),
+                       'provider' => $this,
+                       'forceHTTPS' => $this->getCookie( $request, 'forceHTTPS', '', false )
                );
                if ( !SessionManager::validateSessionId( $info['id'] ) ) {
                        unset( $info['id'] );
                }
+               $info['persisted'] = isset( $info['id'] );
 
                list( $userId, $userName, $token ) = $this->getUserInfoFromCookies( $request );
                if ( $userId !== null ) {
@@ -128,21 +131,22 @@ class CookieSessionProvider extends SessionProvider {
                                        return null;
                                }
                                $info['userInfo'] = $userInfo->verified();
-                       } elseif ( isset( $info['id'] ) ) { // No point if no session ID
+                       } elseif ( isset( $info['id'] ) ) {
                                $info['userInfo'] = $userInfo;
+                       } else {
+                               // No point in returning, loadSessionInfoFromStore() will
+                               // reject it anyway.
+                               return null;
                        }
-               }
-
-               if ( !$info ) {
+               } elseif ( isset( $info['id'] ) ) {
+                       // No UserID cookie, so insist that the session is anonymous.
+                       $info['userInfo'] = UserInfo::newAnonymous();
+               } else {
+                       // No session ID and no user is the same as an empty session, so
+                       // there's no point.
                        return null;
                }
 
-               $info += array(
-                       'provider' => $this,
-                       'persisted' => isset( $info['id'] ),
-                       'forceHTTPS' => $this->getCookie( $request, 'forceHTTPS', '', false )
-               );
-
                return new SessionInfo( $this->priority, $info );
        }
 
index 840baa7..4ad69ae 100644 (file)
@@ -314,6 +314,58 @@ final class Session implements \Countable, \Iterator {
                }
        }
 
+       /**
+        * Fetch a CSRF token from the session
+        *
+        * Note that this does not persist the session, which you'll probably want
+        * to do if you want the token to actually be useful.
+        *
+        * @param string|string[] $salt Token salt
+        * @param string $key Token key
+        * @return MediaWiki\\Session\\SessionToken
+        */
+       public function getToken( $salt = '', $key = 'default' ) {
+               $new = false;
+               $secrets = $this->get( 'wsTokenSecrets' );
+               if ( !is_array( $secrets ) ) {
+                       $secrets = array();
+               }
+               if ( isset( $secrets[$key] ) && is_string( $secrets[$key] ) ) {
+                       $secret = $secrets[$key];
+               } else {
+                       $secret = \MWCryptRand::generateHex( 32 );
+                       $secrets[$key] = $secret;
+                       $this->set( 'wsTokenSecrets', $secrets );
+                       $new = true;
+               }
+               if ( is_array( $salt ) ) {
+                       $salt = join( '|', $salt );
+               }
+               return new Token( $secret, (string)$salt, $new );
+       }
+
+       /**
+        * Remove a CSRF token from the session
+        *
+        * The next call to self::getToken() with $key will generate a new secret.
+        *
+        * @param string $key Token key
+        */
+       public function resetToken( $key = 'default' ) {
+               $secrets = $this->get( 'wsTokenSecrets' );
+               if ( is_array( $secrets ) && isset( $secrets[$key] ) ) {
+                       unset( $secrets[$key] );
+                       $this->set( 'wsTokenSecrets', $secrets );
+               }
+       }
+
+       /**
+        * Remove all CSRF tokens from the session
+        */
+       public function resetAllTokens() {
+               $this->remove( 'wsTokenSecrets' );
+       }
+
        /**
         * Delay automatic saving while multiple updates are being made
         *
index 95c6f0c..2a13ed2 100644 (file)
@@ -65,7 +65,9 @@ final class SessionBackend {
        private $dataHash = null;
 
        /** @var BagOStuff */
-       private $store;
+       private $tempStore;
+       /** @var BagOStuff */
+       private $permStore;
 
        /** @var LoggerInterface */
        private $logger;
@@ -97,12 +99,14 @@ final class SessionBackend {
        /**
         * @param SessionId $id Session ID object
         * @param SessionInfo $info Session info to populate from
-        * @param BagOStuff $store Backend data store
+        * @param BagOStuff $tempStore In-process data store
+        * @param BagOStuff $permstore Backend data store for persisted sessions
         * @param LoggerInterface $logger
         * @param int $lifetime Session data lifetime in seconds
         */
        public function __construct(
-               SessionId $id, SessionInfo $info, BagOStuff $store, LoggerInterface $logger, $lifetime
+               SessionId $id, SessionInfo $info, BagOStuff $tempStore, BagOStuff $permStore,
+               LoggerInterface $logger, $lifetime
        ) {
                $phpSessionHandling = \RequestContext::getMain()->getConfig()->get( 'PHPSessionHandling' );
                $this->usePhpSessionHandling = $phpSessionHandling !== 'disable';
@@ -121,7 +125,8 @@ final class SessionBackend {
 
                $this->id = $id;
                $this->user = $info->getUserInfo() ? $info->getUserInfo()->getUser() : new User;
-               $this->store = $store;
+               $this->tempStore = $tempStore;
+               $this->permStore = $permStore;
                $this->logger = $logger;
                $this->lifetime = $lifetime;
                $this->provider = $info->getProvider();
@@ -130,7 +135,14 @@ final class SessionBackend {
                $this->forceHTTPS = $info->forceHTTPS();
                $this->providerMetadata = $info->getProviderMetadata();
 
-               $blob = $store->get( wfMemcKey( 'MWSession', (string)$this->id ) );
+               $key = wfMemcKey( 'MWSession', (string)$this->id );
+               $blob = $tempStore->get( $key );
+               if ( $blob === false ) {
+                       $blob = $permStore->get( $key );
+                       if ( $blob !== false ) {
+                               $tempStore->set( $key, $blob );
+                       }
+               }
                if ( !is_array( $blob ) ||
                        !isset( $blob['metadata'] ) || !is_array( $blob['metadata'] ) ||
                        !isset( $blob['data'] ) || !is_array( $blob['data'] )
@@ -229,7 +241,8 @@ final class SessionBackend {
                        $this->autosave();
 
                        // Delete the data for the old session ID now
-                       $this->store->delete( wfMemcKey( 'MWSession', $oldId ) );
+                       $this->tempStore->delete( wfMemcKey( 'MWSession', $oldId ) );
+                       $this->permStore->delete( wfMemcKey( 'MWSession', $oldId ) );
                }
        }
 
@@ -262,6 +275,7 @@ final class SessionBackend {
                if ( !$this->persist ) {
                        $this->persist = true;
                        $this->forcePersist = true;
+                       $this->metaDirty = true;
                        $this->logger->debug( "SessionBackend $this->id force-persist due to persist()" );
                        $this->autosave();
                } else {
@@ -543,7 +557,7 @@ final class SessionBackend {
                // Ensure the user has a token
                // @codeCoverageIgnoreStart
                $anon = $this->user->isAnon();
-               if ( !$anon && !$this->user->getToken() ) {
+               if ( !$anon && !$this->user->getToken( false ) ) {
                        $this->logger->debug(
                                "SessionBackend $this->id creating token for user {$this->user} on save"
                        );
@@ -595,12 +609,13 @@ final class SessionBackend {
                        'provider' => (string)$this->provider,
                        'providerMetadata' => $this->providerMetadata,
                        'userId' => $anon ? 0 : $this->user->getId(),
-                       'userName' => $anon ? null : $this->user->getName(),
+                       'userName' => User::isValidUserName( $this->user->getName() ) ? $this->user->getName() : null,
                        'userToken' => $anon ? null : $this->user->getToken(),
                        'remember' => !$anon && $this->remember,
                        'forceHTTPS' => $this->forceHTTPS,
                        'expires' => time() + $this->lifetime,
                        'loggedOut' => $this->loggedOut,
+                       'persisted' => $this->persist,
                );
 
                \Hooks::run( 'SessionMetadata', array( $this, &$metadata, $this->requests ) );
@@ -611,7 +626,7 @@ final class SessionBackend {
                        }
                }
 
-               $this->store->set(
+               $this->tempStore->set(
                        wfMemcKey( 'MWSession', (string)$this->id ),
                        array(
                                'data' => $this->data,
@@ -619,6 +634,16 @@ final class SessionBackend {
                        ),
                        $metadata['expires']
                );
+               if ( $this->persist ) {
+                       $this->permStore->set(
+                               wfMemcKey( 'MWSession', (string)$this->id ),
+                               array(
+                                       'data' => $this->data,
+                                       'metadata' => $metadata,
+                               ),
+                               $metadata['expires']
+                       );
+               }
 
                $this->metaDirty = false;
                $this->dataDirty = false;
index ecc4e54..6b221fd 100644 (file)
@@ -55,7 +55,10 @@ final class SessionManager implements SessionManagerInterface {
        private $config;
 
        /** @var BagOStuff|null */
-       private $store;
+       private $tempStore;
+
+       /** @var BagOStuff|null */
+       private $permStore;
 
        /** @var SessionProvider[] */
        private $sessionProviders = null;
@@ -159,16 +162,17 @@ final class SessionManager implements SessionManagerInterface {
                        $this->setLogger( \MediaWiki\Logger\LoggerFactory::getInstance( 'session' ) );
                }
 
+               $this->tempStore = new \HashBagOStuff;
                if ( isset( $options['store'] ) ) {
                        if ( !$options['store'] instanceof BagOStuff ) {
                                throw new \InvalidArgumentException(
                                        '$options[\'store\'] must be an instance of BagOStuff'
                                );
                        }
-                       $this->store = $options['store'];
+                       $this->permStore = $options['store'];
                } else {
-                       $this->store = \ObjectCache::getInstance( $this->config->get( 'SessionCacheType' ) );
-                       $this->store->setLogger( $this->logger );
+                       $this->permStore = \ObjectCache::getInstance( $this->config->get( 'SessionCacheType' ) );
+                       $this->permStore->setLogger( $this->logger );
                }
 
                register_shutdown_function( array( $this, 'shutdown' ) );
@@ -202,7 +206,14 @@ final class SessionManager implements SessionManagerInterface {
                // Test this here to provide a better log message for the common case
                // of "no such ID"
                $key = wfMemcKey( 'MWSession', $id );
-               if ( is_array( $this->store->get( $key ) ) ) {
+               $existing = $this->tempStore->get( $key );
+               if ( $existing === false ) {
+                       $existing = $this->permStore->get( $key );
+                       if ( $existing !== false ) {
+                               $this->tempStore->set( $key, $existing );
+                       }
+               }
+               if ( is_array( $existing ) ) {
                        $info = new SessionInfo( SessionInfo::MIN_PRIORITY, array( 'id' => $id, 'idIsSafe' => true ) );
                        if ( $this->loadSessionInfoFromStore( $info, $request ) ) {
                                $session = $this->getSessionFromInfo( $info, $request );
@@ -240,7 +251,14 @@ final class SessionManager implements SessionManagerInterface {
                        }
 
                        $key = wfMemcKey( 'MWSession', $id );
-                       if ( is_array( $this->store->get( $key ) ) ) {
+                       $existing = $this->tempStore->get( $key );
+                       if ( $existing === false ) {
+                               $existing = $this->permStore->get( $key );
+                               if ( $existing !== false ) {
+                                       $this->tempStore->set( $key, $existing );
+                               }
+                       }
+                       if ( is_array( $existing ) ) {
                                throw new \InvalidArgumentException( 'Session ID already exists' );
                        }
                }
@@ -520,8 +538,8 @@ final class SessionManager implements SessionManagerInterface {
 
                // Reset the user's token to kill existing sessions
                $user = User::newFromName( $username );
-               if ( $user && $user->getToken() ) {
-                       $user->setToken( true );
+               if ( $user && $user->getToken( false ) ) {
+                       $user->setToken();
                        $user->saveSettings();
                }
 
@@ -660,7 +678,13 @@ final class SessionManager implements SessionManagerInterface {
         */
        private function loadSessionInfoFromStore( SessionInfo &$info, WebRequest $request ) {
                $key = wfMemcKey( 'MWSession', $info->getId() );
-               $blob = $this->store->get( $key );
+               $blob = $this->tempStore->get( $key );
+               if ( $blob === false ) {
+                       $blob = $this->permStore->get( $key );
+                       if ( $blob !== false ) {
+                               $this->tempStore->set( $key, $blob );
+                       }
+               }
 
                $newParams = array();
 
@@ -668,7 +692,8 @@ final class SessionManager implements SessionManagerInterface {
                        // Sanity check: blob must be an array, if it's saved at all
                        if ( !is_array( $blob ) ) {
                                $this->logger->warning( "Session $info: Bad data" );
-                               $this->store->delete( $key );
+                               $this->tempStore->delete( $key );
+                               $this->permStore->delete( $key );
                                return false;
                        }
 
@@ -677,7 +702,8 @@ final class SessionManager implements SessionManagerInterface {
                                !isset( $blob['metadata'] ) || !is_array( $blob['metadata'] )
                        ) {
                                $this->logger->warning( "Session $info: Bad data structure" );
-                               $this->store->delete( $key );
+                               $this->tempStore->delete( $key );
+                               $this->permStore->delete( $key );
                                return false;
                        }
 
@@ -692,7 +718,8 @@ final class SessionManager implements SessionManagerInterface {
                                !array_key_exists( 'provider', $metadata )
                        ) {
                                $this->logger->warning( "Session $info: Bad metadata" );
-                               $this->store->delete( $key );
+                               $this->tempStore->delete( $key );
+                               $this->permStore->delete( $key );
                                return false;
                        }
 
@@ -702,7 +729,8 @@ final class SessionManager implements SessionManagerInterface {
                                $newParams['provider'] = $provider = $this->getProvider( $metadata['provider'] );
                                if ( !$provider ) {
                                        $this->logger->warning( "Session $info: Unknown provider, " . $metadata['provider'] );
-                                       $this->store->delete( $key );
+                                       $this->tempStore->delete( $key );
+                                       $this->permStore->delete( $key );
                                        return false;
                                }
                        } elseif ( $metadata['provider'] !== (string)$provider ) {
@@ -801,6 +829,9 @@ final class SessionManager implements SessionManagerInterface {
                        if ( !empty( $metadata['forceHTTPS'] ) && !$info->forceHTTPS() ) {
                                $newParams['forceHTTPS'] = true;
                        }
+                       if ( !empty( $metadata['persisted'] ) && !$info->wasPersisted() ) {
+                               $newParams['persisted'] = true;
+                       }
 
                        if ( !$info->isIdSafe() ) {
                                $newParams['idIsSafe'] = true;
@@ -890,7 +921,8 @@ final class SessionManager implements SessionManagerInterface {
                        $backend = new SessionBackend(
                                $this->allSessionIds[$id],
                                $info,
-                               $this->store,
+                               $this->tempStore,
+                               $this->permStore,
                                $this->logger,
                                $this->config->get( 'ObjectCacheSessionExpiry' )
                        );
@@ -967,7 +999,9 @@ final class SessionManager implements SessionManagerInterface {
                do {
                        $id = wfBaseConvert( \MWCryptRand::generateHex( 40 ), 16, 32, 32 );
                        $key = wfMemcKey( 'MWSession', $id );
-               } while ( isset( $this->allSessionIds[$id] ) || is_array( $this->store->get( $key ) ) );
+               } while ( isset( $this->allSessionIds[$id] ) ||
+                       is_array( $this->tempStore->get( $key ) ) || is_array( $this->permStore->get( $key ) )
+               );
                return $id;
        }
 
@@ -977,7 +1011,7 @@ final class SessionManager implements SessionManagerInterface {
         * @param PHPSessionHandler $handler
         */
        public function setupPHPSessionHandler( PHPSessionHandler $handler ) {
-               $handler->setManager( $this, $this->store, $this->logger );
+               $handler->setManager( $this, $this->permStore, $this->logger );
        }
 
        /**
diff --git a/includes/session/Token.php b/includes/session/Token.php
new file mode 100644 (file)
index 0000000..9b4a73c
--- /dev/null
@@ -0,0 +1,125 @@
+<?php
+/**
+ * MediaWiki session token
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup Session
+ */
+
+namespace MediaWiki\Session;
+
+/**
+ * Value object representing a CSRF token
+ *
+ * @ingroup Session
+ * @since 1.27
+ */
+class Token {
+       /** CSRF token suffix. Plus and terminal backslash are included to stop
+        * editing from certain broken proxies. */
+       const SUFFIX = '+\\';
+
+       private $secret = '';
+       private $salt = '';
+       private $new = false;
+
+       /**
+        * @param string $secret Token secret
+        * @param string $salt Token salt
+        * @param bool $new Whether the secret was newly-created
+        */
+       public function __construct( $secret, $salt, $new = false ) {
+               $this->secret = $secret;
+               $this->salt = $salt;
+               $this->new = $new;
+       }
+
+       /**
+        * Decode the timestamp from a token string
+        *
+        * Does not validate the token beyond the syntactic checks necessary to
+        * be able to extract the timestamp.
+        *
+        * @param string $token
+        * @param int|null
+        */
+       public static function getTimestamp( $token ) {
+               $suffixLen = strlen( self::SUFFIX );
+               $len = strlen( $token );
+               if ( $len <= 32 + $suffixLen ||
+                       substr( $token, -$suffixLen ) !== self::SUFFIX ||
+                       strspn( $token, '0123456789abcdef' ) + $suffixLen !== $len
+               ) {
+                       return null;
+               }
+
+               return hexdec( substr( $token, 32, -$suffixLen ) );
+       }
+
+       /**
+        * Get the string representation of the token at a timestamp
+        * @param int timestamp
+        * @return string
+        */
+       protected function toStringAtTimestamp( $timestamp ) {
+               return hash_hmac( 'md5', $timestamp . $this->salt, $this->secret, false ) .
+                       dechex( $timestamp ) .
+                       self::SUFFIX;
+       }
+
+       /**
+        * Get the string representation of the token
+        * @return string
+        */
+       public function toString() {
+               return $this->toStringAtTimestamp( wfTimestamp() );
+       }
+
+       public function __toString() {
+               return $this->toString();
+       }
+
+       /**
+        * Test if the token-string matches this token
+        * @param string $userToken
+        * @param int|null $maxAge Return false if $userToken is older than this many seconds
+        * @return bool
+        */
+       public function match( $userToken, $maxAge = null ) {
+               $timestamp = self::getTimestamp( $userToken );
+               if ( $timestamp === null ) {
+                       return false;
+               }
+               if ( $maxAge !== null && $timestamp < wfTimestamp() - $maxAge ) {
+                       // Expired token
+                       return false;
+               }
+
+               $sessionToken = $this->toStringAtTimestamp( $timestamp );
+               return hash_equals( $sessionToken, $userToken );
+       }
+
+       /**
+        * Indicate whether this token was just created
+        * @return bool
+        */
+       public function wasNew() {
+               return $this->new;
+       }
+
+}
index e844bb6..c01b9ec 100644 (file)
@@ -152,10 +152,10 @@ final class UserInfo {
 
        /**
         * Return the user token
-        * @return string|null
+        * @return string
         */
        public function getToken() {
-               return $this->user === null || $this->user->getId() === 0 ? null : $this->user->getToken( true );
+               return $this->user === null || $this->user->getId() === 0 ? '' : $this->user->getToken( false );
        }
 
        /**
index 8656798..3e5a936 100644 (file)
@@ -111,13 +111,10 @@ class SpecialChangePassword extends FormSpecialPage {
                );
 
                if ( !$this->getUser()->isLoggedIn() ) {
-                       if ( !LoginForm::getLoginToken() ) {
-                               LoginForm::setLoginToken();
-                       }
                        $fields['LoginOnChangeToken'] = array(
                                'type' => 'hidden',
                                'label' => 'Change Password Token',
-                               'default' => LoginForm::getLoginToken(),
+                               'default' => LoginForm::getLoginToken()->toString(),
                        );
                }
 
@@ -179,7 +176,7 @@ class SpecialChangePassword extends FormSpecialPage {
                }
 
                if ( !$this->getUser()->isLoggedIn()
-                       && $request->getVal( 'wpLoginOnChangeToken' ) !== LoginForm::getLoginToken()
+                       && !LoginForm::getLoginToken()->match( $request->getVal( 'wpLoginOnChangeToken' ) )
                ) {
                        // Potential CSRF (bug 62497)
                        return false;
@@ -218,8 +215,8 @@ class SpecialChangePassword extends FormSpecialPage {
                        $this->getOutput()->returnToMain();
                } else {
                        $request = $this->getRequest();
-                       LoginForm::setLoginToken();
-                       $token = LoginForm::getLoginToken();
+                       LoginForm::clearLoginToken();
+                       $token = LoginForm::getLoginToken()->toString();
                        $data = array(
                                'action' => 'submitlogin',
                                'wpName' => $this->mUserName,
index 27d2304..a7e5e02 100644 (file)
@@ -117,9 +117,9 @@ class MovePageForm extends UnlistedSpecialPage {
                $this->moveTalk = $request->getBool( 'wpMovetalk', $def );
                $this->fixRedirects = $request->getBool( 'wpFixRedirects', $def );
                $this->leaveRedirect = $request->getBool( 'wpLeaveRedirect', $def );
-               $this->moveSubpages = $request->getBool( 'wpMovesubpages', false );
-               $this->deleteAndMove = $request->getBool( 'wpDeleteAndMove' ) && $request->getBool( 'wpConfirm' );
-               $this->moveOverShared = $request->getBool( 'wpMoveOverSharedFile', false );
+               $this->moveSubpages = $request->getBool( 'wpMovesubpages' );
+               $this->deleteAndMove = $request->getBool( 'wpDeleteAndMove' );
+               $this->moveOverShared = $request->getBool( 'wpMoveOverSharedFile' );
                $this->watch = $request->getCheck( 'wpWatch' ) && $user->isLoggedIn();
 
                if ( 'submit' == $request->getVal( 'action' ) && $request->wasPosted()
@@ -166,8 +166,8 @@ class MovePageForm extends UnlistedSpecialPage {
                        );
                }
 
-               $submitVar = 'wpMove';
-               $confirm = false;
+               $deleteAndMove = false;
+               $moveOverShared = false;
 
                $newTitle = $this->newTitle;
 
@@ -194,8 +194,7 @@ class MovePageForm extends UnlistedSpecialPage {
                                "<div class='warningbox'>\n$1\n</div>\n",
                                array( 'delete_and_move_text', $newTitle->getPrefixedText() )
                        );
-                       $submitVar = 'wpDeleteAndMove';
-                       $confirm = true;
+                       $deleteAndMove = true;
                        $err = array();
                }
 
@@ -209,7 +208,7 @@ class MovePageForm extends UnlistedSpecialPage {
                                        $newTitle->getPrefixedText()
                                )
                        );
-                       $submitVar = 'wpMoveOverSharedFile';
+                       $moveOverShared = true;
                        $err = array();
                }
 
@@ -440,11 +439,16 @@ class MovePageForm extends UnlistedSpecialPage {
                        );
                }
 
-               if ( $confirm ) {
+               $hiddenFields = '';
+               if ( $moveOverShared ) {
+                       $hiddenFields .= Html::hidden( 'wpMoveOverSharedFile', '1' );
+               }
+
+               if ( $deleteAndMove ) {
                        $fields[] = new OOUI\FieldLayout(
                                new OOUI\CheckboxInputWidget( array(
-                                       'name' => 'wpConfirm',
-                                       'id' => 'wpConfirm',
+                                       'name' => 'wpDeleteAndMove',
+                                       'id' => 'wpDeleteAndMove',
                                        'value' => '1',
                                ) ),
                                array(
@@ -456,7 +460,7 @@ class MovePageForm extends UnlistedSpecialPage {
 
                $fields[] = new OOUI\FieldLayout(
                        new OOUI\ButtonInputWidget( array(
-                               'name' => $submitVar,
+                               'name' => 'wpMove',
                                'value' => $this->msg( 'movepagebtn' )->text(),
                                'label' => $this->msg( 'movepagebtn' )->text(),
                                'flags' => array( 'constructive', 'primary' ),
@@ -481,6 +485,7 @@ class MovePageForm extends UnlistedSpecialPage {
                $form->appendContent(
                        $fieldset,
                        new OOUI\HtmlSnippet(
+                               $hiddenFields .
                                Html::hidden( 'wpOldTitle', $this->oldTitle->getPrefixedText() ) .
                                Html::hidden( 'wpEditToken', $user->getEditToken() )
                        )
index f030231..0bf2485 100644 (file)
@@ -84,10 +84,7 @@ class SpecialRecentChanges extends ChangesListSpecialPage {
                $opts->add( 'hideliu', false );
                $opts->add( 'hidepatrolled', $user->getBoolOption( 'hidepatrolled' ) );
                $opts->add( 'hidemyself', false );
-
-               if ( $config->get( 'RCWatchCategoryMembership' ) ) {
-                       $opts->add( 'hidecategorization', $user->getBoolOption( 'hidecategorization' ) );
-               }
+               $opts->add( 'hidecategorization', $user->getBoolOption( 'hidecategorization' ) );
 
                $opts->add( 'categories', '' );
                $opts->add( 'categories_any', false );
index 9473dff..d9a5e4f 100644 (file)
@@ -531,9 +531,8 @@ class LoginForm extends SpecialPage {
                }
 
                # Request forgery checks.
-               if ( !self::getCreateaccountToken() ) {
-                       self::setCreateaccountToken();
-
+               $token = self::getCreateaccountToken();
+               if ( $token->wasNew() ) {
                        return Status::newFatal( 'nocookiesfornew' );
                }
 
@@ -543,7 +542,7 @@ class LoginForm extends SpecialPage {
                }
 
                # Validate the createaccount token
-               if ( $this->mToken !== self::getCreateaccountToken() ) {
+               if ( !$token->match( $this->mToken ) ) {
                        return Status::newFatal( 'sessionfailure' );
                }
 
@@ -737,9 +736,8 @@ class LoginForm extends SpecialPage {
                // but wrong-token attempts do.
 
                // If the user doesn't have a login token yet, set one.
-               if ( !self::getLoginToken() ) {
-                       self::setLoginToken();
-
+               $token = self::getLoginToken();
+               if ( $token->wasNew() ) {
                        return self::NEED_TOKEN;
                }
                // If the user didn't pass a login token, tell them we need one
@@ -753,7 +751,7 @@ class LoginForm extends SpecialPage {
                }
 
                // Validate the login token
-               if ( $this->mToken !== self::getLoginToken() ) {
+               if ( !$token->match( $this->mToken ) ) {
                        return self::WRONG_TOKEN;
                }
 
@@ -1492,15 +1490,9 @@ class LoginForm extends SpecialPage {
                $template->set( 'loggedinuser', $user->getName() );
 
                if ( $this->mType == 'signup' ) {
-                       if ( !self::getCreateaccountToken() ) {
-                               self::setCreateaccountToken();
-                       }
-                       $template->set( 'token', self::getCreateaccountToken() );
+                       $template->set( 'token', self::getCreateaccountToken()->toString() );
                } else {
-                       if ( !self::getLoginToken() ) {
-                               self::setLoginToken();
-                       }
-                       $template->set( 'token', self::getLoginToken() );
+                       $template->set( 'token', self::getLoginToken()->toString() );
                }
 
                # Prepare language selection links as needed
@@ -1576,22 +1568,25 @@ class LoginForm extends SpecialPage {
 
        /**
         * Get the login token from the current session
-        * @return mixed
+        * @since 1.27 returns a MediaWiki\\Session\\Token instead of a string
+        * @return MediaWiki\\Session\\Token
         */
        public static function getLoginToken() {
                global $wgRequest;
-
-               return $wgRequest->getSessionData( 'wsLoginToken' );
+               return $wgRequest->getSession()->getToken( '', 'login' );
        }
 
        /**
-        * Randomly generate a new login token and attach it to the current session
+        * Formerly randomly generated a login token that would be returned by
+        * $this->getLoginToken().
+        *
+        * Since 1.27, this is a no-op. The token is generated as necessary by
+        * $this->getLoginToken().
+        *
+        * @deprecated since 1.27
         */
        public static function setLoginToken() {
-               global $wgRequest;
-               // Generate a token directly instead of using $user->getEditToken()
-               // because the latter reuses wsEditToken in the session
-               $wgRequest->setSessionData( 'wsLoginToken', MWCryptRand::generateHex( 32 ) );
+               wfDeprecated( __METHOD__, '1.27' );
        }
 
        /**
@@ -1599,24 +1594,30 @@ class LoginForm extends SpecialPage {
         */
        public static function clearLoginToken() {
                global $wgRequest;
-               $wgRequest->setSessionData( 'wsLoginToken', null );
+               $wgRequest->getSession()->resetToken( 'login' );
        }
 
        /**
         * Get the createaccount token from the current session
-        * @return mixed
+        * @since 1.27 returns a MediaWiki\\Session\\Token instead of a string
+        * @return MediaWiki\\Session\\Token
         */
        public static function getCreateaccountToken() {
                global $wgRequest;
-               return $wgRequest->getSessionData( 'wsCreateaccountToken' );
+               return $wgRequest->getSession()->getToken( '', 'createaccount' );
        }
 
        /**
-        * Randomly generate a new createaccount token and attach it to the current session
+        * Formerly randomly generated a createaccount token that would be returned
+        * by $this->getCreateaccountToken().
+        *
+        * Since 1.27, this is a no-op. The token is generated as necessary by
+        * $this->getCreateaccountToken().
+        *
+        * @deprecated since 1.27
         */
        public static function setCreateaccountToken() {
-               global $wgRequest;
-               $wgRequest->setSessionData( 'wsCreateaccountToken', MWCryptRand::generateHex( 32 ) );
+               wfDeprecated( __METHOD__, '1.27' );
        }
 
        /**
@@ -1624,7 +1625,7 @@ class LoginForm extends SpecialPage {
         */
        public static function clearCreateaccountToken() {
                global $wgRequest;
-               $wgRequest->setSessionData( 'wsCreateaccountToken', null );
+               $wgRequest->getSession()->resetToken( 'createaccount' );
        }
 
        /**
index 43228fa..a628902 100644 (file)
@@ -38,12 +38,6 @@ class SpecialVersion extends SpecialPage {
 
        protected static $extensionTypes = false;
 
-       protected static $viewvcUrls = array(
-               'svn+ssh://svn.wikimedia.org/svnroot/mediawiki' => 'http://svn.wikimedia.org/viewvc/mediawiki',
-               'http://svn.wikimedia.org/svnroot/mediawiki' => 'http://svn.wikimedia.org/viewvc/mediawiki',
-               'https://svn.wikimedia.org/svnroot/mediawiki' => 'https://svn.wikimedia.org/viewvc/mediawiki',
-       );
-
        public function __construct() {
                parent::__construct( 'Version' );
        }
@@ -258,7 +252,7 @@ class SpecialVersion extends SpecialPage {
        }
 
        /**
-        * Return a string of the MediaWiki version with SVN revision if available.
+        * Return a string of the MediaWiki version with Git revision if available.
         *
         * @param string $flags
         * @return mixed
@@ -267,25 +261,15 @@ class SpecialVersion extends SpecialPage {
                global $wgVersion, $IP;
 
                $gitInfo = self::getGitHeadSha1( $IP );
-               $svnInfo = self::getSvnInfo( $IP );
-               if ( !$svnInfo && !$gitInfo ) {
+               if ( !$gitInfo ) {
                        $version = $wgVersion;
-               } elseif ( $gitInfo && $flags === 'nodb' ) {
+               } elseif ( $flags === 'nodb' ) {
                        $shortSha1 = substr( $gitInfo, 0, 7 );
                        $version = "$wgVersion ($shortSha1)";
-               } elseif ( $gitInfo ) {
+               } else {
                        $shortSha1 = substr( $gitInfo, 0, 7 );
                        $shortSha1 = wfMessage( 'parentheses' )->params( $shortSha1 )->escaped();
                        $version = "$wgVersion $shortSha1";
-               } elseif ( $flags === 'nodb' ) {
-                       $version = "$wgVersion (r{$svnInfo['checkout-rev']})";
-               } else {
-                       $version = $wgVersion . ' ' .
-                               wfMessage(
-                                       'version-svn-revision',
-                                       isset( $svnInfo['directory-rev'] ) ? $svnInfo['directory-rev'] : '',
-                                       isset( $svnInfo['checkout-rev'] ) ? $svnInfo['checkout-rev'] : ''
-                               )->text();
                }
 
                return $version;
@@ -293,8 +277,7 @@ class SpecialVersion extends SpecialPage {
 
        /**
         * Return a wikitext-formatted string of the MediaWiki version with a link to
-        * the SVN revision or the git SHA1 of head if available.
-        * Git is prefered over Svn
+        * the Git SHA1 of head if available.
         * The fallback is just $wgVersion
         *
         * @return mixed
@@ -306,43 +289,12 @@ class SpecialVersion extends SpecialPage {
                if ( $gitVersion ) {
                        $v = $gitVersion;
                } else {
-                       $svnVersion = self::getVersionLinkedSvn();
-                       if ( $svnVersion ) {
-                               $v = $svnVersion;
-                       } else {
-                               $v = $wgVersion; // fallback
-                       }
+                       $v = $wgVersion; // fallback
                }
 
                return $v;
        }
 
-       /**
-        * @return string Global wgVersion + a link to subversion revision of svn BASE
-        */
-       private static function getVersionLinkedSvn() {
-               global $IP;
-
-               $info = self::getSvnInfo( $IP );
-               if ( !isset( $info['checkout-rev'] ) ) {
-                       return false;
-               }
-
-               $linkText = wfMessage(
-                       'version-svn-revision',
-                       isset( $info['directory-rev'] ) ? $info['directory-rev'] : '',
-                       $info['checkout-rev']
-               )->text();
-
-               if ( isset( $info['viewvc-url'] ) ) {
-                       $version = "[{$info['viewvc-url']} $linkText]";
-               } else {
-                       $version = $linkText;
-               }
-
-               return self::getwgVersionLinked() . " $version";
-       }
-
        /**
         * @return string
         */
@@ -744,7 +696,7 @@ class SpecialVersion extends SpecialPage {
                }
 
                // ... and the version information
-               // If the extension path is set we will check that directory for GIT and SVN
+               // If the extension path is set we will check that directory for GIT
                // metadata in an attempt to extract date and vcs commit metadata.
                $canonicalVersion = '&ndash;';
                $extensionPath = null;
@@ -764,11 +716,6 @@ class SpecialVersion extends SpecialPage {
                                $coreHeadSHA1 = self::getGitHeadSha1( $IP );
                                if ( $coreHeadSHA1 ) {
                                        $this->coreId = $coreHeadSHA1;
-                               } else {
-                                       $svnInfo = self::getSvnInfo( $IP );
-                                       if ( $svnInfo !== false ) {
-                                               $this->coreId = $svnInfo['checkout-rev'];
-                                       }
                                }
                        }
                        $cache = wfGetCache( CACHE_ANYTHING );
@@ -783,12 +730,6 @@ class SpecialVersion extends SpecialPage {
                                        $vcsVersion = substr( $vcsVersion, 0, 7 );
                                        $vcsLink = $gitInfo->getHeadViewUrl();
                                        $vcsDate = $gitInfo->getHeadCommitDate();
-                               } else {
-                                       $svnInfo = self::getSvnInfo( $extensionPath );
-                                       if ( $svnInfo !== false ) {
-                                               $vcsVersion = $this->msg( 'version-svn-revision', $svnInfo['checkout-rev'] )->text();
-                                               $vcsLink = isset( $svnInfo['viewvc-url'] ) ? $svnInfo['viewvc-url'] : '';
-                                       }
                                }
                                $cache->set( $memcKey, array( $vcsVersion, $vcsLink, $vcsDate ), 60 * 60 * 24 );
                        } else {
@@ -1154,108 +1095,6 @@ class SpecialVersion extends SpecialPage {
                }
        }
 
-       /**
-        * Get an associative array of information about a given path, from its .svn
-        * subdirectory. Returns false on error, such as if the directory was not
-        * checked out with subversion.
-        *
-        * Returned keys are:
-        *    Required:
-        *        checkout-rev          The revision which was checked out
-        *    Optional:
-        *        directory-rev         The revision when the directory was last modified
-        *        url                   The subversion URL of the directory
-        *        repo-url              The base URL of the repository
-        *        viewvc-url            A ViewVC URL pointing to the checked-out revision
-        * @param string $dir
-        * @return array|bool
-        */
-       public static function getSvnInfo( $dir ) {
-               // http://svnbook.red-bean.com/nightly/en/svn.developer.insidewc.html
-               $entries = $dir . '/.svn/entries';
-
-               if ( !file_exists( $entries ) ) {
-                       return false;
-               }
-
-               $lines = file( $entries );
-               if ( !count( $lines ) ) {
-                       return false;
-               }
-
-               // check if file is xml (subversion release <= 1.3) or not (subversion release = 1.4)
-               if ( preg_match( '/^<\?xml/', $lines[0] ) ) {
-                       // subversion is release <= 1.3
-                       if ( !function_exists( 'simplexml_load_file' ) ) {
-                               // We could fall back to expat... YUCK
-                               return false;
-                       }
-
-                       // SimpleXml whines about the xmlns...
-                       MediaWiki\suppressWarnings();
-                       $xml = simplexml_load_file( $entries );
-                       MediaWiki\restoreWarnings();
-
-                       if ( $xml ) {
-                               foreach ( $xml->entry as $entry ) {
-                                       if ( $xml->entry[0]['name'] == '' ) {
-                                               // The directory entry should always have a revision marker.
-                                               if ( $entry['revision'] ) {
-                                                       return array( 'checkout-rev' => intval( $entry['revision'] ) );
-                                               }
-                                       }
-                               }
-                       }
-
-                       return false;
-               }
-
-               // Subversion is release 1.4 or above.
-               if ( count( $lines ) < 11 ) {
-                       return false;
-               }
-
-               $info = array(
-                       'checkout-rev' => intval( trim( $lines[3] ) ),
-                       'url' => trim( $lines[4] ),
-                       'repo-url' => trim( $lines[5] ),
-                       'directory-rev' => intval( trim( $lines[10] ) )
-               );
-
-               if ( isset( self::$viewvcUrls[$info['repo-url']] ) ) {
-                       $viewvc = str_replace(
-                               $info['repo-url'],
-                               self::$viewvcUrls[$info['repo-url']],
-                               $info['url']
-                       );
-
-                       $viewvc .= '/?pathrev=';
-                       $viewvc .= urlencode( $info['checkout-rev'] );
-                       $info['viewvc-url'] = $viewvc;
-               }
-
-               return $info;
-       }
-
-       /**
-        * Retrieve the revision number of a Subversion working directory.
-        *
-        * @param string $dir Directory of the svn checkout
-        *
-        * @return int Revision number
-        */
-       public static function getSvnRevision( $dir ) {
-               $info = self::getSvnInfo( $dir );
-
-               if ( $info === false ) {
-                       return false;
-               } elseif ( isset( $info['checkout-rev'] ) ) {
-                       return $info['checkout-rev'];
-               } else {
-                       return false;
-               }
-       }
-
        /**
         * @param string $dir Directory of the git checkout
         * @return bool|string Sha1 of commit HEAD points to
index 6ebe9a8..cc5c150 100644 (file)
@@ -118,10 +118,7 @@ class SpecialWatchlist extends ChangesListSpecialPage {
                $opts->add( 'hideliu', $user->getBoolOption( 'watchlisthideliu' ) );
                $opts->add( 'hidepatrolled', $user->getBoolOption( 'watchlisthidepatrolled' ) );
                $opts->add( 'hidemyself', $user->getBoolOption( 'watchlisthideown' ) );
-
-               if ( $this->getConfig()->get( 'RCWatchCategoryMembership' ) ) {
-                       $opts->add( 'hidecategorization', $user->getBoolOption( 'watchlisthidecategorization' ) );
-               }
+               $opts->add( 'hidecategorization', $user->getBoolOption( 'watchlisthidecategorization' ) );
 
                return $opts;
        }
diff --git a/includes/user/LoggedOutEditToken.php b/includes/user/LoggedOutEditToken.php
new file mode 100644 (file)
index 0000000..14548f4
--- /dev/null
@@ -0,0 +1,47 @@
+<?php
+/**
+ * MediaWiki edit token
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup Session
+ */
+
+use MediaWiki\Session\Token;
+
+/**
+ * Value object representing a logged-out user's edit token
+ *
+ * This exists so that code generically dealing with MediaWiki\\Session\\Token
+ * (i.e. the API) doesn't have to have so many special cases for anon edit
+ * tokens.
+ *
+ * @since 1.27
+ */
+class LoggedOutEditToken extends MediaWiki\Session\Token {
+       public function __construct() {
+               parent::__construct( '', '', false );
+       }
+
+       protected function toStringAtTimestamp( $timestamp ) {
+               return self::SUFFIX;
+       }
+
+       public function match( $userToken, $maxAge = null ) {
+               return $userToken === self::SUFFIX;
+       }
+}
index 2fadd6b..b1f79ce 100644 (file)
@@ -24,9 +24,10 @@ use MediaWiki\Session\SessionManager;
 
 /**
  * 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', '+\\' );
+define( 'EDIT_TOKEN_SUFFIX', MediaWiki\Session\Token::SUFFIX );
 
 /**
  * The User object encapsulates all of the user-specific settings (user_id,
@@ -47,6 +48,7 @@ class User implements IDBAccessObject {
        /**
         * Global constant made accessible as class constants so that autoloader
         * magic can be used.
+        * @deprecated since 1.27, use \\MediaWiki\\Session\\Token::SUFFIX
         */
        const EDIT_TOKEN_SUFFIX = EDIT_TOKEN_SUFFIX;
 
@@ -1259,12 +1261,20 @@ class User implements IDBAccessObject {
                        $all = false;
                }
 
-               if ( isset( $row->user_email ) ) {
-                       $this->mEmail = $row->user_email;
-                       $this->mToken = $row->user_token;
-                       if ( $this->mToken == '' ) {
+               if ( isset( $row->user_token ) ) {
+                       // The definition for the column is binary(32), so trim the NULs
+                       // that appends. The previous definition was char(32), so trim
+                       // spaces too.
+                       $this->mToken = rtrim( $row->user_token, " \0" );
+                       if ( $this->mToken === '' ) {
                                $this->mToken = null;
                        }
+               } else {
+                       $all = false;
+               }
+
+               if ( isset( $row->user_email ) ) {
+                       $this->mEmail = $row->user_email;
                        $this->mEmailAuthenticated = wfTimestampOrNull( TS_MW, $row->user_email_authenticated );
                        $this->mEmailToken = $row->user_email_token;
                        $this->mEmailTokenExpires = wfTimestampOrNull( TS_MW, $row->user_email_token_expires );
@@ -3431,7 +3441,7 @@ class User implements IDBAccessObject {
                }
 
                $this->getWatchedItem( $title )->resetNotificationTimestamp(
-                       $force, $oldid, WatchedItem::DEFERRED
+                       $force, $oldid
                );
        }
 
@@ -4066,30 +4076,25 @@ class User implements IDBAccessObject {
        }
 
        /**
-        * Internal implementation for self::getEditToken() and
-        * self::matchEditToken().
+        * Initialize (if necessary) and return a session token value
+        * which can be used in edit forms to show that the user's
+        * login credentials aren't being hijacked with a foreign form
+        * submission.
         *
-        * @param string|array $salt
-        * @param WebRequest $request
-        * @param string|int $timestamp
-        * @return string
+        * @since 1.27
+        * @param string|array $salt Array of Strings Optional function-specific data for hashing
+        * @param WebRequest|null $request WebRequest object to use or null to use $wgRequest
+        * @return MediaWiki\\Session\\Token The new edit token
         */
-       private function getEditTokenAtTimestamp( $salt, $request, $timestamp ) {
+       public function getEditTokenObject( $salt = '', $request = null ) {
                if ( $this->isAnon() ) {
-                       return self::EDIT_TOKEN_SUFFIX;
-               } else {
-                       $token = $request->getSessionData( 'wsEditToken' );
-                       if ( $token === null ) {
-                               $token = MWCryptRand::generateHex( 32 );
-                               $request->setSessionData( 'wsEditToken', $token );
-                       }
-                       if ( is_array( $salt ) ) {
-                               $salt = implode( '|', $salt );
-                       }
-                       return hash_hmac( 'md5', $timestamp . $salt, $token, false ) .
-                               dechex( $timestamp ) .
-                               self::EDIT_TOKEN_SUFFIX;
+                       return new LoggedOutEditToken();
+               }
+
+               if ( !$request ) {
+                       $request = $this->getRequest();
                }
+               return $request->getSession()->getToken( $salt );
        }
 
        /**
@@ -4099,29 +4104,23 @@ class User implements IDBAccessObject {
         * submission.
         *
         * @since 1.19
-        *
         * @param string|array $salt Array of Strings Optional function-specific data for hashing
         * @param WebRequest|null $request WebRequest object to use or null to use $wgRequest
         * @return string The new edit token
         */
        public function getEditToken( $salt = '', $request = null ) {
-               return $this->getEditTokenAtTimestamp(
-                       $salt, $request ?: $this->getRequest(), wfTimestamp()
-               );
+               return $this->getEditTokenObject( $salt, $request )->toString();
        }
 
        /**
         * Get the embedded timestamp from a token.
+        * @deprecated since 1.27, use \\MediaWiki\\Session\\Token::getTimestamp instead.
         * @param string $val Input token
         * @return int|null
         */
        public static function getEditTokenTimestamp( $val ) {
-               $suffixLen = strlen( self::EDIT_TOKEN_SUFFIX );
-               if ( strlen( $val ) <= 32 + $suffixLen ) {
-                       return null;
-               }
-
-               return hexdec( substr( $val, 32, -$suffixLen ) );
+               wfDeprecated( __METHOD__, '1.27' );
+               return MediaWiki\Session\Token::getTimestamp( $val );
        }
 
        /**
@@ -4137,28 +4136,7 @@ class User implements IDBAccessObject {
         * @return bool Whether the token matches
         */
        public function matchEditToken( $val, $salt = '', $request = null, $maxage = null ) {
-               if ( $this->isAnon() ) {
-                       return $val === self::EDIT_TOKEN_SUFFIX;
-               }
-
-               $timestamp = self::getEditTokenTimestamp( $val );
-               if ( $timestamp === null ) {
-                       return false;
-               }
-               if ( $maxage !== null && $timestamp < wfTimestamp() - $maxage ) {
-                       // Expired token
-                       return false;
-               }
-
-               $sessionToken = $this->getEditTokenAtTimestamp(
-                       $salt, $request ?: $this->getRequest(), $timestamp
-               );
-
-               if ( !hash_equals( $sessionToken, $val ) ) {
-                       wfDebug( "User::matchEditToken: broken session data\n" );
-               }
-
-               return hash_equals( $sessionToken, $val );
+               return $this->getEditTokenObject( $salt, $request )->match( $val, $maxage );
        }
 
        /**
index 13cab5b..ffb7053 100644 (file)
@@ -66,6 +66,6 @@ class BatchRowWriter {
                }
 
                $this->db->commit();
-               wfWaitForSlaves( false, false, $this->clusterName );
+               wfGetLBFactory()->waitForReplication();
        }
 }
index a012f59..8c8dfe0 100644 (file)
@@ -21,9 +21,6 @@
  * @ingroup Language
  */
 
-require_once __DIR__ . '/../LanguageConverter.php';
-require_once __DIR__ . '/LanguageZh.php';
-
 /**
  * @ingroup Language
  */
index db3a22c..af0431f 100644 (file)
@@ -21,8 +21,6 @@
  * @ingroup Language
  */
 
-require_once __DIR__ . '/../LanguageConverter.php';
-
 /**
  * Conversion script between Latin and Syllabics for Inuktitut.
  * - Syllabics -> lowercase Latin
index 0f60889..0357730 100644 (file)
@@ -21,9 +21,6 @@
  * @ingroup Language
  */
 
-require_once __DIR__ . '/../LanguageConverter.php';
-require_once __DIR__ . '/LanguageKk_cyrl.php';
-
 define( 'KK_C_UC', 'АӘБВГҒДЕЁЖЗИЙКҚЛМНҢОӨПРСТУҰҮФХҺЦЧШЩЪЫІЬЭЮЯ' ); # Kazakh Cyrillic uppercase
 define( 'KK_C_LC', 'аәбвгғдеёжзийкқлмнңоөпрстуұүфхһцчшщъыіьэюя' ); # Kazakh Cyrillic lowercase
 define( 'KK_L_UC', 'AÄBCÇDEÉFGĞHIİÏJKLMNÑOÖPQRSŞTUÜVWXYÝZ' ); # Kazakh Latin uppercase
index 1fdebc2..c14f468 100644 (file)
@@ -21,9 +21,6 @@
  * @ingroup Language
  */
 
-require_once __DIR__ . '/../LanguageConverter.php';
-require_once __DIR__ . '/LanguageKu_ku.php';
-
 /**
  * Kurdish converter routines
  *
index 105a3af..afd7283 100644 (file)
@@ -21,8 +21,6 @@
  * @ingroup Language
  */
 
-require_once __DIR__ . '/../LanguageConverter.php';
-
 /**
  * Conversion script between Latin and Tifinagh for Tachelhit.
  * - Tifinagh -> lowercase Latin
index bdf1ec4..ece50e8 100644 (file)
@@ -21,8 +21,6 @@
  * @ingroup Language
  */
 
-require_once __DIR__ . '/../LanguageConverter.php';
-
 /**
  * There are two levels of conversion for Serbian: the script level
  * (Cyrillics <-> Latin), and the variant level (ekavian
index 10755b4..6518e65 100644 (file)
@@ -21,8 +21,6 @@
  * @ingroup Language
  */
 
-require_once __DIR__ . '/../LanguageConverter.php';
-
 /**
  * Converts Tajiki to latin orthography
  *
index 985de68..6910d9c 100644 (file)
@@ -21,8 +21,6 @@
  * @ingroup Language
  */
 
-require_once __DIR__ . '/../LanguageConverter.php';
-
 /**
  * @ingroup Language
  */
index 0f47c38..6e8860f 100644 (file)
@@ -21,9 +21,6 @@
  * @ingroup Language
  */
 
-require_once __DIR__ . '/../LanguageConverter.php';
-require_once __DIR__ . '/LanguageZh_hans.php';
-
 /**
  * @ingroup Language
  */
index 47d10c2..ca63658 100644 (file)
        "version-hook-subscribedby": "يستخدم بواسطة",
        "version-version": "($1)",
        "version-no-ext-name": "[لا اسم]",
-       "version-svn-revision": "ن$1",
        "version-license": "ترخيص ميدياويكي",
        "version-ext-license": "ترخيص",
        "version-ext-colheader-name": "امتداد",
index 9cf6493..980de92 100644 (file)
        "deletepage": "صحیفه‌‌نی سیل",
        "confirm": "تصدیق ائت",
        "excontent": "کؤهنه مظمون: '$1'",
-       "excontentauthor": "ترکÛ\8cب: '$1 (Ù\88'[[Special:Contributions/$2|$2]]' ØªØ§Ø±Û\8cØ®Ú\86Ù\87â\80\8cدÙ\87 Ù\81اÙ\84Û\8cتÛ\8c Ù\82ئÛ\8cد Ø§Ø¦Ø¯Û\8cÙ\84Ù\86 Û\8cئگاÙ\86Ù\87 Ø§Û\8cستÛ\8cÙ\81ادÙ\87â\80\8cÚ\86Û\8câ\80\8cدÛ\8cر)",
+       "excontentauthor": "صÙ\81Ø­Ù\87 Ø§Û\8cÚ\86Û\8cÙ\86دÙ\87â\80\8cÚ©Û\8cÙ\84ر Ø¨Û\87 Ø§Û\8cدÛ\8c: Â«$1» Ù\88 ØªÚ©Ø¬Ù\87 Ú\86اÙ\84Û\8cشاÙ\86 Â«[[Special:Contributions/$2|$2]] ([[User talk:$2|داÙ\86Û\8cØ´Û\8cÙ\82]])» Ø§Û\8cدÛ\8c.",
        "exbeforeblank": "سیلینمه‌دن اوولکی مزمون: '$1",
        "delete-confirm": "سیل $1",
        "delete-legend": "سیل",
index 8daa609..cf85e49 100644 (file)
        "botpasswords-label-grants": "Прыдатныя дазволы:",
        "botpasswords-label-restrictions": "Абмежаваньні на выкарыстаньне:",
        "botpasswords-label-grants-column": "Дазволена",
+       "botpasswords-bad-appid": "Назва робата «$1» зьяўляецца няслушнай.",
+       "botpasswords-insert-failed": "Не атрымалася дадаць робата зь імем «$1». Магчыма, ён ужо быў дададзены?",
+       "botpasswords-update-failed": "Не атрымалася абнавіць робата зь імем «$1». Магчыма, ён быў выдалены?",
        "resetpass_forbidden": "Пароль ня можа быць зьменены",
        "resetpass-no-info": "Для непасрэднага доступу да гэтай старонкі Вам неабходна ўвайсьці ў сыстэму.",
        "resetpass-submit-loggedin": "Зьмяніць пароль",
        "whatlinkshere": "Спасылкі на старонку",
        "whatlinkshere-title": "Старонкі, якія спасылаюцца на $1",
        "whatlinkshere-page": "Старонка:",
-       "linkshere": "Наступныя старонкі спасылаюцца на '''[[:$1]]''':",
+       "linkshere": "Наступныя старонкі спасылаюцца на <strong>[[:$1]]</strong>:",
        "nolinkshere": "Ніводная старонка не спасылаецца на '''[[:$1]]'''.",
        "nolinkshere-ns": "Ніводная старонка не спасылаецца на '''[[:$1]]''' з выбранай прасторы назваў.",
        "isredirect": "старонка-перанакіраваньне",
        "istemplate": "уключэньне",
        "isimage": "спасылка на файл",
        "whatlinkshere-prev": "{{PLURAL:$1|папярэдняя|папярэднія}} $1",
-       "whatlinkshere-next": "{{PLURAL:$1|наступная|наступныя|наступныя}} $1",
+       "whatlinkshere-next": "{{PLURAL:$1|наступная|наступныя}} $1",
        "whatlinkshere-links": "← спасылкі",
        "whatlinkshere-hideredirs": "$1 перанакіраваньні",
        "whatlinkshere-hidetrans": "$1 уключэньні",
        "version-hook-subscribedby": "Падпісаны на",
        "version-version": "($1)",
        "version-no-ext-name": "[бяз назвы]",
-       "version-svn-revision": "(r$2)",
        "version-license": "Ліцэнзія MediaWiki",
        "version-ext-license": "Ліцэнзія",
        "version-ext-colheader-name": "Пашырэньне",
        "expand_templates_preview": "Папярэдні прагляд",
        "expand_templates_preview_fail_html": "<em>Праз тое што {{SITENAME}} мае ўключаным сыры HTML і адбылася страта зьвестак сэсіі, папярэдні прагляд схаваны, як засьцярога ад атакаў з дапамогай JavaScript.</em>\n\n<strong>Калі гэта слушная спроба перадпрагляду, калі ласка, паспрабуйце яшчэ раз.</strong>\nКалі гэта не спрацуе, паспрабуйце [[Special:UserLogout|выйсьці]] і ўвайсьці яшчэ раз.",
        "expand_templates_preview_fail_html_anon": "<em>Праз тое што {{SITENAME}} мае ўключаным сыры HTML і вы не ўвайшлі ў сыстэму, папярэдні прагляд схаваны, як засьцярога ад атакаў з дапамогай JavaScript.</em>\n\n<strong>Калі гэта слушная спроба перадпрагляду, калі ласка, [[Special:UserLogin|увайдзіце ў сыстэму]] і паспрабуйце яшчэ раз.</strong>",
-       "pagelanguage": "Ð\92Ñ\8bбаÑ\80 мовы старонкі",
+       "pagelanguage": "Ð\97Ñ\8cмена мовы старонкі",
        "pagelang-name": "Старонка",
        "pagelang-language": "Мова",
        "pagelang-use-default": "Ужываць мову па змоўчаньні",
        "action-pagelang": "зьмену мовы старонкі",
        "log-name-pagelang": "Журнал зьменаў мовы",
        "log-description-pagelang": "Гэта журнал зьменаў мовы старонак.",
-       "logentry-pagelang-pagelang": "$1 {{GENDER:$2|зьмяніў|зьмяніла}} мову старонкі $3 з $4 на $5.",
+       "logentry-pagelang-pagelang": "$1 {{GENDER:$2|зьмяніў|зьмяніла}} мову старонкі $3 з $4 на $5",
        "default-skin-not-found": "Упс! Тэма афармленьня па змоўчаньні для вашай вікі, вызначаная ў <code dir=\"ltr\">$wgDefaultSkin</code> як <code>$1</code> недаступная.\n\nВашае ўсталяваньне, падобна, уключае {{PLURAL:$4|наступную тэму афармленьне|наступныя тэмы афармленьня}}. Глядзіце старонку [https://www.mediawiki.org/wiki/Manual:Skin_configuration Інструкцыя:Наладка тэмаў афармленьня] дзеля інфармацыі, як падключыць {{PLURAL:$4|яе|іх і абраць тэму па змоўчаньні}}.\n\n$2\n\n; Калі вы толькі што ўсталявалі MediaWiki:\n: Напэўна вы ўсталявалі з git або наўпрост з крынічнага коду з ужываньнем іншага мэтаду. Гэта чакана. Паспрабуйце ўсталяваць некалькі тэмаў афармленьня з [https://www.mediawiki.org/wiki/Category:All_skins каталёгу тэмаў mediawiki.org]:\n:* Спампуйце [https://www.mediawiki.org/wiki/Download tarball-усталёўнік], які ўтрымлівае некалькі тэмаў і пашырэньняў. Вы можаце скапіяваць каталёг <code>skins/</code> зь яго.\n:* Спампуйце tarball-усталёўнікі для асобных тэмаў з [https://www.mediawiki.org/wiki/Special:SkinDistributor mediawiki.org].\n:* [https://www.mediawiki.org/wiki/Download_from_Git#Using_Git_to_download_MediaWiki_skins Выкарыстайце Git, каб спампаваць тэмы афармленьня].\n: Калі вы распрацоўнік MediaWiki, гэта не павінна ўплываць на вашае git-сховішча.\n\n; Калі вы толькі што абнавілі MediaWiki:\n: MediaWiki вэрсіі 1.24 і навейшыя больш не падключаюць тэмы афармленьня аўтаматычна (глядзіце [https://www.mediawiki.org/wiki/Manual:Skin_autodiscovery Інструкцыя:Аўтаматычнае выяўленьне тэмаў афармленьня]). Вы можаце дадаць {{PLURAL:$5|наступны радок у|наступныя радкі ў}} <code>LocalSettings.php</code>, каб падключыць {{PLURAL:$5|усталяваную тэму|усе ўсталяваныя тэмы}} афармленьня:\n\n<pre dir=\"ltr\">$3</pre>\n\n; Калі вы толькі што зьмянілі <code>LocalSettings.php</code>:\n: Пераправерце назвы тэмаў афармленьня на наяўнасьць памылак.",
        "default-skin-not-found-no-skins": "Упс! Тэма афармленьня па змоўчаньні для вашай вікі, вызначаная ў <code>$wgDefaultSkin</code> як <code>$1</code>, недаступная.\n\nВы ня маеце ўсталяваных тэмаў афармленьня.\n\n; Калі вы толькі што ўсталявалі або абнавілі MediaWiki:\n: Напэўна вы ўсталявалі з git або наўпрост з крынічнага коду з ужываньнем іншага мэтаду. Гэта чакана. MediaWiki вэрсіі 1.24 і навейшыя ня ўтрымліваюць тэмы афармленьня ў галоўным сховішчы. Паспрабуйце ўсталяваць некалькі тэмаў афармленьня з [https://www.mediawiki.org/wiki/Category:All_skins каталёгу тэмаў mediawiki.org]:\n:* Спампуйце [https://www.mediawiki.org/wiki/Download tarball-усталёўнік], які ўтрымлівае некалькі тэмаў і пашырэньняў. Вы можаце скапіяваць каталёг <code dir=\"ltr\">skins/</code> зь яго.\n:* Спампуйце tarball-усталёўнікі для асобны тэмаў афармленьня з [https://www.mediawiki.org/wiki/Special:SkinDistributor mediawiki.org].\n:* [https://www.mediawiki.org/wiki/Download_from_Git#Using_Git_to_download_MediaWiki_skins Выкарыстайце Git, каб спампаваць тэмы афармленьня].\n: Калі вы распрацоўнік MediaWiki, гэта не павінна ўплываць на вашае git-сховішча. Глядзіце [https://www.mediawiki.org/wiki/Manual:Skin_configuration Інструкцыя:Наладка тэмаў афармленьня] дзеля інфармацыі, як падключыць іх і абраць тэму па змоўчаньні.",
        "default-skin-not-found-row-enabled": "* <code>$1</code> / $2 (уключана)",
index 2df341f..e65ac80 100644 (file)
        "right-changetags": "নির্দিষ্ট সংস্করণ এবং দীর্ঘ সম্পাদনাগুলোতে [[Special:Tags|ট্যাগ]] সংযোজন ও অপসারণ করুন",
        "grant-group-email": "ইমেইল পাঠান",
        "grant-createaccount": "অ্যাকাউন্ট তৈরি করুন",
+       "grant-editmycssjs": "আপনার সিএসএস/জাভাস্ক্রিপ্ট সম্পাদনা করুন",
        "grant-editmyoptions": "আপনার ব্যবহারকারী পছন্দসমূহ সম্পাদনা করুন",
        "grant-editmywatchlist": "আপনার নজরতালিকা সম্পাদনা করুন",
+       "grant-basic": "মৌলিক অধিকার",
        "newuserlogpage": "ব্যবহারকারী সৃষ্টির লগ",
        "newuserlogpagetext": "এটি নতুন ব্যবহারকারী সৃষ্টির লগ",
        "rightslog": "ব্যবহারকারীর অধিকার লগ",
        "foreign-structured-upload-form-label-infoform-categories": "বিষয়শ্রেণীসমূহ",
        "foreign-structured-upload-form-label-infoform-date": "তারিখ",
        "foreign-structured-upload-form-label-not-own-work-local-local": "এছাড়াও আপনি [[Special:Upload|ডিফল্ট আপলোডের পাতা]] চেষ্টা করতে পারেন।",
+       "foreign-structured-upload-form-2-label-ccbysa": "[https://creativecommons.org/licenses/by-sa/4.0/deed.bn ক্রিয়েটিভ কমন্স অ্যাট্রিবিউশন-শেয়ার অ্যালাইক ৪.০] লাইসেন্সের আওতায় এটি ইন্টারনেটে <strong>চিরতরে প্রকাশ করা ঠিক হবে</strong>",
        "foreign-structured-upload-form-3-label-yes": "হ্যাঁ",
        "foreign-structured-upload-form-3-label-no": "না",
        "backend-fail-stream": "\"$1\" ফাইলের স্ট্রিম দেখানো যাচ্ছে না।",
        "changecontentmodel-reason-label": "কারণ:",
        "changecontentmodel-success-title": "বিষয়বস্তুর প্রতিরূপ পরিবর্তিত হয়েছিলো",
        "changecontentmodel-success-text": "[[:$1]]-এর বিষয়বস্তুর ধরণ পরিবর্তন হয়েছে।",
+       "log-name-contentmodel": "বিষয়বস্তুর মডেল পরিবর্তন লগ",
        "logentry-contentmodel-change": "$1 $3 পাতার বিষয়বস্তুর মডেল \"$4\" থেকে \"$5\"-এ {{GENDER:$2|পরিবর্তন করেছেন}}",
        "logentry-contentmodel-change-revertlink": "প্রত্যাবর্তন",
        "logentry-contentmodel-change-revert": "প্রত্যাবর্তন",
        "export-download": "ফাইল হিসেবে সংরক্ষণ করা হোক",
        "export-templates": "টেমপ্লেট অন্তর্ভুক্তি",
        "export-pagelinks": "সম্পর্কিত পাতাগুলো এই ধাপ পর্যন্ত যুক্ত করো:",
+       "export-manual": "হাতেকরে পাতা যোগ করুন:",
        "allmessages": "সিস্টেম বার্তাসমূহ",
        "allmessagesname": "নাম",
        "allmessagesdefault": "আদি টেক্সট",
        "pageinfo-category-files": "ফাইলের সংখ্যা",
        "markaspatrolleddiff": "পরীক্ষিত হিসেবে চিহ্নিত করুন",
        "markaspatrolledtext": "এই পাতাটি পরীক্ষিত হিসেবে চিহ্নিত করুন",
+       "markaspatrolledtext-file": "এই ফাইলের সংস্করণ পরীক্ষিত হিসেবে চিহ্নিত করুন",
        "markedaspatrolled": "পরীক্ষিত বলে চিহ্নিত করুন",
        "markedaspatrolledtext": "আপনার নির্বাচিত সংস্করণ [[:$1]] পরীক্ষিত বলে চিহ্নিত করা হয়েছে।",
        "rcpatroldisabled": "সাম্প্রতিক পরিবর্তন প্যাট্রোল নিষ্ক্রিয়",
        "widthheightpage": "$1 × $2, $3টি {{PLURAL:$1|পাতা}}",
        "file-info": "ফাইলের আকার: $1, MIME ধরণ: $2",
        "file-info-size": "$1 × $2 পিক্সেল, ফাইলের আকার: $3, এমআইএমই ধরণ: $4",
-       "file-info-size-pages": "$1 × $2 পিক্সেল, fফাইলের আকার: $3, MIME ধরন: $4, $5 {{PLURAL:$5|পাতা|পাতাসমূহ}}",
+       "file-info-size-pages": "$1 × $2 পিক্সেল, ফাইলের আকার: $3, MIME ধরন: $4, $5টি {{PLURAL:$5|পাতা}}",
        "file-nohires": "এর চেয়ে বেশি রেজোলিউশন লভ্য নয়।",
        "svg-long-desc": "এসভিজি ফাইল, সাধারণত $1 × $2 পিক্সেল, ফাইলের আকার: $3",
        "svg-long-desc-animated": "এনিমেটেড এসভিজি ফাইল, সাধারণত $1 × $2 পিক্সেল, ফাইলের আকার: $3",
        "exif-morepermissionsurl": "অতিরিক্ত লাইসেন্সিং তথ্যাদি",
        "exif-attributionurl": "যখন এই কাজটি পুনরায় ব্যবহার করবেন, অনুগ্রহ করে এই লিংকটি যোগ করুন",
        "exif-preferredattributionname": "যখন এই কাজটি পুনরায় ব্যবহার করবেন, অনুগ্রহ করে প্রণেতাকে ক্রেডিট দিন",
-       "exif-pngfilecomment": "পিএনজি ফাইল কমেন্ট",
+       "exif-pngfilecomment": "পিএনজি ফাইলের মন্তব্য",
        "exif-disclaimer": "দাবিত্যাগ",
        "exif-contentwarning": "বিষয়বস্তু সতর্কবার্তা",
-       "exif-giffilecomment": "জিআইএফ ফাইল কমেন্ট",
+       "exif-giffilecomment": "জিআইএফ ফাইলের মন্তব্য",
        "exif-intellectualgenre": "উপাদানের প্রকার",
        "exif-subjectnewscode": "বিষয় কোড",
        "exif-scenecode": "আইপিটিসি সিন কোড",
        "exif-compression-4": "সিসিআইটিটি গ্রুপ ৪ ফ্যাক্স এনকোডিং",
        "exif-copyrighted-true": "কপিরাইটকৃত",
        "exif-copyrighted-false": "কপিরাইট সংক্রান্ত তথ্য নেই",
+       "exif-photometricinterpretation-1": "কালো এবং সাদা (কালো হল 0)",
        "exif-unknowndate": "অজানা তারিখ",
        "exif-orientation-1": "সাধারণ",
        "exif-orientation-2": "অনুভূমিকভাবে উল্টানো",
        "scarytranscludefailed-httpstatus": "[$1: HTTP $2 এর জন্য টেমপ্লেট আনা বিফল হয়েছে]",
        "scarytranscludetoolong": "[URL অতিরিক্ত দীর্ঘ]",
        "deletedwhileediting": "'''সতর্কীকরণ''': আপনি পাতাটি সম্পাদনা শুরু করার পরে তা মুছে ফেলা হয়েছে!",
-       "confirmrecreate": "আপনি সম্পাদনা শুরু করার পর ব্যবহারকারী [[User:$1|$1]] ([[User talk:$1|আলাপ]]) এই পাতাটি মুছে দিয়েছেন, নিচের কারণ দেখিয়ে:\n: ''$2''\nআপনি সত্যিই যে পাতাটি পুনরায় সৃষ্টি করতে চান, তা দয়া করে নিশ্চিত করুন।",
-       "confirmrecreate-noreason": "আপনি সম্পাদনা শুরু করার পর ব্যবহারকারী [[User:$1|$1]] ([[User talk:$1|আলাপ]]) এই পাতাটি মুছে দিয়েছেন। আপনি সত্যিই যে পাতাটি পুনরায় সৃষ্টি করতে চান, তা দয়া করে নিশ্চিত করুন।",
+       "confirmrecreate": "আপনি সম্পাদনা শুরু করার পর ব্যবহারকারী [[User:$1|$1]] ([[User talk:$1|আলাপ]]) এই পাতাটি মুছে দিয়েছেন, নিচের কারণ দেখিয়ে:\n: <em>$2</em>\nআপনি সত্যিই যে পাতাটি পুনরায় সৃষ্টি করতে চান, তা দয়া করে নিশ্চিত করুন।",
+       "confirmrecreate-noreason": "আপনি সম্পাদনা শুরু করার পর ব্যবহারকারী [[User:$1|$1]] ([[User talk:$1|আলাপ]]) এই পাতাটি {{GENDER:$1|মুছে}} দিয়েছেন। আপনি সত্যিই যে পাতাটি পুনরায় সৃষ্টি করতে চান, তা দয়া করে নিশ্চিত করুন।",
        "recreate": "পুনরায় তৈরি করো",
        "confirm_purge_button": "ঠিক আছে",
        "confirm-purge-top": "এই পাতার ক্যাশে পরিষ্কার করতে চান?",
        "htmlform-title-not-exists": "$1-এর অস্তিত্ব নেই।",
        "htmlform-user-not-exists": "<strong>$1</strong>-এর অস্তিত্ব নেই।",
        "htmlform-user-not-valid": "<strong>$1</strong> একটি বৈধ ব্যবহারকারীর নাম নয়।",
-       "sqlite-has-fts": "$1 সহ পূর্ণ টেক্সট সার্চ সমর্থন",
-       "sqlite-no-fts": "$1 বাদে পূর্ণ টেক্সট সার্চ সমর্থন",
+       "sqlite-has-fts": "$1 সহ পূর্ণ-পাঠ্য অনুসন্ধান সমর্থন",
+       "sqlite-no-fts": "$1 বাদে পূর্ণ-পাঠ্য অনুসন্ধান সমর্থন",
        "logentry-delete-delete": "$1 কর্তৃক $3 পাতাটি অপসারিত হয়েছে",
        "logentry-delete-restore": "$1 কর্তৃক $3 পাতাটি {{GENDER:$2|ফিরিয়ে আনা}} হয়েছে",
        "logentry-delete-event": "$1 {{PLURAL:$5|একটি লগ ইভেন্টের|$5 লগ ইভেন্টসমূহের}} দৃশ্যমানতা {{GENDER:$2|পরিবর্তন}} করেছেন $3: $4",
        "api-error-blacklisted": "অনুগ্রহ করে অপর কোনো বর্ণনামূলক নাম ব্যবহার করুন।",
        "sessionprovider-generic": "$1টি সেশন",
        "sessionprovider-mediawiki-session-cookiesessionprovider": "কুকি-ভিত্তিক সেশন",
+       "sessionprovider-nocookies": "কুকি নিষ্ক্রিয় করা। নিশ্চিত করুন যে আপনার কুকি সক্রিয় আছে এবং আবার শুরু করুন।",
        "randomrootpage": "অজানা মূল পাতা"
 }
index d52c605..fd8ca52 100644 (file)
        "rcshowhidemine": "$1 moje izmjene",
        "rcshowhidemine-show": "Prikaži",
        "rcshowhidemine-hide": "Sakrij",
-       "rcshowhidecategorization": "$1 kategorizaciju stranice",
+       "rcshowhidecategorization": "$1 kategorizaciju stranica",
        "rcshowhidecategorization-show": "Prikaži",
        "rcshowhidecategorization-hide": "Sakrij",
        "rclinks": "Prikaži posljednjih $1 izmjena u posljednjih $2 dana<br />$3",
        "filename-thumb-name": "Izgleda da je naslov u obliku sličice. Nemojte postavljati sličice nazad na istu wiki. Ako je riječ o nečemu drugom, popravite naziv datoteke tako da ima više značenja i da nema prefiks sličice.",
        "filename-bad-prefix": "Naziv datoteke koju postavljate počinje sa '''\"$1\"''', što je naziv koji obično automatski dodjeljuju digitalni fotoaparati i kamere.\nMolimo Vas da odaberete naziv datoteke koji opisuje njen sadržaj.",
        "filename-prefix-blacklist": " #<!-- ostavite ovu liniju onakvom kakva jeste --> <pre>\n# Sintaksa je slijedeća:\n#   * Sve od karaktera \"#\" pa do kraja je komentar\n#   * Svaka neprazna linija je prefiks za tipična imena datoteka koja automatski dodjeljuje digitalna kamera\nCIMG # Casio\nDSC_ # Nikon\nDSCF # Fuji\nDSCN # Nikon\nDUW # neki mobilni telefoni\nIMG # generic\nJD # Jenoptik\nMGP # Pentax\nPICT # razni\n #</pre> <!-- ostavite ovu liniju onakvom kakva jeste -->",
-       "upload-success-subj": "Uspješno slanje",
-       "upload-success-msg": "Vaša datoteka iz [$2] je uspješno postavljena. Dostupna je ovdje: [[:{{ns:file}}:$1]]",
-       "upload-failure-subj": "Problem pri postavljanju",
-       "upload-failure-msg": "Nastao je problem s Vašim postavljanjem sa [$2]:\n\n$1",
-       "upload-warning-subj": "Upozorenje pri slanju",
-       "upload-warning-msg": "Nastao je problem sa vašim postavljanjem sa [$2]. Morate se vratiti na [[Special:Upload/stash/$1|formu za postavljanje]] kako biste riješili ovaj problem.",
        "upload-proto-error": "Pogrešan protokol",
        "upload-proto-error-text": "Postavljanje sa vanjske lokacije zahtjeva URL-ove koji počinju sa <code>http://</code> ili <code>ftp://</code>.",
        "upload-file-error": "Unutrašnja greška",
        "wlheader-showupdated": "Stranice koje su izmijenjene otkad ste ih posljednji put posjetili prikazane su <strong>podebljanim slovima</strong>.",
        "wlnote": "Ispod {{PLURAL:$1|je najskorija izmjena|su <strong>$1</strong> najskorije izmjene|<strong>$1</strong> najskorijih izmjena}} načinjenih {{PLURAL:$2|posljednjeg sata|u posljednjih <strong>$2</strong> sata|u posljednjih <strong>$2</strong> sati}}, od $3, $4.",
        "wlshowlast": "Prikaži posljednjih $1 sati $2 dana",
-       "watchlistall2": "sve",
        "watchlist-hide": "Sakrij",
        "watchlist-submit": "Prikaži",
        "wlshowtime": "Prikaži posljednjih:",
index ed2dd59..d3b4ae5 100644 (file)
        "recentchangeslinked-page": "АгӀон цӀе:",
        "recentchangeslinked-to": "Кхечу агӀор, гайта хийцамаш агӀонашца, хӀоттийначу агӀонтӀе хьажорг йолуш",
        "recentchanges-page-added-to-category": "[[:$1]] категори чу тоьхна",
+       "recentchanges-page-removed-from-category": "[[:$1]] дӀаяьккхина категори чура",
        "upload": "Файл чуяккхар",
        "uploadbtn": "Файл чуяккхар",
        "reuploaddesc": "Юху гӀо файл чуйоккху агӀоне",
        "years": "{{PLURAL:$1|$1 шо|$1 шо}}",
        "ago": "$1 хьалха",
        "just-now": "хӀинца",
-       "hours-ago": "$1 {{PLURAL:$1|сахьт}}",
+       "hours-ago": "$1 {{PLURAL:$1|сахьт}} хьалха",
        "minutes-ago": "$1 {{PLURAL:$1|минот}} хьалха",
        "seconds-ago": "$1 {{PLURAL:$1|секунд}} хьалха",
        "monday-at": "оршотан дийнахь $1",
index 3ee81bd..e07376f 100644 (file)
        "laggedslavemode": "ئاگاداری: لەوانەیە لاپەڕەکە نوێکردنەکان لە بەر نەگرێت.",
        "readonly": "بنکەدراوە داخراوە",
        "enterlockreason": "هۆیەک بۆ قوفڵ‌کردنەکە بنووسە کە  تێیدا کاتی کردنەوەی قۆفڵەکە باس کرابێت",
-       "readonlytext": "بÙ\86Ú©Û\95دراÙ\88Û\95Ú©Û\95 Ù\84Û\95Ù\85 Ú©Ø§ØªÛ\95دا  Ù\84Û\95بÛ\95ر Ú\86اکسازÛ\8c Ø¦Ø§Ø³Ø§Û\8cÛ\8c Ø¨Û\86 Ù\86Ù\88سÛ\8cÙ\86Û\8c Ù\86Ù\88Û\8e Ù\88 Ø¯Û\95ستکارÛ\8c Ù\82Ù\88Ù\81Úµ Ú©Ø±Ø§Ù\88Ù\87. Ø¯Ù\88اÛ\8c Ø¦Û\95Ù\88Û\95 Ø¦Û\95گرÛ\8eتÛ\95Ù\88Û\95 Ø¨Û\86 Ø¦Ø§Ø³ØªÛ\8c Ø®Û\86Û\8c.\n\nئÛ\95Ù\88 Ø¨Û\95Ú\95Û\8eÙ\88بÛ\95رÛ\95Û\8c Ú©Û\95 Ù\82Ù\88Ù\81ÚµÛ\8c Ú©Ø±Ø¯Ù\88Ù\88Ù\87 Ø¦Û\95Ù\85 Ú\95Ù\88Ù\88Ù\86â\80\8cکردÙ\86Û\95Ù\88Û\95Û\8c Ù\86Ù\88Ù\88سÛ\8cÙ\88Û\95 : $1",
+       "readonlytext": "داتابÛ\8eس Ø¦Û\8eستا Ø¨Û\95 Ú¾Û\86Û\8c Ø¯Ø§Ù\86اÙ\86Û\8c Ø¨Ø§Ø¨Û\95تÛ\8c Ù\86Ù\88Û\8e Ù\88 Ú¯Û\86Ú\95اÙ\86کارÛ\8cÛ\8c Ø¯Û\8cÚ©Û\95 Ø¯Ø§Ø®Ø±Ø§Ù\88Û\95Ø\8c Ù\84Û\95Ù\88اÙ\86Û\95Û\8cÛ\95 Ø¨Û\95 Ù\85Û\95بÛ\95ستÛ\8c Ú\86اکسازÛ\8cÛ\8c Ú\95Û\86تÛ\8cÙ\86 Ø¨Û\8eت Ù\88 Ø¯Û\95Ú¯Ú\95Û\8eتÛ\95Ù\88Û\95 Ø¨Û\86 Ø¯Û\86Ø®Û\8c Ø¦Ø§Ø³Ø§Û\8cÛ\8c.\n\nئÛ\95Ù\88 Ø¨Û\95Ú\95Û\8eÙ\88Û\95بÛ\95رÛ\8c Ø³Û\8cستÛ\95Ù\85Û\95 Ú©Û\95 Ø¯Ø§Û\8cخستÙ\88Ù\88Û\95 Ø¦Û\95Ù\85 Ú\95Ù\88Ù\88Ù\86کردÙ\86Û\95Ù\88Û\95Û\8cÛ\95Û\8c Ù¾Û\8eØ´Ú©Û\95Ø´ Ú©Ø±Ø¯Ù\88Ù\88Û\95: $1",
        "missing-article": "داتابەیسەکە نەیتوانی دەقی پەڕەیەک بەناوی «$1» $2  بدۆزێتەوە کە دەبوا بیدۆزیبایەتەوە.\n\nئەمە زیاتر لە بەدواچوونی بەستەری جیاوازی یان مێژووی کۆنی پەڕەیەکی سڕدراو ڕوودەدات.\n\nئەگەر وا نەبێت، ئەوا ڕەنگە گرفتێکت لەم نەرمامێرەدا دۆزیبێتەوە.\nتکایە ئەمە بە ئاماژەدان بە ناونیشانی URLـەکەیەوە بە [[Special:ListUsers/sysop|بەڕێوبەرێک]] ڕاپۆرت بدە.",
        "missingarticle-rev": "(پێداچوونەوە#: $1)",
        "missingarticle-diff": "(جیاوازی: $1، $2)",
        "emaildisabled": "ئەم ماڵپەڕە ناتوانێ ئیمەیل بنێرێ.",
        "accountcreated": "ھەژمار دروست کرا",
        "accountcreatedtext": "هەژماری بەکارهێنەری [[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|لێدوان]]) دروست کراوە.",
-       "createaccount-title": "درووست‌کردنی هەژمارە بۆ {{SITENAME}}",
-       "createaccount-text": "کەسێک هەژمارەیەکی بۆ ئی‌مێڵ ئەدرەسەکی تۆ لەسەر {{SITENAME}} ($4) بەناوی \"$2\"، بە وشەی نهێنی \"$3\".\nئێستا دەبێ بڕۆیتە ژوورەوە و وشەی نهێنی بگۆڕیت.\n\nئەگەر ئەو هەژمارە بە هەڵە درووست‌کراوە، ئەم برووسکە لە بەرچاو مەگرە.",
+       "createaccount-title": "درووست کردنی ھەژمار بۆ {{SITENAME}}",
+       "createaccount-text": "کەسێک ھەژمارێکی بۆ ناونیشانی ئیمێلی تۆ لە {{SITENAME}}دا ($4) بە ناوی «$2»ـەوە و بە تێپەڕوشەی  «$3»ـەوە دروست کردووە.\nدەبێت ھەر ئێستا بچیتە چوورەوە و تێپەڕوشەیەکەت بگۆڕیت.\n\nئەگەر ئەم ھەژمارە بە ھەڵە دروست کراوە، دەکرێت گوێ بەم پەیامە نەدەیت.",
        "login-throttled": "زۆر زۆر ھەوڵت داوە بۆ چوونە ژوورەوە.\nتکایە $1 بوەستە پێش ھەوڵی دووبارە.",
        "loginlanguagelabel": "زمان: $1",
        "pt-login": "بچۆ ژوورەوە",
        "confirmedittext": "پێویستە پێش هەرجۆرە دەستکاریەکی لاپەڕەکان ئەدرەسی ئیمەیلت ڕاچاو کردبێت .<br />\nتکایە لە [[Special:Preferences|ھەڵبژاردەکانی بەکارھێنەر]] ئی‌مەیلەکەت دانێ و بڕواپێکراوی بکە.",
        "nosuchsectiontitle": "بەش نەدۆزرایەوە",
        "nosuchsectiontext": "هەوڵی دەستکاریکردنی بەشێکت داوە کە بوونی نیە.\nلەوانەیە لەو کاتە خەریکی بینینی پەڕە بوویت گۆزرابێتەوە یان سڕابێتەوە.",
-       "loginreqtitle": "پێویستە بچییە ژوورەوە",
-       "loginreqlink": "بچییە ژوورەوە",
+       "loginreqtitle": "پێویستە بچیتە ژوورەوە",
+       "loginreqlink": "بچیتە ژوورەوە",
        "loginreqpagetext": "بۆ دیتنی لاپەڕەکانی دیکە دەبێ $1 .",
        "accmailtitle": "تێپەڕوشە نێررا",
        "accmailtext": "تێپەڕوشەیەک کە بە هەڕەمەکی بۆ [[User talk:$1|$1]] دروست کرا، نێررا بۆ $2. دەتوانیت لە پەڕەی <em>[[Special:ChangePassword|گۆڕینی تێپەڕوشەدا]]</em> لە کاتی چوونەژوورەوەدا بیگۆڕی.",
        "anontalkpagetext": "----''ئەمە لاپەڕەی وتووێژە بۆ بەکارهێنەرێکی نەناسراوە کە هێشتا هەژمارەی درووست‌نەکردووه یان کەڵکی‌ لێ وەرناگرێ .\nلەبەر ئەوە مەجبوورین ئای‌پی ئەدرەسەکی ژمارەیی بۆ ناساندنی بەکار بێنین.\nئای‌پی ئەدرەسی وا لەوانەیه لە لایەن چەندین بەکارهێنەروە بەکاربێت.\nئەگەر تۆ بەکارهێنەرێکی نەناسراوی و هەست ئەکەی ئەم لێدوانە پەیوەندی بە تۆوە نیە تکایە [[Special:UserLogin/signup|ھەژمارێکی نوێ دروست بکە]] یان [[Special:UserLogin|بچۆ ژوورەوە]] لەبەر ئەوەی لەداهاتوودا دەگەڵ بەکارهێنەرانی‌ نەناسراوی دی تێکەڵ نەکرێیت. ''",
        "noarticletext": "ھەنووکە ھیچ دەقێک لەم پەڕەیەدا نییە.\nدەتوانی بۆ ئەم ناوە لە [[Special:Search/{{PAGENAME}}|پەڕەکانی تردا بگەڕێی]]، <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} لە لۆگەکاندا بگەڕێی]، یان [{{fullurl:{{FULLPAGENAME}}|action=edit}} ئەم پەڕەیە دەستکاری بکەیت]</span>.",
        "noarticletext-nopermission": "ھەنووکە ھیچ دەقێک لەم پەڕەیەدا نییە.\nدەتوانی لە پەڕەکانی تردا [[Special:Search/{{PAGENAME}}|بۆ ئەم ناوە بگەڕێی]]، یان <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} لە لۆگە پەیوەندیدارەکاندا بگەڕێی]</span>، بەڵام ناتوانی ئەم پەڕەیە دروست بکەی.",
-       "userpage-userdoesnotexist": "هەژماری بەکارهێنەری \"<nowiki>$1</nowiki>\" تۆمار نەکراوە.<br />\nگەر دەتەوێ ئەم لاپەڕە درووست‌کەی یان دەستکاری بکەی تکایە تاقی‌بکەوە .",
+       "userpage-userdoesnotexist": "ھەژماری بەکارھێنەریی «$1» تۆمار نەکراوە.\nتکایە دڵنیا ببەرەوە ئەگەر دەتھەوێت ئەم پەڕەیە دروست یان دەستکاری بکەیت.",
        "userpage-userdoesnotexist-view": "ھەژماری بەکارھێنەریی «$1» تۆمار نەکراوە.",
        "blocked-notice-logextract": "ھەنووکە ئەم بەکارھێنەرە بەربەست کراوە.\nدوایین بابەتی لۆگی بەربەستن لە ژێرەوە ھاتووە:",
        "clearyourcache": "تێبینی:''' لە دوای پاشەکەوت کردن، لەوانەیە  بۆ بینینی گۆڕانکارییەکان پێویست بێ cacheی وێبگەڕەکەت پاکبکەیتەوە.\n* '''Firefox / Safari:''' دوگمەی ''Shift'' بگرە کاتێک لەسەر ''Reload''دا کرتە دەکەی، یان ھەرکام لە ''Ctrl-F5'' یان ''Ctrl-R'' لێبدە (''⌘-R'' لەسەر Mac دا)\n* '''Google Chrome:''' دوگمەکانی ''Ctrl-Shift-R'' لێبدە  (''⌘-Shift-R'' لەسەر Mac دا)\n* '''Internet Explorer:''' دوگمەی ''Ctrl'' بگرە کاتێک لەسەر  ''Refresh''دا کرتە دەکەی، یان ''Ctrl-F5'' لێبدە\n* '''Opera:''' لە ڕێگەی ''Tools → Preferences'' ەوە cacheەکە بسڕەوە.",
        "template-semiprotected": "(نیوەپارێزراو)",
        "hiddencategories": "ئەم پەڕە ئەندامێکی {{PLURAL:$1|١ پۆلی شاراوەیە|$1 پۆلی شاراوەیە}}:",
        "edittools": "<!-- دەقی ئێرە لە ژێری فۆرمی دەستکاری و بارکردندا نیشان دەدرێت. -->",
-       "nocreatetext": "{{SITENAME}} توانای درووست‌کردنی لاپەڕە نوێکانی داخستووە.<br />\nئەتوانی بگەڕێتەوە دواوە و یەکێک لەو لاپەڕانەی وا هەن دەستکاری بکەیت ، یان [[Special:UserLogin|بچۆ ژوورەوە یان هەژمارێک درووست‌بکە]]",
+       "nocreatetext": "{{SITENAME}} توانای دروست کردنی پەڕەی نوێی سنووردار کردووە.\nدەتوانیت بگەڕێیتەوە دواوە و پەڕەیەک دەستکاری بکەیت یان [[Special:UserLogin|بچیتە ژوورەوە یان ھەژمارێک دروست بکەیت]].",
        "nocreate-loggedin": "ئیجازەی دروست کردنی پەڕەی نوێت نیە.",
        "sectioneditnotsupported-title": "بەش دەستکاریکردنی پشتیوانی ناکرێ",
        "sectioneditnotsupported-text": "دەستکاریکردنی بەش لە پەڕەدا پشتیوانی ناکرێ.",
        "powersearch-legend": "گەڕانی پێشکەوتوو",
        "powersearch-ns": "گەڕان لە بۆشاییی ناوەکانی:",
        "powersearch-togglelabel": "تاوتوێ بکە:",
-       "powersearch-toggleall": "ھەموو",
+       "powersearch-toggleall": "ھەموویان",
        "powersearch-togglenone": "ھیچیان",
        "powersearch-remember": "ھەڵبژاردەکانت بۆ گەڕانەکانی تر لە بیر بێت",
        "search-external": "گەڕانی دەرەکی",
        "action-edit": "دەستکاریی ئەم پەڕەیە",
        "action-createpage": "دروستکردنی پەڕەکان",
        "action-createtalk": "دروستکردنی پەڕەکانی وتووێژ",
-       "action-createaccount": "درووست‌کردنی هەژمارەی ئەم بەکارهێنەرە",
+       "action-createaccount": "دروست کردنی ئەم ھەژماری بەکارھێنەرییە",
        "action-history": "مێژووی ئەم پەڕەیە ببینە",
        "action-minoredit": "نیشان‌کردنی ئەم دەستکاریە وەک بچووک",
        "action-move": "گواستنەوەی ئەم پەڕەیە",
        "imagelinks": "بەکارھێنانی پەڕگە",
        "linkstoimage": "لەم {{PLURAL:$1|پەڕەی خوارەوە بەستەر دراوە|$1 پەڕەی خوارەوە بەستەر دراوە}} بۆ ئەم پەڕگە:",
        "linkstoimage-more": "زیاتر لە $1 {{PLURAL:$1|بەستەری لاپەڕە|بەستەری لاپەڕە}} بۆ ئەم پەڕگه.\nئەم لیستە {{PLURAL:$1|یەکەم لاپەڕەی بەستەرە|یەکەم لاپەڕە $1 بەستەرە}} بۆ تەنها یەم پەڕگە.\nهەروا [[Special:WhatLinksHere/$2|لیستی تەواو]] ئامادەی کەڵک وەرگرتنە.",
-       "nolinkstoimage": "‌لاپەڕەیەک نەدۆزرایەوە کە بەستەری هەبێ بۆ ئەم پەڕگە.",
+       "nolinkstoimage": "ھیچ پەڕەیەک نییە کە بەستەری ھەبێت بۆ ئەم پەڕگەیە.",
        "morelinkstoimage": "[[Special:WhatLinksHere/$1|بەستەری زیاتر]] ببینە بۆ ئەم پەڕگە.",
        "linkstoimage-redirect": "$1 (ڕەوانەکەری پەڕگە) $2",
        "duplicatesoffile": "ئەم {{PLURAL:$1|پەڕگە دووبارەکرنەوەیەکی|پەڕگانە دووبارەکردنەوەی}} ئەم پەڕگەن ([[Special:FileDuplicateSearch/$2|وردەکاری زیاتر]]):",
        "unusedtemplatestext": "ئەم پەڕە هەموو پەڕەکانی بۆشاییی ناوی {{ns:template}} بە لیست دەکات کە لە پەڕەی تردا بەکارنەھێنراون.\nلە بیری نەکەی پێش سڕینەوەیان پشکنینی بەستەرەکانی تر بۆ داڕێژەکان بکەی.",
        "unusedtemplateswlh": "بەستەرەکانی تر",
        "randompage": "پەڕەی ھەڕەمەکی",
-       "randompage-nopages": "هیچ لاپەڕەیەک لەم {{PLURAL:$2|ناوبۆشاییەدا|ناوبۆشاییانەدا}} نیە: $1.",
+       "randompage-nopages": "ھیچ پەڕەیەک لە {{PLURAL:$2|بۆشایی ناو|بۆشایی ناوەکان}}ی خوارەوەدا نییە: $1.",
        "randomincategory": "پەڕەیەک بە ھەڵکەوت لە پۆلدا",
        "randomincategory-submit": "بڕۆ",
        "randomredirect": "ڕەوانەکەری ھەڕەمەکی",
        "deletereason-dropdown": "* ھۆکارە باوەکانی سڕینەوە\n** سپام\n** خراپکاری\n** پێشێلکردنی مافی لەبەرگرتنەوە\n** داخوازی دانەر\n** ڕەوانەکەری شکاو",
        "delete-edit-reasonlist": "دەستکاری کردنی ھۆکارەکانی سڕینەوە",
        "delete-toobig": "ئەم لاپەڕە مێژوویەکی دەستکاری زۆر گەورەی هەیە، زیاتر لە $1 {{PLURAL:$1|پێداچوونەوە|پێداچوونەوە}}.\nبۆ بەرگری لە خراپ‌بوونی چاوەڕوان نەکراوی {{SITENAME}}، سڕینەوەی لاپەڕەی وا بەربەست‌کراوە.",
-       "delete-warning-toobig": "ئÛ\95Ù\85 Ù\84اپÛ\95Ú\95Û\95 Ù\85Û\8eÚ\98Ù\88Ù\88Û\8cÛ\95Ú©Û\8c Ø¯Û\95ستکارÛ\8c Ø²Û\86ر Ú¯Û\95Ù\88رÛ\95Û\8c Ù\87Û\95Û\8cÛ\95Ø\8c Ø²Û\8cاتر Ù\84Û\95 $1 {{PLURAL:$1|Ù¾Û\8eداÚ\86Ù\88Ù\88Ù\86Û\95Ù\88Û\95|Ù¾Û\8eداÚ\86Ù\88Ù\88Ù\86Û\95Ù\88Û\95}}.\nسÚ\95Û\8cÙ\86Û\95Ù\88Û\8c Ø¦Û\95Ù\88Û\95 Ù\84Û\95 Ù\88اÙ\86Û\95Û\8cÛ\95 Ú©Ø§Ø±Û\95کاÙ\86Û\8c Ø¨Ù\86Ú©Û\95دراÙ\88Û\8c {{SITENAME}} ØªÙ\88Ù\88Ø´Û\8c Ú©Û\8eØ´Û\95 Ø¨Ú©Ø§ØªØ\9b\nدÙ\88Ù\88رÙ\86Ù\88اÚ\95اÙ\86Û\95 Ø¬Û\8eâ\80\8cبÛ\95جÛ\8eÛ\8c Ø¨Ú©ە.",
+       "delete-warning-toobig": "ئÛ\95Ù\85 Ù¾Û\95Ú\95Û\95Û\8cÛ\95 Ù\85Û\8eÚ\98Ù\88Ù\88Û\8cÛ\95Ú©Û\8c Ø¯Û\95ستکارÛ\8cÛ\8c Ø²Û\86ر Ú¯Û\95Ù\88رÛ\95Û\8c Ú¾Û\95Û\8cÛ\95Ø\8c Ø²Û\86رتر Ù\84Û\95 $1 {{PLURAL:$1|Ù¾Û\8eداÚ\86Ù\88Ù\88Ù\86Û\95Ù\88Û\95}}.\nسÚ\95Û\8cÙ\86Û\95Ù\88Û\95Û\8c Ø¦Û\95Ù\88 Ù¾Û\95Ú\95Û\95Û\8cÛ\95 Ù\84Û\95Ù\88اÙ\86Û\95Û\8c Ú©Ø§Ø±Û\95کاÙ\86Û\8c Ø¨Ù\86Ú©Û\95دراÙ\88Û\95Û\8c {{SITENAME}} ØªÙ\88Ù\88Ø´Û\8c Ú©Û\8eØ´Û\95 Ø¨Ú©Ø§ØªØ\9b\nبÛ\95 Ø³Û\95رÙ\86جÛ\95Ù\88Û\95 Ø¨Ú\86Û\86 Ù¾Û\8eØ´Û\95Ù\88ە.",
        "deleting-backlinks-warning": "'''ھۆشدار:''' [[Special:WhatLinksHere/{{FULLPAGENAME}}|پەڕەکانی تر]] بەم پەڕەیەی دەتەوێ بیسڕییەوە بەستەر دراوە.",
        "rollback": "گەڕاندنەوەی دەستکارییەکان",
        "rollbacklink": "گەڕاندنەوە",
        "cannotundelete": "ھێنانەوە سەرکەوتوو نەبوو:\n$1",
        "undeletedpage": "'''$1 هێنراوەتەوە'''\n\nبۆ دیتنی پێشینەی دوایین سڕینەوەکان و هێنانەوەکان سەرنجی [[Special:Log/delete|لۆگی سڕینەوە]] بدە.",
        "undelete-header": "بۆ دیتنی ئەو لاپەڕانەی لەم داییانەدا سڕاونەتەوە چاو لە [[Special:Log/delete|لۆگی سڕینەوە]] بکە.",
-       "undelete-search-title": "Ú¯Û\95Ú\95اÙ\86 Ø¨Û\86 Ù\84اپÛ\95Ú\95Û\95 Ø³Ú\95اوەکان",
-       "undelete-search-box": "Ú¯Û\95Ú\95اÙ\86 Ø¨Û\86 Ù\84اپÛ\95Ú\95Û\95 Ø³Ú\95اوەکان",
+       "undelete-search-title": "Ú¯Û\95Ú\95اÙ\86 Ø¨Û\86 Ù¾Û\95Ú\95Û\95 Ø³Ú\95راوەکان",
+       "undelete-search-box": "Ú¯Û\95Ú\95اÙ\86 Ø¨Û\86 Ù¾Û\95Ú\95Û\95 Ø³Ú\95راوەکان",
        "undelete-search-prefix": "نیشان‌دانی ئەو لاپەڕانەی دەستپێکیان ئەمەیە:",
        "undelete-search-submit": "گەڕان",
        "undelete-no-results": "لە ئەرشیڤی سڕاوەکانی لاپەڕەیەکی هاوتا نەدۆزرایەوە.",
        "whatlinkshere-title": "ئەو پەڕانەی بەستەریان ھەیە بۆ «$1»",
        "whatlinkshere-page": "پەڕە:",
        "linkshere": "پەڕەکانی ژێرەوە بەستەر دراون بۆ <strong>[[:$1]]</strong>:",
-       "nolinkshere": "هیچ لاپەڕەیەک بەستەری نەداوە بە '''[[:$1]]'''.",
-       "nolinkshere-ns": "هیچ لاپەڕەیەک بەستەری نەداوە بە '''[[:$1]]''' لە بۆشایی‌ناوی هەڵبژێردراو.",
+       "nolinkshere": "ھیچ پەڕەیەک بەستەری نییە بۆ <strong>[[:$1]]</strong>.",
+       "nolinkshere-ns": "ھیچ پەڕەیەک بەستەری نییە بۆ <strong>[[:$1]]</strong> لە بۆشایی ناوی هەڵبژێرراودا.",
        "isredirect": "پەڕەی ڕەوانەکەر",
        "istemplate": "بەکارھێنراو",
        "isimage": "بەستەری پەڕگە",
        "movenotallowed": "ڕێگەت پێ‌نەدراوە بۆ گواستنەوەی لاپەڕەکان.",
        "movenotallowedfile": "ڕێگەت پێ‌نەدراوە بۆ گواستنەوەی پەڕگەکان.",
        "cant-move-user-page": "ڕێگەت پێ‌نەدراوە بۆ گواستنەوەی لاپەڕەکانی بەکارهێنەر (جیاواز لە ژێرلاپەڕەکان).",
-       "cant-move-to-user-page": "ڕێگەت پێ‌نەدراوە بۆ گواستنەوەی لاپەڕەیەک بۆ لاپەڕەی بەکارهێنەر (غەیری بۆ ژێرلاپەڕەی بەکارهێنەر).",
+       "cant-move-to-user-page": "مافی ئەوەت نییە کە پەڕەیەک بگوێزیتەوە بۆ پەڕەیەکی بەکارھێنەری (بەڵام بۆ ژێرپەڕەیەکی بەکارھێنەری دەتوانیت).",
        "newtitle": "بۆ ناوی نوێی:",
        "move-watch": "پەڕەی سەرچاوە و مەبەست بخە ژێر چاودێری",
        "movepagebtn": "ئەم پەڕەیە بگوازەوە",
        "movepage-moved-redirect": "ڕەوانەکەرێک دروست کرا.",
        "movepage-moved-noredirect": "لە دانانی ڕەوانەکەر بەرگری کرا.",
        "articleexists": "پەڕەیەک بەم ناوە ھەیە یان ئەو ناوەی تۆ ھەڵتبژاردووە ڕێگەی پێنەدراوە.\nتکایە ناوێکی دیکە ھەڵبژێرە.",
-       "cantmove-titleprotected": "ناتوانی لاپەڕەیەک بگوێزیتەوە بۆ ئەم شوێنە، لەبەر ئەوەی سەردێڕی نوێ لە درووست‌کردن پارێزراوە.",
+       "cantmove-titleprotected": "ناتوانیت پەڕەیەک بگوێزیتەوە بۆ ئەم شوێنە، چونکە سەرناوە نوێیەکە پارێزراوە لە درووست کردن.",
        "movetalk": "پەڕەی لێدوانی پەیوەندیدار بگوازەوە",
        "move-subpages": "ژێرپەڕەکانی بگوازەوە (ھەتا $1 پەڕە)",
        "move-talk-subpages": "ژێرپەڕەکانی پەڕەی لێدوان بگوازەوە (ھەتا $1 پەڕە)",
        "delete_and_move_text": "== پێویستییەکانی سڕینەوە ==\nلاپەڕەی مەبەست \"[[:$1]]\" لە پێش‌دا هەیە.\nئایا دەتەوێ ئەوە بسڕیتەوە تا ڕێگە بۆ گواستنەوەی بکەیتەوە؟",
        "delete_and_move_confirm": "بەڵێ، پەڕەکە بسڕەوه",
        "delete_and_move_reason": "سڕایەوە بۆ کردنەوەی ڕیگە بۆ گواستنەوە لە «[[$1]]»ەوە",
-       "selfmove": "سەردێڕەکانی سەرچاوە و مەبەست یەکێکن؛\nناکرێ لاپەڕەیەک بۆ سەر خۆی‌ بگوازرێتەوە.",
+       "selfmove": "سەرناوی سەرچاوە و مەبەست یەکێکن؛\nناکرێت پەڕەیەک بۆ سەر خۆی‌ بگوازرێتەوە.",
        "immobile-source-namespace": "پەڕەکان لە بۆشاییی ناوی \"$1\"دا ناگوێزرێنەوە.",
        "immobile-target-namespace": "گواستنەوەی لاپەڕە بۆناو بۆشایی‌ناو \"$1\" ناکرێت.",
        "immobile-target-namespace-iw": "بەستەرێکی نێوان‌ویکی ئامانجێکی گونجاو نیە بۆ گواستنەوەی لاپەڕە.",
        "protectedpagemovewarning": "'''ھۆشیار بە: ئەم پەڕە پارێزراوە بۆ ئەوی تەنیا ئەو بەکارھێنەرانە کە مافەکانی بەڕێوەبەرایەتییان ھەیە بتوانن بیگوازنەوە.'''\nدوایین لۆگ بۆ ژێدەر لە خوارەوەدا ھاتووە:",
        "semiprotectedpagemovewarning": "'''ئاگاداری:''' ئەم پەڕە پارێزراوە بۆ ئەوی تەنھا بەکارھێنەرە تۆمارکراوەکان بتوانن بیگوازنەوە.\nدوایین لۆگ بۆ ژێدەر لە خوارەوەدا ھاتووە:",
        "export": "ھەناردنی پەڕەکان",
-       "exporttext": "دەتوانی دەق و مێژووی دەستکاری لاپەڕەیەکی تایبەت یان دەستە لاپەڕەیەک بۆ ناو پەڕگەیەکی XML هەناردن بکەیت.\nدواتر بە کەڵک‌وەرگرتن لە [[Special:Import|لاپەڕەی هێنانەناوە]] لە مێدیاویکی‌دا، دەتوانی بیهێنیتە ناو ویکی‌یەکانی دیکە.\n\nبۆ هەناردنی لاپەڕەکان، سەردێڕەکان لە چوارچێوەی دەقی خوارەوە بنووسە، هەر هێڵێک یەک سەردێڕ. هەروا هەڵبژێرە ئایا پێداچوونەوەی ئێستا و هەموو پێداچوونەوە کۆنەکانت دەوێ یان هەر پێداچوونەوەی ئێستا و زانیاریی سەبارەت بە دوایین دەستکاری.\n\nلە بابەتی دواتر هەروەها دەتوانی لە بەستەرێک کەڵک وەرگریت، بۆ نموونە [[{{#Special:Export}}/{{MediaWiki:Mainpage}}]] بۆ لەپەڕەی \"[[{{MediaWiki:Mainpage}}]]\".",
+       "exporttext": "دەتوانیت دەق و مێژووی دەستکاریی پەڕەیەکی دەستنیشان کراو یان کۆمەڵێک پەڕە کە ناو پەڕگەیەکی XML دا پێچراونەتەوە، هەناردە بکەیت.\nدەکرێت ئەمە لە ویکییەکی دیکەدا ھاوردە بکرێت بە کەڵک وەرگرتن لە  ئامرازی [[Special:Import|ھاوردە کردنی پەڕە]]ی MediaWiki.\n\nبۆ هەناردە کردنی پەڕەکان، سەرناوەکانیان لە چوارچێوەی خوارەوەدا بنووسە، هەر سەرناوێک لە هێڵێکدا. و هەڵبژێرە کە پێداچوونەوەی ئێستا و ھەموو پێداچوونەوە کۆنەکانت دەوێت یان تەنھا پێداچوونەوەی ئێستا و زانیاریی سەبارەت بە دوایین دەستکاری.\n\nئەگەر تەنھا پێداچوونەوەی ئێستات دەوێت، دەتوانیت بەستەرێکیش بە کار بھێنیت، بۆ نموونە [[{{#Special:Export}}/{{MediaWiki:Mainpage}}]] بۆ پەڕەی «[[{{MediaWiki:Mainpage}}]]».",
        "exportall": "ھەموو پەڕەکان ھەناردە بکە",
        "exportcuronly": "تەنها پێداچوونەوەی ئێستا لەخۆ بگرێت نەک هەموو مێژوو",
        "exportnohistory": "----\n'''ئاگاداربە: '''ھەناردنی ھەموو مێژووی پەڕەکان لەم فۆرمەوە لەبەر ھۆکاری ڕێخستن، داخراوە.",
        "tooltip-watch": "ئەم پەڕە بخە سەر لیستی چاودێریت",
        "tooltip-watchlistedit-normal-submit": "ناونیشانەکان لاببە",
        "tooltip-watchlistedit-raw-submit": "نوێکردنەوەی لیستی چاودێری",
-       "tooltip-recreate": "درووست‌کردنەوەی لاپەڕە ئەگەرچی سڕاوەتەوە",
+       "tooltip-recreate": "پەڕەکە دروست‌ بکەرەوە ئەگەرچی سڕراوەتەوە",
        "tooltip-upload": "دەستپێکردنی بارکردن",
        "tooltip-rollback": "«گەڕاندنەوە» بە یەک کرتە گۆڕانکاریی/گۆڕانکارییەکانی ئەم پەڕەیە دەگەڕێنێتەوە بۆ دوایین بەشداربوو",
        "tooltip-undo": "«پووچەڵکردنەوە» ئەم گۆڕانکارییە دەگەڕێنێتەوە و فۆرمی دەستکاریکردن لە شێوەی پێشبینیندا دەکاتەوە. بەم جۆرە دەکرێ ھۆکارێک لە کورتەی دەستکاریدا بنووسرێ.",
index 26205fc..7565ad1 100644 (file)
        "changeemail-newemail": "Nová e-mailová adresa:",
        "changeemail-newemail-help": "Toto pole by mělo zůstat prázdné, pokud chcete odstranit svou e-mailovou adresu. Pokud bude e-mailová adresa odstraněná, nebudete si moct obnovit zapomenuté heslo a přijímat e-maily z této wiki.",
        "changeemail-none": "(žádná)",
-       "changeemail-password": "Vaše heslo do {{gender:2sg|{{SITENAME}}}}:",
+       "changeemail-password": "{{GENDER:|Vaše heslo}} do {{GRAMMAR:2sg|{{SITENAME}}}}:",
        "changeemail-submit": "Změnit e-mail",
        "changeemail-throttled": "Provedli jste příliš mnoho pokusů o přihlášení.\nČekejte prosím $1 a zkuste to znovu.",
        "changeemail-nochange": "Zadejte prosím odlišnou e-mailovou adresu.",
index 44b8704..145a9bc 100644 (file)
        "jumptonavigation": "плаваниѥ",
        "jumptosearch": "исканиѥ",
        "pool-errorunknown": "нєвѣдома блаꙁна",
-       "aboutsite": "О {{grammar:instrumental|{{SITENAME}}}}",
+       "aboutsite": "{{grammar:genitive|{{SITENAME}}}} опьсаниѥ",
        "aboutpage": "Project:О сѥмь опꙑтьствовании",
        "copyright": "подъ прощєниѥмь $1 пьсано ѥстъ · ащє ино нє каꙁано ѥстъ",
        "copyrightpage": "{{ns:project}}:Творьцъ права",
        "nlinks": "$1 {{PLURAL:$1|съвѧꙁь|съвѧꙁи|съвѧꙁии}}",
        "nmembers": "$1 {{PLURAL:$1|члѣнъ|члѣна|члѣни|члѣнъ}}",
        "shortpages": "кратъкꙑ страницѧ",
+       "protectedpages-reason": "какъ съмꙑслъ",
        "listusers": "польꙃєватєлъ каталогъ",
        "usereditcount": "$1 {{PLURAL:$1|мѣна|мѣнꙑ|мѣнъ}}",
        "usercreated": "{{GENDER:$3|сътворилъ|сътворила}} мѣсто $1 въ $2",
        "fileduplicatesearch-submit": "ищи",
        "specialpages": "нарочьнꙑ страницѧ",
        "tag-filter": "[[Special:Tags|мѣтъць]] сито :",
+       "tag-list-wrapper": "([[Special:Tags|{{PLURAL:$1|мѣтъка|мѣтъцѣ|мѣтъци}}]]: $2)",
+       "tags-active-yes": "да",
+       "tags-active-no": "нѣтъ",
        "tags-edit": "исправи",
+       "tags-hitcount": "$1 {{PLURAL:$1|мѣна|мѣноу|мѣнъ}}",
+       "tags-create-reason": "какъ съмꙑслъ :",
+       "tags-create-submit": "сътворѥниѥ",
+       "tags-delete-reason": "какъ съмꙑслъ :",
+       "tags-activate-reason": "какъ съмꙑслъ :",
+       "tags-deactivate-reason": "какъ съмꙑслъ :",
        "htmlform-no": "нѣтъ",
        "htmlform-yes": "да",
        "logentry-delete-delete": "$1 {{GENDER:$2|поничьжилъ|поничьжила}} страницѫ ⁖ $3 ⁖",
index d3fe597..ade3f30 100644 (file)
@@ -63,6 +63,7 @@
        "tog-hideminor": "Skjul mindre ændringer i listen over seneste ændringer",
        "tog-hidepatrolled": "Skjul patruljerede redigeringer i seneste ændringer",
        "tog-newpageshidepatrolled": "Skjul patruljerede sider på listen over nye sider",
+       "tog-hidecategorization": "Skjul kategorisering af sider",
        "tog-extendwatchlist": "Udvid overvågningslisten til at vise alle ændringer og ikke kun den nyeste",
        "tog-usenewrc": "Gruppér ændringer per side i listen over seneste ændringer og i overvågningslisten",
        "tog-numberheadings": "Automatisk nummerering af overskrifter",
        "tog-watchlisthidebots": "Skjul ændringer fra botter i overvågningslisten",
        "tog-watchlisthideminor": "Skjul mindre ændringer i overvågningslisten",
        "tog-watchlisthideliu": "Skjul indloggede brugeres redigeringer i overvågningslisten",
+       "tog-watchlistreloadautomatically": "Opdater overvågningslisten automatisk, når et filter er ændret (JavaScript påkrævet)",
        "tog-watchlisthideanons": "Skjul anonyme brugeres redigeringer i overvågningslisten",
        "tog-watchlisthidepatrolled": "Skjul patruljerede ændringer fra overvågningslisten",
+       "tog-watchlisthidecategorization": "Skjul kategorisering af sider",
        "tog-ccmeonemails": "Send mig kopier af e-mails som jeg sender til andre brugere",
        "tog-diffonly": "Vis ikke sideindhold neden under versionssammenligninger",
        "tog-showhiddencats": "Vis skjulte kategorier",
        "morenotlisted": "Denne liste er ikke komplet.",
        "mypage": "Side",
        "mytalk": "Diskussion",
-       "anontalk": "Diskussionsside for denne IP-adresse",
+       "anontalk": "Diskussion",
        "navigation": "Navigation",
        "and": "&#32;og",
        "qbfind": "Søg",
        "viewcount": "Siden er vist {{PLURAL:$1|en gang|$1 gange}}.",
        "protectedpage": "Beskyttet side",
        "jumpto": "Skift til:",
-       "jumptonavigation": "Navigation",
-       "jumptosearch": "Søgning",
+       "jumptonavigation": "navigering",
+       "jumptosearch": "søgning",
        "view-pool-error": "Beklager, men serverne er i øjeblikket overbelastede.\nFor mange brugere prøver at se denne side.\nVent et øjeblik, før du prøver at besøge denne side igen.\n\n$1",
        "generic-pool-error": "Beklager, men serverne er i øjeblikket overbelastede.\nFor mange brugere prøver at se denne side.\nVent et øjeblik før du prøver at besøge denne side igen.",
        "pool-timeout": "Timeout mens man venter på låsningen",
        "virus-scanfailed": "virus-scan fejlede med fejlkode $1",
        "virus-unknownscanner": "ukendt virus-scanner:",
        "logouttext": "'''Du er nu logget af.'''\n\nBemærk, at nogle sider stadigvæk kan vises som om du var logget på, indtil du tømmer din browsers cache.",
+       "cannotlogoutnow-title": "Kan ikke logge af på nuværende tidspunkt",
+       "cannotlogoutnow-text": "Det er ikke muligt at logge af når du bruger $1.",
        "welcomeuser": "Velkommen, $1!",
        "welcomecreation-msg": "Din konto er blevet oprettet.\nGlem ikke at ændre dine [[Special:Preferences|{{SITENAME}} indstillinger]].",
        "yourname": "Dit brugernavn:",
        "userlogin-remembermypassword": "Husk mig",
        "userlogin-signwithsecure": "Brug sikker forbindelse",
        "cannotloginnow-title": "Kan ikke logge ind på nuværende tidspunkt",
+       "cannotloginnow-text": "Det er ikke muligt at logge på når du bruger $1.",
        "yourdomainname": "Dit domænenavn:",
        "password-change-forbidden": "Du kan ikke ændre adgangskoder på denne wiki.",
        "externaldberror": "Der er opstået en fejl i en ekstern adgangsdatabase, eller du har ikke rettigheder til at opdatere denne.",
        "wrongpasswordempty": "Du glemte at indtaste adgangskode. Prøv igen.",
        "passwordtooshort": "Adgangskoden skal mindst være på $1 {{PLURAL:$1|tegn|tegn}}.",
        "passwordtoolong": "Adgangskoden må ikke være længere end {{PLURAL:$1|et tegn|$1 tegn}}.",
+       "passwordtoopopular": "Almindeligt brugte adgangskoder, kan ikke bruges. Vælg venligst en mere unik adgangskode.",
        "password-name-match": "Adgangskoden må ikke være det samme som brugernavnet.",
        "password-login-forbidden": "Brugen af dette brugernavn og adgangskode er blevet forbudt.",
        "mailmypassword": "Nulstil adgangskode",
        "resetpass_submit": "Gem adgangskode og log på",
        "changepassword-success": "Din adgangskode er nu ændret!",
        "changepassword-throttled": "Du har forsøgt at logge på for mange gange for nylig.\nVent venligst $1, før du prøver igen.",
+       "botpasswords": "Bot adgangskoder",
+       "botpasswords-summary": "<em>Bot adgangskoder</em> giver adgang til en brugerkonto via API'en, uden at bruge kontoens normale login-legitimationsoplysninger. Brugerrettighederne kan være begrænset, når du er logget på med et bot password,.\n\nHvis du ikke ved, hvorfor du måske ønsker at gøre dette, bør du nok ikke gøre det. Ingen bør nogensinde bede dig om at generere et af disse, og give det til dem.",
+       "botpasswords-disabled": "Bot adgangskoder er deaktiveret.",
+       "botpasswords-no-central-id": "For at bruge bot adgangskoder, skal du være logget på en central konto.",
+       "botpasswords-existing": "Eksisterende bot adgangskoder",
+       "botpasswords-createnew": "Opret en ny bot adgangskode",
+       "botpasswords-editexisting": "Redigere en eksisterende bot adgangskode",
+       "botpasswords-label-appid": "Botnavn:",
+       "botpasswords-label-create": "Opret",
+       "botpasswords-label-update": "Opdatér",
+       "botpasswords-label-cancel": "Afbryd",
+       "botpasswords-label-delete": "Slet",
+       "botpasswords-label-resetpassword": "Nulstil adgangskode",
+       "botpasswords-label-grants": "Tilgængelige bevillinger:",
        "resetpass_forbidden": "Adgangskoder kan ikke ændres",
        "resetpass-no-info": "Du skal være logget på for at komme direkte til denne side.",
        "resetpass-submit-loggedin": "Skift adgangskode",
        "revision-info": "Version fra $1 af $2 {{GENDER:$6|$2}}$7",
        "previousrevision": "←Ældre version",
        "nextrevision": "Nyere version→",
-       "currentrevisionlink": "se nuværende version",
+       "currentrevisionlink": "Nuværende version",
        "cur": "nuværende",
        "next": "næste",
        "last": "forrige",
        "mergelog": "Sammenfletningslog",
        "revertmerge": "Gendan sammenfletning",
        "mergelogpagetext": "Nedenfor vises en liste med de nyeste sammenfletninger af en sides historik i en anden.",
-       "history-title": "$1: Versionshistorik",
+       "history-title": "Versionshistorik for \"$1\"",
        "difference-title": "Forskel mellem versioner af \"$1\"",
        "difference-title-multipage": "Forskel mellem siderne \"$1\" og \"$2\"",
        "difference-multipage": "(Forskel mellem sider)",
        "listfiles-summary": "Denne specialside viser alle oplagte filer.",
        "listfiles_search_for": "Søge efter fil:",
        "listfiles-userdoesnotexist": "Brugerkontoen \"$1\" er ikke registreret.",
-       "imgfile": "Fil",
+       "imgfile": "fil",
        "listfiles": "Filliste",
        "listfiles_thumb": "Thumbnail",
        "listfiles_date": "Dato",
        "deleting-backlinks-warning": "'''Advarsel:''' [[Special:WhatLinksHere/{{FULLPAGENAME}}|Andre sider]] linker til eller inkluderer den side, du er ved at slette.",
        "rollback": "Fjern redigeringer",
        "rollbacklink": "rul tilbage",
-       "rollbacklinkcount": "tilbagefør $1 {{PLURAL:$1|redigering|redigeringer}}",
-       "rollbacklinkcount-morethan": "tilbagefør mere end $1 {{PLURAL:$1|redigering|redigeringer}}",
+       "rollbacklinkcount": "rul {{PLURAL:$1|en redigering|$1 redigeringer}} tilbage",
+       "rollbacklinkcount-morethan": "rul mere end {{PLURAL:$1|en redigering|$1 redigeringer}} tilbage",
        "rollbackfailed": "Kunne ikke fjerne redigeringen",
        "cantrollback": "Kan ikke fjerne redigering; den sidste bruger er den eneste forfatter.",
        "alreadyrolled": "Kan ikke fjerne den seneste redigering af [[:$1]] foretaget af [[User:$2|$2]] ([[User talk:$2|diskussion]]{{int:pipe-separator}}[[Special:Contributions/$2|{{int:contribslink}}]]);\nen anden har allerede redigeret siden eller fjernet redigeringen.\n\nDen seneste redigering er foretaget af [[User:$3|$3]] ([[User talk:$3|diskussion]]{{int:pipe-separator}}[[Special:Contributions/$3|{{int:contribslink}}]]).",
        "contributions-userdoesnotexist": "Brugerkontoen \"$1\" er ikke registreret.",
        "nocontribs": "Ingen ændringer er fundet som opfylder disse kriterier.",
        "uctop": "(seneste)",
-       "month": "Måned:",
-       "year": "År:",
+       "month": "Fra måned (og tidligere):",
+       "year": "Fra år (og tidligere):",
        "sp-contributions-newbies": "Vis kun bidrag fra nye brugere",
        "sp-contributions-newbies-sub": "Fra nye kontoer",
        "sp-contributions-newbies-title": "Brugerbidrag fra nye konti",
        "blocklist-nousertalk": "kan ikke redigere egen diskussionsside",
        "ipblocklist-empty": "Blokeringslisten er tom.",
        "ipblocklist-no-results": "Den angivene IP-addresse eller brugernavn er ikke blokeret.",
-       "blocklink": "bloker",
+       "blocklink": "blokér",
        "unblocklink": "ophæv blokering",
        "change-blocklink": "ændring af blokering",
        "contribslink": "bidrag",
        "javascripttest-pagetext-frameworks": "Vælg venligst en af de følgende testmiljøer: $1",
        "javascripttest-pagetext-skins": "Vælg et udseende, som testene skal køres med:",
        "javascripttest-qunit-intro": "Se [$1 testdokumentationen] på mediawiki.org.",
-       "tooltip-pt-userpage": "Din brugerside",
+       "tooltip-pt-userpage": "{{GENDER:|Din}} brugerside",
        "tooltip-pt-anonuserpage": "Brugersiden for den ip-adresse du redigerer som",
-       "tooltip-pt-mytalk": "Din diskussionsside",
+       "tooltip-pt-mytalk": "{{GENDER:|Din}} diskussionsside",
        "tooltip-pt-anontalk": "Diskussion om redigeringer fra denne ip-adresse",
-       "tooltip-pt-preferences": "Dine indstillinger",
+       "tooltip-pt-preferences": "{{GENDER:|Dine}} indstillinger",
        "tooltip-pt-watchlist": "Listen over sider du overvåger for ændringer.",
-       "tooltip-pt-mycontris": "Liste over dine bidrag",
+       "tooltip-pt-mycontris": "Liste over {{GENDER:|dine}} bidrag",
        "tooltip-pt-login": "Du opfordres til at logge på, men det er ikke obligatorisk.",
        "tooltip-pt-logout": "Log af",
        "tooltip-pt-createaccount": "Du opfordres til at oprette en konto og logge på, men det er ikke obligatorisk",
        "tooltip-n-randompage": "Gå til en tilfældig side",
        "tooltip-n-help": "Stedet hvor du finder hjælp",
        "tooltip-t-whatlinkshere": "Liste med alle sider som henviser hertil",
-       "tooltip-t-recentchangeslinked": "Seneste ændringer i sider som denne side henviser til",
+       "tooltip-t-recentchangeslinked": "Seneste ændringer af sider som denne side henviser til",
        "tooltip-feed-rss": "RSS-feed for denne side",
        "tooltip-feed-atom": "Atom-feed for denne side",
-       "tooltip-t-contributions": "Se denne brugers bidrag",
+       "tooltip-t-contributions": "En liste over bidrag fra {{GENDER:$1|denne bruger}}",
        "tooltip-t-emailuser": "Send en e-mail til denne bruger",
        "tooltip-t-info": "Yderligere oplysninger om denne side",
        "tooltip-t-upload": "Upload et billede eller anden mediafil",
        "file-info-size": "$1 × $2 punkter, filstørrelse: $3, MIME-Type: $4",
        "file-info-size-pages": "$1 × $2 punkter, filstørrelse: $3, MIME-type: $4, $5 {{PLURAL:$5|side|sider}}",
        "file-nohires": "Ingen højere opløsning fundet.",
-       "svg-long-desc": "SVG fil, basisstørrelse $1 × $2 punkters, størrelse: $3",
+       "svg-long-desc": "SVG fil, basisstørrelse $1 × $2 pixels, filstørrelse: $3",
        "svg-long-desc-animated": "Animeret SVG-fil, basisstørrelse $1 × $2 punkter, filstørrelse: $3",
        "svg-long-error": "Ugyldig SVG-fil: $1",
        "show-big-image": "Oprindelige fil",
        "special-characters-title-endash": "tankestreg",
        "special-characters-title-emdash": "lang tankestreg",
        "special-characters-title-minus": "minustegn",
+       "mw-widgets-dateinput-no-date": "Ingen dato valgt",
        "mw-widgets-dateinput-placeholder-day": "ÅÅÅÅ-MM-DD",
        "mw-widgets-dateinput-placeholder-month": "ÅÅÅÅ-MM",
+       "mw-widgets-titleinput-description-new-page": "side eksisterer ikke endnu",
+       "mw-widgets-titleinput-description-redirect": "omdiriger til $1",
        "api-error-blacklisted": "Vælg venligst en anden, beskrivende titel.",
        "randomrootpage": "Tilfældig stamside"
 }
index 36e8ab8..ef5e80c 100644 (file)
        "version-hook-subscribedby": "Aufruf von",
        "version-version": "($1)",
        "version-no-ext-name": "[kein Name]",
-       "version-svn-revision": "(Version $2)",
        "version-license": "MediaWiki-Lizenz",
        "version-ext-license": "Lizenz",
        "version-ext-colheader-name": "Bezeichnung",
index b46381d..8bd14b5 100644 (file)
        "version-hook-name": "Nameyê çengelî",
        "version-hook-subscribedby": "Eza biyayoğ",
        "version-version": "($1)",
-       "version-svn-revision": "(r$2)",
        "version-license": "Lisansê MediaWiki",
        "version-ext-license": "Lisans",
        "version-ext-colheader-name": "Dergiye",
index 8dec4b2..0ccd390 100644 (file)
        "javascripttest-pagetext-frameworks": "Παρακαλώ επιλέξτε ένα από τα ακόλουθα πλαίσια δοκιμών: $1",
        "javascripttest-pagetext-skins": "Επιλέξτε ένα skin για να εκτελέσετε δοκιμές με αυτό:",
        "javascripttest-qunit-intro": "Ανατρέξτε στην ενότητα [ $1 τεκμηρίωση δοκιμών] στο mediawiki.org.",
-       "tooltip-pt-userpage": "Η σελίδα χρήστη σας",
+       "tooltip-pt-userpage": "Η σελίδα {{GENDER:|χρήστη σας|χρήστριας σας}}",
        "tooltip-pt-anonuserpage": "Η σελίδα χρήστη στον οποίο αντιστοιχεί η διεύθυνση IP που έχετε",
-       "tooltip-pt-mytalk": "Η σελίδα συζήτησής σας",
+       "tooltip-pt-mytalk": "Η σελίδα συζήτησής {{GENDER:|σας}}",
        "tooltip-pt-anontalk": "Συζήτηση σχετικά με τις αλλαγές που έγιναν από αυτή τη διεύθυνση IP",
-       "tooltip-pt-preferences": "Οι προτιμήσεις σας",
+       "tooltip-pt-preferences": "Οι προτιμήσεις {{GENDER:|σας}}",
        "tooltip-pt-watchlist": "Η λίστα με τις σελίδες που παρακολουθείτε για αλλαγές",
-       "tooltip-pt-mycontris": "Κατάλογος των συνεισφορών σας",
+       "tooltip-pt-mycontris": "Κατάλογος των συνεισφορών {{GENDER:|σας}}",
        "tooltip-pt-anoncontribs": "Μια λίστα με τις επεξεργασίες που έγιναν από αυτή τη διεύθυνση IP",
        "tooltip-pt-login": "Σας ενθαρρύνουμε να συνδεθείτε· ωστόσο, δεν είναι υποχρεωτικό",
        "tooltip-pt-logout": "Έξοδος",
        "htmlform-user-not-valid": "Το <strong>$1</strong> δεν είναι έγκυρο όνομα χρήστη.",
        "sqlite-has-fts": "$1 με υποστήριξη αναζήτησης πλήρους κειμένου",
        "sqlite-no-fts": "$1 χωρίς την υποστήριξη αναζήτησης πλήρους κειμένου",
-       "logentry-delete-delete": "{{GENDER:$1|Ο|Η}} $1 διέγραψε τη σελίδα $3",
+       "logentry-delete-delete": "{{GENDER:$2|Ο|Η}} $1 διέγραψε τη σελίδα $3",
        "logentry-delete-restore": "Ο/Η $1 αποκατέστησε τη σελίδα $3",
        "logentry-delete-event": "{{GENDER:$2|Ο|Η}} $1 άλλαξε την ορατότητα {{PLURAL:$5|ενός καταγραφόμενου συμβάντος|$5 καταγραφόμενων συμβάντων}} στο $3: $4",
        "logentry-delete-revision": "{{GENDER:$2|Ο|Η}} $1 άλλαξε την ορατότητα {{PLURAL:$5|μίας αναθεώρησης|$5 αναθεωρήσεων}} στη σελίδα $3: $4",
index 639af0f..bf906d5 100644 (file)
        "version-hook-subscribedby": "Subscribed by",
        "version-version": "($1)",
        "version-no-ext-name": "[no name]",
-       "version-svn-revision": "r$1",
        "version-license": "MediaWiki License",
        "version-ext-license": "License",
        "version-ext-colheader-name": "Extension",
index 9abcabe..5dc6ea6 100644 (file)
        "expensive-parserfunction-warning": "Averto: Ĉi tiu paĝo enhavas tro da multekostaj sintaksaj funkcio-vokoj.\n\nĜi havu malpli ol $2 {{PLURAL:$2|vokon|vokojn}}, sed nun estas $1 {{PLURAL:$1|voko|vokoj}}.",
        "expensive-parserfunction-category": "Paĝoj kun tro da multekostaj sintaksaj funkcio-vokoj",
        "post-expand-template-inclusion-warning": "Averto: Inkluziva pezo de ŝablonoj estas tro granda.\nIuj ŝablonoj ne estos inkluzivitaj.",
-       "post-expand-template-inclusion-category": "Paĝoj kie inkluziva pezo de ŝablonoj estas tro granda.",
+       "post-expand-template-inclusion-category": "Paĝoj kie inkluziva pezo de ŝablonoj estas tro granda",
        "post-expand-template-argument-warning": "Averto: Ĉi tiu paĝo enhavas almenaŭ unu ŝablonan argumenton, kiu havas tro grandan etendan pezon.\nĈi tiuj argumentoj estis forlasitaj.",
        "post-expand-template-argument-category": "Paĝoj enhavantaj forlasitajn argumentojn de ŝablonoj",
        "parser-template-loop-warning": "Rekursiva ŝablono estis trovita: [[$1]]",
        "javascripttest-pagetext-frameworks": "Bonvolu elekti unu el la jenaj test-framoj: $1",
        "javascripttest-pagetext-skins": "Elektu kun kio etoso irigi la testojn:",
        "javascripttest-qunit-intro": "Vidu [$1 testa dokumentaro] en mediawiki.org.",
-       "tooltip-pt-userpage": "Via uzantopaĝo",
+       "tooltip-pt-userpage": "Via uzantpaĝo",
        "tooltip-pt-anonuserpage": "La uzantopaĝo por la IP adreso sub kiu vi estas redaktanta",
        "tooltip-pt-mytalk": "Via diskutpaĝo",
        "tooltip-pt-anontalk": "Diskuto pri redaktoj sub tiu ĉi IP adreso",
-       "tooltip-pt-preferences": "Miaj preferoj",
+       "tooltip-pt-preferences": "{{GENDER:|Viaj}} preferoj",
        "tooltip-pt-watchlist": "Listo de paĝoj kies ŝanĝojn vi priatentas.",
        "tooltip-pt-mycontris": "Listo de viaj kontribuoj",
        "tooltip-pt-login": "Vi estas invitita ensaluti, tamen ne estas devige.",
        "tooltip-ca-move": "Alinomigi tiun ĉi paĝon",
        "tooltip-ca-watch": "Aldoni tiun ĉi paĝon al via atentaro",
        "tooltip-ca-unwatch": "Forigi tiun ĉi paĝon el via atentaro",
-       "tooltip-search": "Traserĉi {{SITENAME}}n",
+       "tooltip-search": "Serĉi tra {{SITENAME}}",
        "tooltip-search-go": "Iru al paĝo kun ĉi preciza nomo se ĝi ekzistas",
        "tooltip-search-fulltext": "Serĉi la paĝojn por ĉi tiu teksto",
        "tooltip-p-logo": "Ĉefpaĝo",
        "tooltip-t-recentchangeslinked": "Lastaj ŝanĝoj en paĝoj kiuj ligas al tiu ĉi paĝo",
        "tooltip-feed-rss": "RSS-fonto por tiu ĉi paĝo",
        "tooltip-feed-atom": "Atom-fonto por ĉi tiu paĝo",
-       "tooltip-t-contributions": "Rigardi la liston de kontribuoj de tiu ĉi uzanto",
+       "tooltip-t-contributions": "Listo de kontribuoj de {{GENDER:$1|ĉi tiu uzanto}}",
        "tooltip-t-emailuser": "Sendi retmesaĝon al tiu ĉi uzanto",
        "tooltip-t-info": "Pli da informo pri ĉi tiu paĝo",
        "tooltip-t-upload": "Alŝuti bildojn aŭ dosierojn",
index 645dca9..936d1b9 100644 (file)
        "version-hook-subscribedby": "وارد شده توسط",
        "version-version": "($1)",
        "version-no-ext-name": "[بدون نام]",
-       "version-svn-revision": "(&رلم;r$2)",
        "version-license": "اجازه‌نامهٔ مدیاویکی",
        "version-ext-license": "مجوزها",
        "version-ext-colheader-name": "گستره‌ها",
index 9795daf..ad07699 100644 (file)
        "grant-uploadeditmovefile": "Tallentaa, korvata ja siirtää tiedostoja",
        "grant-uploadfile": "Tallentaa uusia tiedostoja",
        "grant-basic": "Perustason oikeudet",
-       "grant-viewdeleted": "Näe poistetut tiedostot ja sivut",
-       "grant-viewmywatchlist": "Näe oma tarkkailulistasi",
+       "grant-viewdeleted": "Nähdä poistettuja sivuja ja tiedostoja",
+       "grant-viewmywatchlist": "Nähdä oma tarkkailulista",
        "newuserlogpage": "Uudet käyttäjät",
        "newuserlogpagetext": "Tämä on loki luoduista käyttäjätunnuksista.",
        "rightslog": "Käyttöoikeusloki",
        "listgrouprights-namespaceprotection-header": "Nimiavaruuksien rajoitukset",
        "listgrouprights-namespaceprotection-namespace": "Nimiavaruus",
        "listgrouprights-namespaceprotection-restrictedto": "Käyttäjän muokkausoikeudet",
+       "listgrants": "Toimintaoikeudet",
+       "listgrants-grant": "Toimintaoikeus",
+       "listgrants-rights": "Oikeudet",
        "trackingcategories": "Tarkkailuluokat",
        "trackingcategories-summary": "Tällä sivulla on luettelo sellaisista ongelmia havaitsevista luokista (tarkkailuluokat), joiden sisällön koostaa automaattisesti MediaWiki-ohjelmisto. Luokkien nimiä voi vaihtaa muuttamalla asianomaista järjestelmäviestiä nimiavaruudessa {{ns:8}}.",
        "trackingcategories-msg": "Tarkkailuluokka",
index 8059ce4..551586e 100644 (file)
@@ -9,13 +9,15 @@
                        "Tocaibon",
                        "Urhixidur",
                        "לערי ריינהארט",
-                       "아라"
+                       "아라",
+                       "Marsitown"
                ]
        },
        "tog-underline": "Sotlinee leams",
        "tog-hideminor": "Plate lis piçulis modifichis tai ultins cambiaments",
        "tog-hidepatrolled": "Plate lis modifichis controladis intai ultins cambiaments",
        "tog-newpageshidepatrolled": "Plate lis pagjinis verificadis de liste des pagjinis gnovis",
+       "tog-hidecategorization": "Plate la categorizazion des pagjinis",
        "tog-extendwatchlist": "Slargje la liste des controladis specialis, no dome aes ultimis",
        "tog-usenewrc": "Ragrupe lis modifichis par pagjine intes ultimis modifichis e inati oservâts speciai",
        "tog-numberheadings": "Numerazion automatiche dai titui",
@@ -26,6 +28,7 @@
        "tog-watchdefault": "Zonte in automatic lis pagjinis che o cambii inte liste di chês tignudis di voli",
        "tog-watchmoves": "Zonte in automatic lis pagjinis che o cambii inte liste di chês tignudis di voli",
        "tog-watchdeletion": "Zonte in automatic lis pagjinis che o cambii inte liste di chês tignudis di voli",
+       "tog-watchrollback": "Zonte ai osservâts speciâi lis pagjinis dulà che tu âs fat il rollback",
        "tog-minordefault": "Imposte come opzion predeterminade ducj i cambiaments come piçui",
        "tog-previewontop": "Mostre anteprime parsore dal spazi pe modifiche",
        "tog-previewonfirst": "Mostre anteprime te prime modifiche",
        "tog-shownumberswatching": "Mostre il numar di utents che a stan tignint di voli",
        "tog-oldsig": "Firme esistente",
        "tog-fancysig": "Interprete lis firmis come test wiki (cence un leam automatic)",
-       "tog-uselivepreview": "Dopre la anteprime direte (sperimentâl)",
+       "tog-uselivepreview": "Dopre la anteprime direte",
        "tog-forceeditsummary": "Domande conferme se il cjamp ogjet al è vueit",
        "tog-watchlisthideown": "Plate i miei cambiaments inte liste des pagjinis tignudis di voli",
        "tog-watchlisthidebots": "Plate i bot de liste dai oservâts speciai",
        "tog-watchlisthideminor": "Plate i piçui cambiaments de liste dai oservâts speciai",
        "tog-watchlisthideliu": "Plate lis modifichis dai utents regjstrâts de liste dai oservâts speciai",
+       "tog-watchlistreloadautomatically": "Ricjarie la liste dai osservâts speciâi dutis lis voltis che tu modifichis un filtri (al covente Javascript)",
        "tog-watchlisthideanons": "Palte lis modifichis dai utents anonims dai oservâts speciai",
        "tog-watchlisthidepatrolled": "Plate lis modifichis verificadis de liste dai oservâts speciai",
+       "tog-watchlisthidecategorization": "Plate la categorizazion des pagjinis",
        "tog-ccmeonemails": "Mandimi une copie dai messaçs che o mandi ai altris utents",
        "tog-diffonly": "No mostrâ la pagjine dopo il control des versions",
        "tog-showhiddencats": "Mostre categoriis platadis",
        "october-date": "$1 di Otubar",
        "november-date": "$1 di Novembar",
        "december-date": "$1 di Dicembar",
+       "period-am": "AM",
+       "period-pm": "PM",
        "pagecategories": "{{PLURAL:$1|Categorie|Categoriis}}",
        "category_header": "Vôs inte categorie \"$1\"",
        "subcategories": "Sot categoriis",
        "morenotlisted": "La liste no je complete",
        "mypage": "Pagjine",
        "mytalk": "Discussions",
-       "anontalk": "Discussion par chest IP",
+       "anontalk": "Discussions",
        "navigation": "somari",
        "and": "&#32;e",
        "qbfind": "Cjate",
        "view": "Viodi",
        "view-foreign": "Vjôt su $1",
        "edit": "Cambie",
+       "edit-local": "Zonte une descrizion locâl",
        "create": "Cree",
+       "create-local": "Zonte une descrizion locâl",
        "editthispage": "Cambie cheste pagjine",
        "create-this-page": "Cree cheste pagjine",
        "delete": "Elimine",
        "otherlanguages": "Altris lenghis",
        "redirectedfrom": "(Inviât ca di $1)",
        "redirectpagesub": "Pagjine di redirezion",
+       "redirectto": "Reindriçât a:",
        "lastmodifiedat": "Cambiât par l'ultime volte ai $2, $1",
        "viewcount": "Cheste pagjine e je stade lete {{PLURAL:$1|une volte|$1 voltis}}.",
        "protectedpage": "Pagjine protezude",
        "jumptonavigation": "navigazion",
        "jumptosearch": "ricercje",
        "view-pool-error": "Scusinus ma i server a son sovrecjariats in chest moment. Masse utents a stan cjalant cheste pagjnie. Torne a provâ fra cualchi minût.\n\n$1",
+       "generic-pool-error": "Scusinus ma i server a son sovrecjariats in chest moment. Masse utents a stan cjalant cheste pagjnie. Torne a provâ fra cualchi minût.",
        "pool-timeout": "Timeout durant la spiete dal sbolc.",
        "pool-queuefull": "La code dal pool e je plene",
        "pool-errorunknown": "Erôr no cognossût",
+       "pool-servererror": "Il servizi contatôr dai pool nol è disponibil $1",
+       "poolcounter-usage-error": "Erôr di ûs: $1",
        "aboutsite": "Informazions su {{SITENAME}}",
        "aboutpage": "Project:Informazions",
        "copyright": "Il contignût al è disponibil sot de licence $1 se nol è specificât in altre maniere",
        "disclaimers": "Avîs legâi",
        "disclaimerpage": "Project:Avîs gjenerâi",
        "edithelp": "Jutori pai cambiaments",
+       "helppage-top-gethelp": "Jutori",
        "mainpage": "Pagjine principâl",
        "mainpage-description": "Pagjine principâl",
        "policy-url": "Project:Politiche",
        "hidetoc": "plate",
        "collapsible-collapse": "Strenç",
        "collapsible-expand": "Slargje",
+       "confirmable-confirm": "Sestu {{GENDER:$1|sugûr|sigure}}?",
+       "confirmable-yes": "Sì",
+       "confirmable-no": "No",
        "thisisdeleted": "Vuelistu cjalâ o ripristinâ $1?",
        "viewdeleted": "Vuelistu viodi $1?",
        "restorelink": "{{PLURAL:$1|une modifiche eliminade|$1 modifichis eliminadis}}",
        "databaseerror-query": "Interogazion: $1",
        "databaseerror-function": "Funzion $1",
        "databaseerror-error": "Erôr: $1",
+       "transaction-duration-limit-exceeded": "Par evitâ masse ritart te rispueste, cheste operazion è je stade fermade par vie che la durade dal timp di scriture ($1) al à passât il limit di $2 {{PLURAL:$2|secont|seconts}}.\nSe si stan modificant tancj elements in un colp al sarès di provâ a fâ la stesse operazion cun mancul elements a la volte.",
        "laggedslavemode": "Atenzion: La pagjine podarès no segnalâ inzornaments recents.",
        "readonly": "Base di dâts blocade",
        "enterlockreason": "Scrivi il motîf dal bloc e indicâ cuant che al varès di jessi gjavât.",
-       "readonlytext": "La base di dâts pal moment e je blocade e no si puedin zontâ vôs e fâ modifichis, probabilmentri pe normâl manutenzion de base di dâts, daspò de cuâl dut al tornarà normâl.\n\nL'aministradôr ch'al à metût il bloc al à scrit cheste motivazion: $1",
+       "readonlytext": "La base di dâts pal moment e je blocade e no si puedin zontâ vôs e fâ modifichis, probabilmentri pe normâl manutenzion de base di dâts, une volte finide dut al tornarà normâl.\n\nL'aministradôr che al à metût il bloc al à scrit cheste motivazion: $1",
        "missing-article": "La base di dâts no à cjatât il test di une pagjine che e varès di vê vût cjatât, di non \"$1\" $2.\n\nChest in gjenar al è causât dal jessi lâts daûr dal leam a une pagjine che e je stade eliminade, partint dal confront di dôs versions o di un leam tal storic.\n\nSe la cause no samee jessi cheste, tu podaressis vê cjatât un problem tal software.\nSegnalilu par plasê a un [[Special:ListUsers/sysop|administrator]], notant la URL.",
        "missingarticle-rev": "(numar de revision: $1)",
        "missingarticle-diff": "(Dif.: $1, $2)",
        "readonly_lag": "Par cumò il database al è stât blocât pe sincronizazion cul server",
+       "nonwrite-api-promise-error": "E je stade mandade la intestazion HTTP 'Promise-Non-Write-API-Action', ma la domande e jere di un modul API in scriture.",
        "internalerror": "Erôr interni",
        "internalerror_info": "Erôr interni: $1",
+       "internalerror-fatal-exception": "Erôr ireversibil di tipo \"$1\"",
        "filecopyerror": "No si pues copiâ il file \"$1\" in \"$2\"",
        "filerenameerror": "No si pues rinominâ \"$1\" in \"$2\"",
        "filedeleteerror": "No si pues eliminâ il file \"$1\".",
        "directorycreateerror": "No si pues creâ la cartele \"$1\"",
+       "directoryreadonlyerror": "La directory \"$1\" e je dome di leture.",
+       "directorynotreadableerror": "La directory \"$1\" non si rive a lei.",
        "filenotfound": "No si pues cjatâ il file \"$1\".",
        "unexpected": "Valor no proviodût: \"$1\" = \"$2\"",
        "formerror": "Erôr: no si rive a mandâ il form",
        "no-null-revision": "No si pues creâ une version vuedie de pagjine \"$1\"",
        "badtitle": "Titul sbaliât",
        "badtitletext": "Il titul de pagjine che tu âs inserît nol è valit, al è vuelit, o al veve un erôr tal colegament tra wiki diviersis o tra versions in altris lenghis.\nAl podarès vê dentri caratars che no podin jessi doprâts tai titui.",
+       "title-invalid-empty": "Il titul de pagjine domandade al è vueit o al à dome il non dal namespace",
+       "title-invalid-utf8": "Il titul de pagjine domandade al à une secuence UTF-8 no valide.",
+       "title-invalid-interwiki": "Il titul de pagjine domandade al à un leam interwiki che no si pues doprâ tai titui.",
+       "title-invalid-talk-namespace": "Il titul de pagjine domandade al clame une pagjine di discussion che no esist",
+       "title-invalid-characters": "Il titul de pagjine domandade al à caratars no valits: \"$1\".",
+       "title-invalid-relative": "Il titul al à un percors (./, ../). al è di cambiâ parcè che nol è dite che il browser dal utent al rivedi a cjatâlu.",
+       "title-invalid-magic-tilde": "Il titul de pagjine domandade nol + valit par vie che al à une sucession speciâl di tildis (<nowiki>~~~</nowiki>).",
+       "title-invalid-too-long": "Il titul de pagjine domandade al è masse lunc. Nol à di jessi plui lunc di {{PLURAL:$1|byte}} in codifiche UTF-8.",
+       "title-invalid-leading-colon": "Il titul de pagjine domandade nol è valit par vie che al à i doi pont al inizi dal titul",
        "perfcached": "I dats seguints a vegnin di une copie de \"cache\" dal database e a podaressin no jessi inzornâts. La cache e rive a tignî al massim  {{PLURAL:$1|un risultâ disponibil|$1 risultats disponibii}}",
        "perfcachedts": "I dats seguints a vegnin di une copie de \"cache\" dal database dal $1 e a podaressin no jessi inzornâts. La cache e rive a tignî al massim  {{PLURAL:$1|un risultâ disponibil|$1 risultats disponibii}}",
        "querypage-no-updates": "Inzornaments de pagjine a son al moment sospindûts. I dats metûts no saràn salvâts.",
        "viewsource": "Cjale risultive",
        "viewsource-title": "Cjale il codiç di $1",
        "actionthrottled": "Azion ritardade",
-       "actionthrottledtext": "Come misure anti-spam tu âs des limitazion tal fâ cheste azion masse voltis in toc di timp curt. Il limit al è stât superât. Tu puedis tornâ a provâ fra cualchi minût.",
+       "actionthrottledtext": "Come misure anti-spam tu âs des limitazion tal fâ cheste azion masse voltis in pôc timp. Il limit al è stât superât. Tu puedis tornâ a provâ fra cualchi minût.",
        "protectedpagetext": "Pagjine protete par evitâ modifichis o altris azions.",
        "viewsourcetext": "Tu puedis viodi e copiâ la risultive di cheste pagjine:",
        "viewyourtext": "Tu puedis viodi o copiâ il codiç des \"tôs modifichis\" in cheste pagjine.",
+       "mycustomcssprotected": "Non hai i permessi per modificare questa pagina CSS",
+       "mycustomjsprotected": "Non hai i permessi per modificare questa pagina JavaScript",
+       "myprivateinfoprotected": "Non si dispone dei permessi necessari per modificare i propri dati personali.",
+       "mypreferencesprotected": "Non si dispone dei permessi necessari per modificare le proprie preferenze.",
        "ns-specialprotected": "Lis pagjinis specialis no si puedin modificâ",
        "exception-nologin": "No tu sês jentrât",
        "virus-unknownscanner": "antivirus no cognossût:",
        "logouttext": "'''Tu sës cumò lât fûr.'''\n\nConsidere che cualchi pagjine e pues mostrâti ancjemò come jentrât tal sît fin cuant che no tu netis la memorie cache dal sgarfadôr.",
        "yourname": "Non utent",
+       "userlogin-yourname": "Non utent",
+       "userlogin-yourname-ph": "Scrîf il to non",
        "yourpassword": "Peraule clâf",
+       "userlogin-yourpassword": "Password",
+       "userlogin-yourpassword-ph": "Scrîf la tô password",
+       "createacct-yourpassword-ph": "Scrîf la tô password",
        "yourpasswordagain": "Torne a scrivile",
+       "createacct-yourpasswordagain": "Conferme la password",
+       "createacct-yourpasswordagain-ph": "Torne a scrivi la tô password",
        "remembermypassword": "Visiti di me di une session a chê altre (fin a $1 {{PLURAL:$1|zornade|zornadis}})",
+       "userlogin-remembermypassword": "Tegnimi colegât",
        "yourdomainname": "Il to domini",
        "login": "Jentre",
        "nav-login-createaccount": "Regjistriti o jentre",
        "logout": "Jes",
        "userlogout": "Jes",
        "notloggedin": "No tu sês jentrât",
+       "userlogin-noaccount": "No âstu ancjemò une identitât?",
+       "userlogin-joinproject": "Regjstriti du {{SITENAME}}",
        "nologin": "No âstu ancjemò une identitât par jentrâ? '''$1'''.",
        "nologinlink": "Creile cumò",
        "createaccount": "Cree une gnove identitât",
        "gotaccount": "Âstu za une identitât? '''$1'''.",
        "gotaccountlink": "Jentre",
        "userlogin-resetlink": "Dismenteât i detais par jentrâ?",
+       "userlogin-resetpassword-link": "Password dismenteade?",
+       "userlogin-helplink2": "Judimi a jentrâ",
+       "createacct-emailoptional": "Direzion email (opzionâl)",
+       "createacct-email-ph": "Scrîl la tô direzion email",
        "createaccountmail": "par pueste eletroniche",
        "createaccountreason": "Reson:",
+       "createacct-submit": "Cree il to profîl utent",
+       "createacct-benefit-heading": "{{SITENAME}} al è fat di int come te",
+       "createacct-benefit-body1": "$1 {{PLURAL:$1|contribût|contribûts}}",
+       "createacct-benefit-body2": "{{PLURAL:$1|pagjine|pagjinis}}",
+       "createacct-benefit-body3": "{{PLURAL:$1|ultin contributôr|ultins contributôrs}}",
        "badretype": "Lis peraulis clâfs inseridis no son compagnis.",
-       "userexists": "Il non utent inserît al è za doprât. Sielç par plasê un non diferent.",
+       "userexists": "Il nome utente inserito è già utilizzato.\nScegli un nome utente diverso.",
        "loginerror": "Erôr te jentrade",
        "createaccounterror": "No si à podût creâ l'identitât: $1",
        "nocookiesnew": "L'identitât utent e je stade creade, ma no tu sês jentrât. {{SITENAME}} al dopre i cookies par visâsi dai utents, e tu tu ju âs disabilitâts. Par plasê abilitiju, dopo jentre cul to gnûf non utent e password.",
        "noname": "No tu âs inserît un non utent valit.",
        "loginsuccesstitle": "Jentrât cun sucès",
        "loginsuccess": "Cumò tu sês jentrât te {{SITENAME}} sicu \"$1\".",
-       "nosuchuser": "Nissun utent regjistrât cul non \"$1\". Controle il non inserît o [[Special:UserLogin/signup|cree tu une gnove identitât]].",
+       "nosuchuser": "Non è registrato alcun utente di nome \"$1\".\nI nomi utente sono sensibili alle maiuscole.\nVerificare il nome inserito o [[Special:UserLogin/signup|creare una nuova utenza]].",
        "nosuchusershort": "Nol esist nissun utent cul non \"$1\". Controle di no vê sbaliât di scrivi.",
        "nouserspecified": "Tu scugnis specificâ un non utent.",
        "wrongpassword": "La peraule clâf zontade no je juste. Torne par plasê a provâ.",
        "createaccount-title": "Creazion di une identitât par {{SITENAME}}",
        "loginlanguagelabel": "Lenghe: $1",
        "pt-login": "Coleghiti",
+       "pt-login-button": "Coleghiti",
        "pt-createaccount": "Regjistris",
+       "pt-userlogout": "Va fûr",
        "changepassword": "Gambie peraule clâf",
        "resetpass_header": "Cambie peraule clâf de identitât",
        "oldpassword": "Vecje peraule clâf",
        "newpassword": "Gnove peraule clâf",
        "retypenew": "Torne a scrivi chê gnove",
        "resetpass-submit-cancel": "Scancele",
+       "passwordreset": "Azere la password",
        "passwordreset-username": "Non utent:",
        "bold_sample": "Test in gruessut",
        "bold_tip": "Test in gruessut",
        "preview": "Anteprime",
        "showpreview": "Mostre anteprime",
        "showdiff": "Mostre cambiaments",
-       "anoneditwarning": "No tu sês jentrât cuntun non utent. La to direzion IP e vignarà regjistrade tal storic di cheste pagjine.",
+       "anoneditwarning": "<strong>Atenzion:</strong>No tu sês jentrât cuntun non utent. La to direzion IP e vignarà regjistrade tal storic di cheste pagjine. -se tu <strong>[$1 jentris]</strong> o <strong>[$2 tu ti regjistris]</strong>, lis tôs modifichis a saran atribuidis al to non utent, adun ad altris beneficis.",
        "missingsummary": "'''Atenzion:''' no tu âs specificât un ogjet par chest cambiament. Se tu tornis a fracâ su \"Salve la pagjine\", il cambiament al vignarà salvât cuntun ogjet vueit.",
        "missingcommenttext": "Inserìs un coment ca sot.",
        "missingcommentheader": "'''Atenzion:''' no tu âs specificât un ogjet/intestazion par chest coment. Se tu tornis a fracâ su \"Salve la pagjine\", il to cambiament al vignarà salvât cuntune intestazion vueide.",
        "note": "'''Note:'''",
        "previewnote": "'''Visiti che cheste e je dome une anteprime.'''\nI tiei cambiaments no son stâts ancjemò salvâts!",
        "editing": "Cambiament di $1",
+       "creating": "Tu creis $1",
        "editingsection": "Cambiament di $1 (sezion)",
        "editingcomment": "Cambiament di $1 (gnove sezion)",
        "editconflict": "Conflit inte modifiche: $1",
        "currentrev": "Version atuâl",
        "currentrev-asof": "Revision atuâl dai $1",
        "revisionasof": "Version dai $1",
-       "revision-info": "Version dal $1, autôr: $2",
+       "revision-info": "Version dal $1 di {{GENDER:$6|$2}}$7",
        "previousrevision": "← Version plui vecje",
        "nextrevision": "Version plui gnove →",
        "currentrevisionlink": "Version atuâl",
        "revdelete-reasonotherlist": "Altri motîf",
        "revertmerge": "Anule unions",
        "history-title": "Storic dai cambiaments di \"$1\"",
+       "difference-title": "$1: diferencis tra lis versions",
        "lineno": "Rie $1:",
        "compareselectedversions": "Confronte versions selezionadis",
        "editundo": "anule",
+       "diff-multi-sameuser": "({{PLURAL:$1|Une version  intermedie|$1 versions intermedis}} di un stess utent no {{PLURAL:$1|je mostrade|son mostradis}})",
        "searchresults": "Risultâts de ricercje",
        "searchresults-title": "Risultâts de ricercje di \"$1\"",
        "titlematches": "Corispondencis tai titui des pagjinis",
        "shown-title": "Mostre $1 {{PLURAL:$1|risultât|risultâts}} par pagjine",
        "viewprevnext": "Cjale ($1 {{int:pipe-separator}} $2) ($3).",
        "searchmenu-exists": "'''E je une pagjine di non \"[[:$1]]\" su cheste wiki'''",
-       "searchmenu-new": "'''Cree la pagjine \"[[:$1]]\" su cheste wiki!'''",
+       "searchmenu-new": "'''Cree la pagjine \"[[:$1]]\" su cheste wiki!'''</strong> {{PLURAL:$2|0=|Viôt ancje lis pagjinis cjatadis cu la tô ricercje .|Viôt ancje i risultâts de ricercje.}}",
        "searchprofile-articles": "Pagjinis di contignûts",
        "searchprofile-images": "Multimedia",
        "searchprofile-everything": "Dut",
        "searchrelated": "leâts",
        "searchall": "ducj",
        "showingresults": "Ca sot {{PLURAL:$1|al è fin a '''1''' risultât|a son fin a '''$1''' risultâts}} scomençant dal numar '''$2'''.",
+       "search-showingresults": "{{PLURAL:$4|Risultât <strong>$1</strong> di <strong>$3</strong>|Resultâts <strong>$1 - $2</strong> di <strong>$3</strong>}}",
        "search-nonefound": "Nissun risultât par cheste ricercje.",
        "powersearch-legend": "Ricercje avanzade",
        "powersearch-ns": "Cîr tai spazis dai nons:",
        "rcnotefrom": "Ca sot i cambiaments dal '''$2''' (fintremai al '''$1''').",
        "rclistfrom": "Mostre i ultins cambiaments dal $3 $2",
        "rcshowhideminor": "$1 i piçui cambiaments",
+       "rcshowhideminor-show": "Mostre",
        "rcshowhideminor-hide": "Plate",
        "rcshowhidebots": "$1 i bots",
        "rcshowhidebots-show": "Mostre",
+       "rcshowhidebots-hide": "Plate",
        "rcshowhideliu": "$1 utents regjstrâts",
        "rcshowhideliu-hide": "Plate",
        "rcshowhideanons": "$1 utents anonims",
+       "rcshowhideanons-show": "Mostre",
        "rcshowhideanons-hide": "Plate",
        "rcshowhidepatr": "$1 cambiaments verificâts",
        "rcshowhidemine": "$1 miei cambiaments",
+       "rcshowhidemine-show": "Mostre",
        "rcshowhidemine-hide": "plate",
        "rclinks": "Mostre i ultins $1 cambiaments tes ultimis $2 zornadis<br />$3",
        "diff": "difarencis",
        "pager-older-n": "{{PLURAL:$1|1 plui vieri|$1 plui vieris}}",
        "booksources": "Fonts librariis",
        "booksources-search-legend": "Ricercje di fonts libraris",
+       "booksources-search": "Cîr",
        "specialloguserlabel": "Utent:",
        "speciallogtitlelabel": "Titul:",
        "log": "Regjistris",
        "deleteotherreason": "Altri motîf o motîf in plui:",
        "deletereasonotherlist": "Altri motîf",
        "rollbacklink": "revoche",
+       "rollbacklinkcount": "torne indaûr di $1 {{PLURAL:$1|modifiche|modifichis}}",
        "protectlogpage": "Regjistri des protezions",
        "protectedarticle": "$1 protezût",
        "modifiedarticleprotection": "cambiât il nivel di protezion par \"[[$1]]\"",
        "contributions": "Contribûts {{GENDER:$1|dal utent|de utente}}",
        "contributions-title": "Contribûts di $1",
        "mycontris": "Contribûts",
+       "anoncontribs": "Contribûts",
        "contribsub2": "Par {{GENDER:$3|$1}} ($2)",
        "nocontribs": "Nissun cambiament che al rispiete chescj criteris cjatât.",
        "uctop": "atuâl",
        "importlogpage": "Regjistris des impuartazions",
        "import-logentry-upload-detail": "$1 {{PLURAL:$1|revision|revisions}}",
        "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|revision|revisions}} di $2",
-       "tooltip-pt-userpage": "La  pagjine utent",
+       "tooltip-pt-userpage": "La {{GENDER:|tô}} pagjine utent",
        "tooltip-pt-anonuserpage": "La pagjine utent di cheste direzion IP",
-       "tooltip-pt-mytalk": "La  pagjine di discussion",
+       "tooltip-pt-mytalk": "La {{GENDER:|tô}} pagjine di discussion",
        "tooltip-pt-anontalk": "Discussions dai cambiaments fats di cheste direzion IP",
-       "tooltip-pt-preferences": "Lis mês preferencis",
+       "tooltip-pt-preferences": "Lis {{GENDER:|mês}} preferencis",
        "tooltip-pt-watchlist": "La liste des pagjinis che tu stâs tignint di voli",
-       "tooltip-pt-mycontris": "Liste dai tiei contribûts",
+       "tooltip-pt-mycontris": "Liste dai {{GENDER:|tiei}} contribûts",
        "tooltip-pt-login": "La regjistrazion e je conseade, ancje se no obligatorie.",
        "tooltip-pt-logout": "Jes (logout)",
        "tooltip-pt-createaccount": "Al sarès preferibil se tu ti regjistrassis par jentrâ. Dut câs nol è obligatori.",
        "tooltip-t-recentchangeslinked": "Liste dai ultins cambiaments intes pagjinis leadis a cheste",
        "tooltip-feed-rss": "Cjanâl RSS par cheste pagjine",
        "tooltip-feed-atom": "Cjanâl Atom par cheste pagjine",
-       "tooltip-t-contributions": "Liste dai contribûts di chest utent",
+       "tooltip-t-contributions": "Liste dai contribûts di {{GENDER:$1|chest utent|cheste utente}}",
        "tooltip-t-emailuser": "Mande un messaç di pueste eletroniche a chest utent",
        "tooltip-t-upload": "Cjame sù files multimediâi",
        "tooltip-t-specialpages": "Liste di dutis lis pagjinis speciâls",
        "exif-model": "Model di machine fotografiche",
        "exif-software": "Software doprât",
        "exif-artist": "Autôr",
+       "exif-exifversion": "Version del formât Exif",
+       "exif-colorspace": "Spazi dai colôrs",
        "exif-datetimeoriginal": "Date e ore di creazion dai dâts",
+       "exif-datetimedigitized": "Date e ore di digitalizazion",
        "exif-exposuretime": "Timp di esposizion",
        "exif-flash": "Flash",
        "exif-focallength": "Lungjece focâl obietîf",
        "watchlisttools-view": "Cjale i cambiaments rilevants",
        "watchlisttools-edit": "Cjale e cambie la liste des pagjinis tignudis di voli",
        "watchlisttools-raw": "Modifiche la liste des pagjinis tignudis di voli in formât testuâl",
+       "signature": "[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1|discussion]])",
        "duplicate-defaultsort": "'''Avîs:''' La clâf predeterminade par l'ordenament \"$2\" invalide la clâf predeterminade precedente \"$1\".",
        "version": "Version",
        "version-variables": "Variabilis",
        "dberr-info": "(No si pues contatâ il servidor de base di dâts: $1)",
        "htmlform-submit": "Invie",
        "htmlform-selectorother-other": "Altris",
+       "logentry-delete-delete": "$1 {{GENDER:$2|al à cancelât|e à cancelât}} la pagjine $3",
+       "logentry-move-move": "$1 {{GENDER:$2|al à spostât}} la pagjine $3 a $4",
        "logentry-newusers-create": "L'utent $1 al è stât {{GENDER:$2|creât}}",
+       "logentry-upload-upload": "$1 {{GENDER:$2|al à tirât su}} $3",
        "searchsuggest-search": "Ricercje",
        "searchsuggest-containing": "che al à dentri...",
        "api-error-unclassified": "Al è capitât un erôr no cognossût",
index 3f52803..4e0b5c6 100644 (file)
        "lastmodifiedatby": "A última modificación desta páxina foi o $1 ás $2 por $3.",
        "othercontribs": "Baseado no traballo feito por $1.",
        "others": "outros",
-       "siteusers": "{{PLURAL:$2|$1}} de {{SITENAME}}",
+       "siteusers": "{{PLURAL:$2|{{GENDER:$1|o usuario|a usuaria}}|os usuarios}} $1 de {{SITENAME}}",
        "anonusers": "{{PLURAL:$2|o usuario anónimo|os usuarios anónimos}} $1 de {{SITENAME}}",
        "creditspage": "Páxina de créditos",
        "nocredits": "Esta páxina non ten dispoñible información de créditos.",
        "expand_templates_preview_fail_html": "<em>Dado que o código HTML puro está activado en {{SITENAME}} e produciuse unha perda dos datos da sesión, a vista previa está oculta como precaución contra ataques mediante código JavaScript.</em>\n\n<strong>Se este é un intento lexítimo de acceso á vista previa, inténteo de novo.</strong>\nSe segue sen funcionar, probe a [[Special:UserLogout|saír]] e volver a entrar coa súa conta.",
        "expand_templates_preview_fail_html_anon": "<em>Dado que o código HTML puro está activado en {{SITENAME}} e produciuse unha perda dos datos da sesión, a vista previa está oculta como precaución contra ataques mediante código JavaScript.</em>\n\n<strong>Se este é un intento lexítimo de acceso á vista previa, probe a [[Special:UserLogout|saír]] e volver a entrar coa súa conta.</strong>",
        "expand_templates_input_missing": "Necesita proporcionar polo menos algún texto de entrada.",
-       "pagelanguage": "Selector de lingua da páxina",
+       "pagelanguage": "Cambiar a lingua da páxina",
        "pagelang-name": "Páxina",
        "pagelang-language": "Lingua",
        "pagelang-use-default": "Utilizar a lingua por defecto",
        "pagelang-submit": "Enviar",
        "right-pagelang": "Cambiar a lingua da páxina",
        "action-pagelang": "cambiar a lingua da páxina",
-       "log-name-pagelang": "Rexistro de cambios de lingua",
+       "log-name-pagelang": "Rexistro de cambios de linguas",
        "log-description-pagelang": "Este é un rexistro dos cambios na lingua das páxinas.",
-       "logentry-pagelang-pagelang": "$1 {{GENDER:$2|cambiou}} a lingua da páxina \"$3\" do $4 ao $5.",
+       "logentry-pagelang-pagelang": "$1 {{GENDER:$2|cambiou}} a lingua de \"$3\" do $4 ao $5.",
        "default-skin-not-found": "Ups! O aspecto predeterminado do wiki, definido en <code dir=\"ltr\">$wgDefaultSkin</code> como <code>$1</code>, non está dispoñíbel.\n\nA súa instalación parece incluír {{PLURAL:$4|o seguinte aspecto|os seguintes aspectos}}. Lea o [https://www.mediawiki.org/wiki/Manual:Skin_configuration Manual de configuración dos aspectos] para obter información sobre como {{PLURAL:$4|activalo|activalos}} e escoller o predeterminado.\n\n$2\n\n; Se acaba de instalar MediaWiki:\n: Probablemente instalou MediaWiki a partir de Git, ou directamente a partir do código fonte mediante algún outro método. En tal caso, este problema é normal. Probe a instalar algúns aspectos do [https://www.mediawiki.org/wiki/Category:All_skins cartafol de aspectos de mediawiki.org]. Para instalar aspectos, siga calquera destes pasos:\n:* Descargue o [https://www.mediawiki.org/wiki/Download arquivo do instalador], que inclúe varios aspectos e complementos. Pode copiar e pegar o cartafol <code>skins/</code> que atopará no arquivo.\n:* Descargue arquivos de aspectos individuais de [https://www.mediawiki.org/wiki/Special:SkinDistributor mediawiki.org].\n:* [https://www.mediawiki.org/wiki/Download_from_Git#Using_Git_to_download_MediaWiki_skins Usando Git para descargar aspectos].\n: Isto non debería interferir co seu repositorio Git se é vostede un desenvolvedor de MediaWiki.\n\n; Se acaba de anovar MediaWiki:\n: MediaWiki 1.24 e versións posteriores xa non activan aspectos de maneira automática (lea o [https://www.mediawiki.org/wiki/Manual:Skin_autodiscovery Manual de descubrimento automático de aspectos]). Pode pegar {{PLURAL:$5|a seguinte liña|as seguintes liñas}} no seu ficheiro <code>LocalSettings.php</code> para activar {{PLURAL:$5|o|todos os}} {{PLURAL:$5|aspecto instalado|aspectos instalados}} actualmente:\n\n<pre dir=\"ltr\">$3</pre>\n\n; Se acaba de modificar <code>LocalSettings.php</code>:\n: Asegúrese de que os nomes dos aspectos están escritos correctamente.",
        "default-skin-not-found-no-skins": "Ups! O aspecto predeterminado do wiki, definido en <code dir=\"ltr\">$wgDefaultSkin</code> como <code>$1</code>, non está dispoñíbel.\n\nNon ten aspectos instalados.\n\n; Se acaba de instalar MediaWiki:\n: Probablemente instalou MediaWiki a partir de Git, ou directamente a partir do código fonte mediante algún outro método. En tal caso, este problema é normal. Probe a instalar algúns aspectos do [https://www.mediawiki.org/wiki/Category:All_skins cartafol de aspectos de mediawiki.org]. Para instalar aspectos, siga calquera destes pasos:\n:* Descargue o [https://www.mediawiki.org/wiki/Download arquivo do instalador], que inclúe varios aspectos e complementos. Pode copiar e pegar o cartafol <code>skins/</code> que atopará no arquivo.\n:* Descargue arquivos de aspectos individuais de [https://www.mediawiki.org/wiki/Special:SkinDistributor mediawiki.org].\n:* [https://www.mediawiki.org/wiki/Download_from_Git#Using_Git_to_download_MediaWiki_skins Use Git para descargar aspectos individuais].\n: Isto non debería interferir co seu repositorio Git se é vostede un desenvolvedor de MediaWiki. Lea o [https://www.mediawiki.org/wiki/Manual:Skin_configuration Manual de configuración de aspectos] para obter información sobre como activar aspectos e escoller o aspecto predeterminado.",
        "default-skin-not-found-row-enabled": "* <code>$1</code>/$2 (activada)",
index 5f43e1e..9c70672 100644 (file)
        "wlheader-showupdated": "તમારી છેલ્લી મુલાકાત પછી બદલાયેલાં પાના  '''ઘાટા''' અક્ષરો વડે દર્શાવ્યાં છે.",
        "wlnote": "નીચે $3, $4 વાગ્યા સુધીના છેલ્લા {{PLURAL:$2|એક કલાક|'''$2''' કલાક}}માં થયેલા {{PLURAL:$1|ફેરફાર|'''$1''' ફેરફારો }} દર્શાવ્યા છે.",
        "wlshowlast": "છેલ્લા $1 કલાકો $2 દિવસો બતાવો",
-       "watchlistall2": "બધા",
        "watchlist-options": "ધ્યાનસૂચિના વિકલ્પો",
        "watching": "નજર રાખી રહ્યાં છો...",
        "unwatching": "નજર રાખવાની બંધ કરી છે...",
        "enotif_lastvisited": "તમારી પાછલી મુલાકાત પછી થયેલા બધા ફેરફારો માટે $1 જુઓ",
        "enotif_lastdiff": "આ ફેરફાર જોવા $1 જુઓ",
        "enotif_anon_editor": "અનામિ સભ્ય $1",
-       "enotif_body": "પ્રિય $WATCHINGUSERNAME,\n\n$PAGEINTRO $NEWPAGE\n\nફેરફારોનો સારાંશ: $PAGESUMMARY $PAGEMINOREDIT\n\nસંપાદકનો સંપર્ક:\nઇમેલ: $PAGEEDITOR_EMAIL\nવિકિ: $PAGEEDITOR_WIKI\n\nજ્યાં સુધી તમે પ્રવેશ કરીને આ પાનાની મુલાકાત નહી લો ત્યાં સુધી તેમાં ભવિષ્યમાં થનાર કોઇ પણ ફેરફારની સૂચના તમને મળશે નહિ. તમે તમારી ધ્યાન સૂચિમાં તમે જોયેલા પાના સંબંધી સૂચનાને લાગતા વિકલ્પોમાં ફેરફાર કરી શકો છો.\n\n\nઆપની વિશ્વાસુ {{SITENAME}} સૂચના પ્રણાલી   \n\n--\nઇમેલ સૂચના પ્રણાલી બદલવા માટે, મુલાકાત લો\n{{canonicalurl:{{#special:Preferences}}}}\n\nતમારી ધ્યાનસૂચિની વિક્લ્પ ગોઠવણી માટે, મુલાકાત લો\n{{canonicalurl:{{#special:EditWatchlist}}}}\n\nધ્યાનસૂચિમાંથી પાનું હટાવવા માટે, મુલાકાત લો\n$UNWATCHURL\n\nમંતવ્યો અને વધુ મદદ માટે:\n$HELPPAGE",
+       "enotif_body": "પ્રિય $WATCHINGUSERNAME,\n\n$PAGEINTRO $NEWPAGE\n\nફેરફારોનો સારાંશ: $PAGESUMMARY $PAGEMINOREDIT\n\nસંપાદકનો સંપર્ક:\nઇમેલ: $PAGEEDITOR_EMAIL\nવિકિ: $PAGEEDITOR_WIKI\n\nજ્યાં સુધી તમે પ્રવેશ કરીને આ પાનાની મુલાકાત નહી લો ત્યાં સુધી તેમાં ભવિષ્યમાં થનાર કોઇ પણ ફેરફારની સૂચના તમને મળશે નહિ. તમે તમારી ધ્યાન સૂચિમાં તમે જોયેલા પાના સંબંધી સૂચનાને લાગતા વિકલ્પોમાં ફેરફાર કરી શકો છો.\n\nઆપની વિશ્વાસુ {{SITENAME}} સૂચના પ્રણાલી   \n\n--\nઇમેલ સૂચના પ્રણાલી બદલવા માટે, મુલાકાત લો\n{{canonicalurl:{{#special:Preferences}}}}\n\nતમારી ધ્યાનસૂચિની વિક્લ્પ ગોઠવણી માટે, મુલાકાત લો\n{{canonicalurl:{{#special:EditWatchlist}}}}\n\nધ્યાનસૂચિમાંથી પાનું હટાવવા માટે, મુલાકાત લો\n$UNWATCHURL\n\nમંતવ્યો અને વધુ મદદ માટે:\n$HELPPAGE",
        "created": "બનાવ્યું",
        "changed": "બદલ્યું",
        "deletepage": "પાનું હટાવો",
index 36ec2d7..ca39584 100644 (file)
        "createaccountreason": "原因:",
        "createacct-reason": "原因",
        "createacct-reason-ph": "汝做麽嘅愛創建另一隻帳號",
-       "createacct-captcha": "安全檢查",
-       "createacct-imgcaptcha-ph": "輸入汝在上背看到嘅字符",
        "createacct-submit": "建立帳號",
        "createacct-benefit-heading": "{{SITENAME}}是由撈您共樣嘅人建立。",
        "createacct-benefit-body1": "$1次編寫",
        "resetpass-temp-password": "臨時密碼:",
        "resetpass-abort-generic": "擴充插件已中止矣更改密碼操作。",
        "passwordreset": "重設密碼",
-       "passwordreset-legend": "重置密码",
        "passwordreset-disabled": "邇隻維基上已禁止矣重設密碼。",
        "passwordreset-emaildisabled": "電子郵件功能在此 wiki 上已禁用。",
        "passwordreset-username": "用戶名:",
        "passwordreset-capture-help": "係講汝選中邇隻框,電子郵件(包括臨時密碼)將顯示,並發送分用戶。",
        "passwordreset-email": "電郵地址:",
        "passwordreset-emailtitle": "在{{SITENAME}}上嘅詳細信息",
-       "passwordreset-emailsent": "密碼重置電子郵件已發送。",
+       "passwordreset-emailsentemail": "密碼重置電子郵件已發送。",
        "changeemail": "更改電子郵件地址",
+       "changeemail-header": "更改電子郵件帳戶",
        "changeemail-no-info": "汝必須登入後直接進入邇隻頁面。",
        "changeemail-oldemail": "當前電郵地址:",
        "changeemail-newemail": "新嘅電郵地址:",
        "default": "默認",
        "prefs-files": "文件",
        "youremail": "電子郵件:",
-       "username": "Yung-fu miàng-chhṳ̂n:",
+       "username": "{{GENDER:$1|用戶名稱}}:",
        "yourrealname": "真名:",
        "yourlanguage": "語言:",
        "yourvariant": "Sṳ-thí pien-von:",
-       "yournick": "Kién-chhṳ̂n:",
+       "yournick": "新个簽名:",
        "badsig": "錯誤嘅原始簽名。請檢查HTML標籤。",
        "badsiglength": "Tshiâm-miàng ko-liong.\nTshòng-tón pit-sî chhai $1-ke sṳ-ngièn yî-ha.",
        "email": "電子郵件",
        "destfilename": "目標文件名",
        "watchthisupload": "監視本文件",
        "filewasdeleted": "早先已經有一隻同名文件分上傳後又分刪除矣。在上傳邇文件之前汝愛檢查$1。",
-       "upload-success-subj": "上傳成功",
        "upload-proto-error": "協議毋著",
        "upload-proto-error-text": "遠程上傳要求URL以<code>http://</code>或 <code>ftp://</code>開頭。",
        "upload-file-error": "內部差錯",
        "nlinks": "$1隻鏈接",
        "nmembers": "$1隻成員",
        "nrevisions": "$1隻修訂版本",
-       "nviews": "$1次瀏覽",
        "specialpage-empty": "本報告無結果。",
        "lonelypages": "孤立頁面",
        "lonelypagestext": "Yî-ha vùn-chông mò-yû lièn-kiet liá-ke wiki chûng ke khì-thâ vùn-chông.",
        "mailnologin": "無電郵地址",
        "mailnologintext": "汝必須先[[Special:UserLogin|登入]]\n並在[[Special:Preferences|偏好設定]]\n肚有一隻有效嘅電郵地址正做得發郵件分其他用戶。",
        "emailuser": "電郵聯繫邇隻用戶",
-       "emailpage": "電郵聯繫用戶",
        "emailpagetext": "Kó-yèn ke-yung-fu yí-kîn chhai chhâm-su sat-chṳ chông chûng sû-ngi̍p yû-háu ke e-mail thi-tiám, yî-ha ke péu-kak chiông-ki yit-ke sêu-sit pûn ke-yung-fu. Ngì chhai chhâm-su sat-chṳ chûng só sû-ngi̍p ke e-mail thi-tiám chiông chhut-hien chhai email \"fat-khien-ngìn\" yit-làn-chûng, liá-yong ke-yung-fu chhiu khó-yî fì-fu̍k.",
        "defemailsubject": "{{SITENAME}} Email",
        "noemailtitle": "電郵地址:",
        "deleteotherreason": "其它/附加理由:",
        "deletereasonotherlist": "其它理由",
        "rollback": "編寫倒轉頭",
-       "rollback_short": "倒轉頭",
        "rollbacklink": "打轉頭",
        "rollbackfailed": "無法倒轉頭",
        "cantrollback": "編寫無法打轉頭;最後嘅貢獻者人本文嘅唯一作者。",
        "protect-cascadeon": "下背嘅$1嘅頁面包含緊本頁面嘅同時,還啟動矣連鎖保護,故所本頁面目前也分保護,還㬟做得編寫。汝做得設定本頁面嘅保護級別,毋過邇影響毋到連鎖保護。",
        "protect-default": "容許所有用戶",
        "protect-fallback": "Sî-yeu \"$1\" ke hí-khó",
-       "protect-level-autoconfirmed": "Kim-chṳ́  sîn-ke lâu hàn-mò chu-chhak ke yung-fu",
+       "protect-level-autoconfirmed": "只有已經自動確定个用戶",
        "protect-level-sysop": "Kón-lî-yèn chôn-cho",
        "protect-summary-cascade": "連鎖",
        "protect-expiring": "終止於$1(UTC)",
        "sp-contributions-uploads": "上傳",
        "sp-contributions-logs": "日誌",
        "sp-contributions-talk": "交流",
-       "sp-contributions-userrights": "Yung-fu khièn-han kón-lî",
+       "sp-contributions-userrights": "用戶權限管理",
        "sp-contributions-search": "搜尋貢獻記錄",
        "sp-contributions-username": "IP地址或用戶名:",
        "sp-contributions-toponly": "單淨展示最新修訂版本嘅編寫",
        "move-page-legend": "Yì-thung vùn-chông",
        "movepagetext": "Yung ha-mien ke péu-tân lòi chhùng-sîn min-miàng yit-ke vùn-chông, pin chiông siû-thin li̍t-sṳ́ thùng-sṳ̀ yì-thung to sîn vùn-chông.\nLó-ke vùn-chông chiông sṳ̀n-vì sîn vùn-chông ke chhûng-thin hong-mien.\nLièn-kiet to ló vùn-chông ke lièn-kiet pin-mò chhṳ-thung kiên-kói;\nchhiáng kiám-chhà sûng-chhûng fe̍t-he sún-fái chhûng-thin-hiong lièn-kiet.\nYin-tông fu-chit khok-thin só-yû lièn-kiet chiông-voi lièn-to chṳ́-thin ke vùn-chông.\n\nChu-yi kó-yèn sîn vùn-chông yí-kîn yû nui-yùng, vùn-chông chiông '''put-voi''' pûn yì-thung, chhù-fî sîn vùn-chông mò nui-yùng fe̍t-he chhûng-thin-hiong, yì-yèn mò-yû siû-thin li̍t-sṳ́.\nNgì chai pit-yeu sṳ̀ khó-yî chhai yì-thung to sîn vùn-chông heu chai yì-fì ló-ke vùn-chông, thùng-sṳ̀ ya-he vù-fap koi-hien yû hong-mien.\n\n'''Kín-ko!'''\nTui yit-ke kîn-sòng pûn fóng-mun ke vùn-chông lòi ngièn, liá khó-nèn he yit-ke chṳ̂n-thai khi̍p thòng-thu̍t ke kiên-kói;\nchhiáng chhai hàng-thung chṳ̂-chhièn siên liáu-kié khì-thâ khó-nèn tai-lòi ke heu-kó.",
        "movepagetalktext": "Yû-kôan ke tui-fa-hiong chiông-voi pûn chhṳ-thung lâu ke-vùn-chông yit-hí yì-thung, '''chhù-fî''':\n*Ngì chiông vùn-chông yì-thung to siông-thùng ke miàng-sṳ, fe̍t-chá\n*Sîn vùn-chông yí-kîn yû yit-ke pâu-hàm nui-yùng ke tui-fa-hiong, fe̍t-he\n*Ngì put kiêu-sién ha-mien ke fu̍k-sién khiông. Chhai liá-chúng chhìn-khóng hâ, pit-sî sú-kûng yì-thung fe̍t-he ha̍p-phîn vùn-chông.",
-       "movearticle": "Yì-thung vùn-chông",
        "movenologintext": "Ngì pit-sî he yit-miàng tên-ki yung-fu pin-chhiâ [[Special:UserLogin|tên-ngi̍p]] heu chhòi-nèn Yì-thung yit-ke vùn-chông.",
        "newtitle": "新標題:",
        "move-watch": "Kam-sṳ chhṳ́-chông",
        "movelogpagetext": "Yî-ha he yí-kîn yì-thung ke vùn-chông chhîn-tân.",
        "movereason": "原因:",
        "revertmove": "恢復",
-       "delete_and_move": "刪除並移動",
        "delete_and_move_text": "==愛刪除==\n\n目標頁面\"[[:$1]]\"已經存在。汝確認愛刪除原頁面並進行移動係無?",
        "delete_and_move_confirm": "著,刪除邇頁",
        "delete_and_move_reason": "Chhù-thet yî-phien yì-thung",
        "import-interwiki-text": "選擇一隻wiki撈頁面標題進行導入。\n修訂日期與編寫人嘅名會分保存。\n所有嘅跨wiki導入操作分記錄在[[Special:Log/import|導入日誌]]肚。",
        "import-interwiki-history": "Fuk-chṳ chhṳ́-chông ke só-yû li̍t-sṳ́ pán-pún",
        "import-interwiki-submit": "導入",
-       "import-interwiki-namespace": "Chiông vùn-chông chón-yì to miàng-sṳ khûng-kiên:",
        "importtext": "Chhiáng sṳ́-yung Special:Export kûng-nèn chhiùng-ngièn wiki thô-chhuttóng-on, tú-chhùn to ngì ke-phién pin song-chhòn to liá-piên.",
        "importstart": "頁面導入中……",
        "import-revision-count": "$1-ke siû-thin",
        "importnofile": "無上傳導入文件。",
        "importlogpage": "導入日誌",
        "importlogpagetext": "管理性導入在其他Wiki上有編寫歷史嘅頁面",
-       "import-logentry-upload": "Theu-ko tóng-on sông-chhòn thô-ngi̍p ke $1",
        "import-logentry-upload-detail": "$1-ke siû-thin",
-       "import-logentry-interwiki": "Khiam-wiki $1",
        "import-logentry-interwiki-detail": "Lòi-chhṳ $2-ke $1-ke siû-thin",
        "tooltip-pt-userpage": "汝嘅用戶頁面",
        "tooltip-pt-anonuserpage": "Ngì-ke phiên-siá pún-chham só yung IP ke tui-yin yung-fu-chông",
        "markedaspatrollederror": "Put-nèn phêu-ki sṳ̀n-vì yí-kîn kiám-chhà",
        "markedaspatrollederrortext": "Ngì sî-yeu chṳ́-thin mêu-ke pán-pún chhòi-nèn phêu-ki sṳ̀n-vì yí-kîn kiám-chhà.",
        "markedaspatrollederror-noautopatrol": "Ngì mò-fap chiông ngì chhṳ-kí só-chok ke kiên-kói phêu-ki sṳ̀n-vì yí-kîn kiám-chhà.",
-       "patrol-log-page": "Sùn-chhà ki-liu̍k",
+       "patrol-log-page": "巡邏檢查日誌",
        "deletedrevision": "已刪除舊版本$1",
        "previousdiff": "←上隻版本",
        "nextdiff": "下隻版本→",
index 8fc539e..53134ca 100644 (file)
        "confirmemail_text": "{{SITENAME}} पर उपलब्ध इ-मेल सुविधाओंका लाभ उठाने के लिये प्रमाणित एड्रेस होना जरूरी हैं।\nआपके एड्रेस पर एक कन्फर्मेशन कोड भेजने के लिये नीचे दिये बटन पर क्लिक करें।\nउस मेल में एक कोड से लदी एक कड़ी होगी;\nआपके इ-मेल के प्रमाणिकरण के लिये इसे अपने ब्राउज़रमें खोलें।",
        "confirmemail_pending": "आपको पहलेसे ही एक कन्फर्मेशन कोड भेजा गया हैं;\nअगर आपने हालमें खाता खोला हैं, तो नये कोड की माँग करने से पहले कुछ पल उसका इंतज़ार करें।",
        "confirmemail_send": "एक कन्फर्मेशन कोड भेजें",
-       "confirmemail_sent": "à¤\95नà¥\8dफरà¥\8dमà¥\87शन à¤\87-मà¥\87ल à¤­à¥\87à¤\9c à¤¦à¤¿या।",
+       "confirmemail_sent": "सतà¥\8dयापन à¤¹à¥\87तà¥\81 à¤\88मà¥\87ल à¤­à¥\87à¤\9cा à¤\97या।",
        "confirmemail_oncreate": "आपके इ-मेल पते पर एक कन्फर्मेशन कोड भेजा गया हैं।\nलॉग इन करने के लिये इसकी आवश्यकता नहीं हैं, पर इस विकिपर उपलब्ध इ-मेल आधारित सुविधाओंका इस्तेमाल करने के लिये यह देना जरूरी हैं।",
        "confirmemail_sendfailed": "{{SITENAME}} आपको पुष्टि डाक नहीं भेज पाई।\nकृपया अपना डाक पता जाँच लें, कहीं उसमें अवैध  अक्षर तो नहीं हैं?\n\nडाक प्रेषक ने कहा: $1",
        "confirmemail_invalid": "गलत कन्फर्मेशन कोड।\nकोड रद्द हो गया होने की संभावना हैं।",
index 59cc6fb..cdb3a9c 100644 (file)
        "rcshowhidemine": "$1 moje promjene",
        "rcshowhidemine-show": "prikaži",
        "rcshowhidemine-hide": "sakrij",
+       "rcshowhidecategorization": "$1 kategorizaciju stranica",
        "rcshowhidecategorization-show": "Prikaži",
        "rcshowhidecategorization-hide": "Sakrij",
        "rclinks": "Prikaži posljednjih $1 promjena {{PLURAL:$2|prethodni dan|u posljednja $2 dana|u posljednjih $2 dana}}<br />$3",
index 08170be..ea5687f 100644 (file)
        "prefs-rc": "Ultime modifiche",
        "prefs-watchlist": "Osservati speciali",
        "prefs-editwatchlist": "Modifica osservati speciali",
-       "prefs-editwatchlist-label": "Modifica le pagine della tua watchlist:",
-       "prefs-editwatchlist-edit": "Visualizza e rimuovi titoli sulla tua watchlist",
+       "prefs-editwatchlist-label": "Modifica i tuoi osservati speciali:",
+       "prefs-editwatchlist-edit": "Visualizza e rimuovi titoli nei tuoi osservati speciali",
        "prefs-editwatchlist-raw": "Modifica la lista in formato testo",
-       "prefs-editwatchlist-clear": "Cancella la tua watchlist",
+       "prefs-editwatchlist-clear": "Svuota i tuoi osservati speciali",
        "prefs-watchlist-days": "Numero di giorni da mostrare negli osservati speciali:",
        "prefs-watchlist-days-max": "Massimo $1 {{PLURAL:$1|giorno|giorni}}",
        "prefs-watchlist-edits": "Numero di modifiche da mostrare con le funzioni avanzate:",
index 1e29e7b..9160476 100644 (file)
        "grant-sendemail": "他の利用者へのメールの送信",
        "grant-uploadeditmovefile": "ファイルをアップロード/置き換え/移動",
        "grant-uploadfile": "新しいファイルをアップロード",
+       "grant-basic": "基礎的な権限",
        "grant-viewdeleted": "削除されたファイルとページを閲覧",
        "grant-viewmywatchlist": "自身のウォッチリストを閲覧",
        "newuserlogpage": "アカウント作成記録",
index 905ea2f..edb601a 100644 (file)
        "actions": "Akshan",
        "namespaces": "Niemspies",
        "variants": "Vieriant",
+       "navigation-heading": "Navigieshan menyuu",
        "errorpagetitle": "Era",
        "returnto": "Ritoern a $1",
        "tagline": "Frahn {{SITENAME}}",
        "disclaimers": "Diskliema",
        "disclaimerpage": "Project: Jinaral diskliema",
        "edithelp": "Editin elp",
-       "mainpage": "Mien piej",
+       "mainpage": "Mien Piej",
        "mainpage-description": "Mien piej",
        "policy-url": "Project:Palisi",
        "portal": "Komiuniti puotal",
        "nstab-template": "Templit",
        "nstab-help": "Elp piej",
        "nstab-category": "Kiatigari",
+       "mainpage-nstab": "Mien piej",
        "nosuchaction": "No soch akshan",
        "nosuchactiontext": "Di akshan spesifai bai di URL invalid.\nYu maita mistaip di URL, ar fala a inkarek lingk.\nDis maita indikiet alzwel wahn bog ina di saafwier yuuz bai {{SITENAME}}.",
        "nosuchspecialpage": "No soch peshal piej",
        "login-throttled": "Yu mek tomoch riisant lagiin atemp.\nBegyu wiet likl bifuo yu chrai agen.",
        "loginlanguagelabel": "Langwij: $1",
        "suspicious-userlogout": "Yu rikwes fi lag out dinai bikaa iluk laik se isen bai a brok brouza ar kiashin praxi.",
+       "pt-login": "Lagiin‎",
+       "pt-createaccount": "Kriet akount‎",
        "resetpass_announce": "Yu lag iin wid a tempareri e-miel kuod.\nFi finish lag iin, yu mos set a nyuu paaswod yaso:",
        "resetpass_header": "Chienj akount paaswod",
        "oldpassword": "Uol paaswod:",
        "rc-enhanced-expand": "Shuo ditiel (rikwaya JavaScript)",
        "rc-enhanced-hide": "Aid ditiel",
        "recentchangeslinked": "Rilietid chienj",
+       "recentchangeslinked-toolbox": "Rilietid chienj‎",
        "recentchangeslinked-title": "Chienj riliet tu \"$1\"",
        "recentchangeslinked-summary": "Dis a lis a riisent chienj wa mek tu piej wa lingk frahn spesifai piej (ar tu memba a spesifai kiatigeri).\nPiej pahn [[Special:Watchlist|yu wachlis]] dem '''buol'''.",
        "recentchangeslinked-page": "Piej niem",
        "linkstoimage": "Di falarin {{PLURAL:$1|piej lingk|$1 piejdem lingk}}",
        "sharedupload": "Dis fail kom frahn $1 ahn kiahn yuuz bai ada prajek.",
        "uploadnewversion-linktext": "Opluod nyuu voerjan a dis fail",
+       "randompage": "Random piej",
        "statistics": "Tatistik",
        "nbytes": "$1 {{PLURAL:$1|bait|bait}}",
        "nmembers": "$1 {{PLURAL:$1|memba|membadem}}",
        "tooltip-pt-mycontris": "Lis a yu kanchribyuushan",
        "tooltip-pt-login": "Yu inkorij fi lag iin; ousomeba, ino mos ahn boun",
        "tooltip-pt-logout": "Lag out",
+       "tooltip-pt-createaccount": "Yu inkorij fi kriet wah akount ah lagiin; ousomeba, a no mos",
        "tooltip-ca-talk": "Diskoshan bout di kantent piej",
-       "tooltip-ca-edit": "Yu kiahn edit dis piej. Du yuuz di priivyuu botn bifuo yu sieb",
+       "tooltip-ca-edit": "Edit dis piej",
        "tooltip-ca-addsection": "Taat a nyuu sekshan",
        "tooltip-ca-viewsource": "Dis piej protek.\nYu kiahn vyuu isuos.",
        "tooltip-ca-history": "Paas rivijan a dis piej",
        "tooltip-search": "Saach {{SITENAME}}",
        "tooltip-search-go": "Go tu a piej wid disaya egzak niem ef iegzis",
        "tooltip-search-fulltext": "Saach di piejdem fi disaya tex",
+       "tooltip-p-logo": "Visit di mien piej",
        "tooltip-n-mainpage": "Vizit di mien piej",
        "tooltip-n-mainpage-description": "Vizit di mien piej",
        "tooltip-n-portal": "Bout di prajek, wa yu kiahn du, we fi fain tingz",
        "tooltip-watch": "Ad dis piej tu yu wachlis",
        "tooltip-rollback": "\"Ruolbak\" rivoert edit(dem) tu dis piej a di laas kanchribiuta ina wan klik",
        "tooltip-undo": "\"Andu\" rivoert dis edit ahn opin di edit faam ina priivyuu muod. Ilou yu fi ad riizn ina di somari.",
+       "pageinfo-toolboxlink": "Piej infamieshan",
        "previousdiff": "← Uola edit",
        "nextdiff": "Nyuwa edit",
        "file-info-size": "$1 × $2 pixl, fail saiz: $3, MIME taip: $4",
        "watchlisttools-view": "Vyuu rilivant chienjdem",
        "watchlisttools-edit": "Vyuu ahn edit wachlis",
        "watchlisttools-raw": "Edit raa wachlis",
-       "specialpages": "Peshal piej"
+       "specialpages": "Peshal piej",
+       "searchsuggest-search": "Saach‎"
 }
index 52c771e..edc1178 100644 (file)
        "protectedinterface": "ეს გვერდი წარმოადგენს ტექსტურ ინტერფეისს პროგრამული უზრუნველყოფისათვის და დაცულია ვანდალიზმის აღკვეთის მიზნით.",
        "editinginterface": "'''ყურადღება:''' თქვენ არედაქტირებთ გვერდს, რომელიც პროგრამის ინტერფეისის ტექსტს შეიცავს. \nამ გვერდზე განხორციელებული რედაქტირება გამოიწვევს ამ ვიკის სხვა მომხმარებელთა სამუშაო ინტერფეისის შეცვლასაც. \nიმისათვის, რომ დაამატოთ ან შეცვალოთ თარგმანები ყველა ვიკიში, გთხოვთ, გამოიყენოთ მედიავიკის ლოკალიზაციის პროექტი [//translatewiki.net/ translatewiki.net].",
        "translateinterface": "თარგმანების ყველა ვიკიში დასამატებლად ან შესაცვლელად, გთხოვთ გამოიყენოთ მედიავიკებისლოკალიზაციის პროექტი [//translatewiki.net/ translatewiki.net].",
-       "cascadeprotected": "ეს გვერდი რედაქტირებისგან დაცულია, რადგან იგი ჩართულია შემდეგ {{PLURAL:$1|გვერდში, რომლის |გვერდებში, რომელთა}} დასაცავადაც ჩართულია პარამეტრი \"იერარქიული\":\n$2",
+       "cascadeprotected": "ეს გვერდი რედაქტირებისგან დაცულია, რადგან იგი ჩართულია შემდეგ {{PLURAL:$1|გვერდში, რომლის|გვერდებში, რომელთა}} დასაცავადაც ჩართულია პარამეტრი \"იერარქიული\":\n$2",
        "namespaceprotected": "თქვენ არ გაქვთ '''$1''' სახელთა სივრცეში გვერდების რედაქტირების უფლება.",
        "customcssprotected": "თქვენ არ გაქვთ ამ CSS გვერდის რედაქტირების უფლება, ვინაიდან ის სხვა მომხმარებლის პირად კონფიგურაციას შეიცავს.",
        "customjsprotected": "თქვენ არ გაქვთ ამ JavaScript გვერდის რედაქტირების უფლება, ვინაიდან ის სხვა მომხმარებლის პირად კონფიგურაციას შეიცავს.",
        "mypreferencesprotected": "თქვენ არ გაქვთ თქვენი კონფიგურაციის შეცვლის ნებართვა.",
        "ns-specialprotected": "გვერდების რედაქტირება სახელთა სივრცეში {{ns:special}} შეუძლებელია.",
        "titleprotected": "შემდეგი გვერდის შექმნა აკრძალულია მომხმარებელ [[User:$1|$1]]-ს მიერ.\nმოცემულია შემდეგი ახსნა: „''$2''“.",
-       "filereadonlyerror": "ფაილი \"$1\" შეცვლა ვერ ხერხდება, რადგანაც ფაილის საცავი \"$2\" მხოლოდ კითხვის რეჟიმშია.\n\nადმინისტრატორი რომელმაც ის დაბლოკა მიუთითა შემდეგი მიზეზი: \"$3\".",
+       "filereadonlyerror": "ფაილის \"$1\" შეცვლა ვერ ხერხდება, რადგანაც ფაილის საცავი \"$2\" მხოლოდ კითხვის რეჟიმშია.\n\nსისტემურმა ადმინისტრატორმა, რომელმაც ის დაბლოკა, მოიყვანა შემდეგი მიზეზი: \"$3\".",
        "invalidtitle-knownnamespace": "დაუშვებელი სათაური სახელთა სივრცე \"$2\" და ტექსტი \"$3\"-თან",
        "invalidtitle-unknownnamespace": "დაუშვებელი სათაური უცნობი სახელთა სივრცის ნომერი $1 და ტექსტი \"$2\"-ით",
        "exception-nologin": "შესვლა არ განხორციელდა",
        "subject": "თემა:",
        "minoredit": "მცირე რედაქტირება",
        "watchthis": "უთვალთვალე ამ გვერდს",
-       "savearticle": "შენახვა",
+       "savearticle": "á\83\92á\83\95á\83\94á\83 á\83\93á\83\98á\83¡ á\83¨á\83\94á\83\9cá\83\90á\83®á\83\95á\83\90",
        "preview": "წინასწარი გადახედვა",
-       "showpreview": "წინასწარი გადახედვა",
+       "showpreview": "á\83¬á\83\98á\83\9cá\83\90á\83¡á\83¬á\83\90á\83 á\83\98 á\83\92á\83\90á\83\93á\83\90á\83®á\83\94á\83\93á\83\95á\83\98á\83¡ á\83©á\83\95á\83\94á\83\9cá\83\94á\83\91á\83\90",
        "showdiff": "ცვლილებების ჩვენება",
        "blankarticle": "გაფრთხილება: გვერდი, რომელსაც ქმნით, ცარიელია. თუკი კვლავ დააჭერთ ღილაკს \"{{int:savearticle}}\", გვერდი შეიქმნება შემცვლელობის გარეშე.",
        "anoneditwarning": "<strong>გაფრთხილება:</strong> თქვენ არ ხართ ავტორიზირებული. თქვენი IP მისამართი საჯაროდ ხილული იქნება, თუკი განახორციელებთ რედაქტირებას. თუ თქვენ გაივლით <strong>[$1 ავტორიზაციას]</strong> ან <strong>[$2 შექმნით ანგარიშს]</strong>, სხვა უპირატესობებთან ერთად, თქვენი რედაქტირებები დაუკავშირდება თქვენს მომხმარებლის სახელს.",
        "subject-preview": "თემის გადახედვა:",
        "previewerrortext": "თქვენი ცვლილებების წინასწარი გადახედვის მცდელობის დროს მოხდა შეცდომა",
        "blockedtitle": "მომხმარებელი ბლოკირებულია",
-       "blockedtext": "'''თქვენი მომხმარებლის სახელი ან IP მისამართი დაბლოკილ იქნა.'''\n\nბლოკირება განახორციელა $1-მ.\nმიზეზად დასახელდა შემდეგი: ''$2''.\n\n* დაბლოკვის დასაწყისი: $8\n* ბლოკის ვადის გასვლის დრო: $6\n* დაბლოკილ იქნა: $7\n\nშეგიძლიათ დაუკავშირდეთ $1-ს ან რომელიმე სხვა [[{{MediaWiki:Grouppage-sysop}}|ადმინისტრატორს]] დაბლოკვის განსახილველად.\nგაითვალისწინეთ, რომ თქვენ ვერ შეძლებთ გამოიყენოთ ფუნქცია „მომხმარებლისთვის ელ. ფოსტის გაგზავნა“, თუ არ გაქვთ მითითებული მოქმედი ელ. ფოსტის მისამართი თქვენი [[Special:Preferences|ანგარიშის კონფიგურაციაში]] ან თუ დაბლოკვის შედეგად გაქვთ ამ ფუნქციის გამოყენების ნებართვა ჩამორთმეული.\nთქვენი ამჟამინდელი IP მისამართია $3, ხოლო ბლოკის იდენტიფიკატორი #$5.\nგთხოვთ, მიუთითოთ ყველა ზემოთხსენებული მონაცემი თქვენს კორესპონდენციაში.",
+       "blockedtext": "<strong>თქვენი მომხმარებლის სახელი ან IP მისამართი დაიბლოკა.</strong>\n\nბლოკირება განახორციელა $1-მ.\nმიზეზად დასახელდა შემდეგი: <em>$2</em>.\n\n* დაბლოკვის დასაწყისი: $8\n* ბლოკის ვადის გასვლის დრო: $6\n* დაბლოკილ იქნა: $7\n\nშეგიძლიათ დაუკავშირდეთ $1-ს ან რომელიმე სხვა [[{{MediaWiki:Grouppage-sysop}}|ადმინისტრატორს]] დაბლოკვის განსახილველად.\nგაითვალისწინეთ, რომ თქვენ ვერ შეძლებთ გამოიყენოთ ფუნქცია „მომხმარებლისთვის ელ. ფოსტის გაგზავნა“, თუ არ გაქვთ მითითებული მოქმედი ელ. ფოსტის მისამართი თქვენი [[Special:Preferences|ანგარიშის კონფიგურაციაში]] ან თუ დაბლოკვის შედეგად გაქვთ ამ ფუნქციის გამოყენების ნებართვა ჩამორთმეული.\nთქვენი ამჟამინდელი IP მისამართია $3, ხოლო ბლოკის იდენტიფიკატორი #$5.\nგთხოვთ, მიუთითოთ ყველა ზემოთხსენებული მონაცემი თქვენს კორესპონდენციაში.",
        "autoblockedtext": "თქვენი IP მისამართი ავტომატურად დაიბლოკა, ვინაიდან მას სხვა მომხმარებელი იყენებდა, რომელიც დაბლოკა $1-მა.\nსაბაბად მოყვანილი იყო შემდეგი:\n\n:''$2''\n\n* ბლოკის დაწყების თარიღი: $8\n* ბლოკის ვადის გასვლა: $6\n*დაიბლოკა $7\n\nშეგიძლიათ დაუკავშირდეთ $10ს ან რომელიმე სხვა\n[[{{MediaWiki:Grouppage-sysop}}|ადმინისტრატორს]] ამ ბლოკის განსახილველად.\n\nგაითვალისწინეთ, რომ თქვენ ვერ გამოიყენებთ „მისწერეთ ელ-წერილი ამ მომხმარებელს“ ფუნქციას თუ თქვენ შემოწმებული ელ-ფოსტის მისამართი\nარ გაქვთ მითითებული თქვენს [[Special:Preferences|კონფიგურაციაში]] და არ ხართ დაბლოკილი მისი გამოყენებისთვის.\n\nთქვენი IP — $3. თქვენი დაბლოკვის საიდენტიფიკაციო ნომერია $5. გთხოვთ მიუთითოთ ეს ნომერი, ნებისმიერ მიმოწერაში.",
        "blockednoreason": "მიზეზი არ არის მითითებული",
        "whitelistedittext": "გვერდების რედაქტირებისათვის თქვენ გესაჭიროებათ $1.",
        "log-fulllog": "ყველა ჟურნალის ხილვა",
        "edit-hook-aborted": "შესწორება გაუქმებულია გადამჭერით.\nდამატებითი ახსნა არ ჩაწერილა.",
        "edit-gone-missing": "გვერდის განახლეა შეუძლებელია.\nშესაძლოა, იგი წაიშალა.",
-       "edit-conflict": "á\83 á\83\94á\83\93á\83\90á\83¥á\83ªá\83\98ების კონფლიქტი.",
+       "edit-conflict": "á\83 á\83\94á\83\93á\83\90á\83¥á\83¢á\83\98á\83 ების კონფლიქტი.",
        "edit-no-change": "თქვენი შესწორება არ იქნა შენახული, რადგანაც ტექსტის ცვლილება არ მოხდა.",
        "postedit-confirmation-created": "გვერდი შეიქმნა.",
        "postedit-confirmation-restored": "გვერდი აღდგა.",
        "history-show-deleted": "მხოლოდ წაშლილი",
        "histfirst": "უძველესი",
        "histlast": "უახლესი",
-       "historysize": "($1 ბაიტი)",
+       "historysize": "({{PLURAL:$1|$1 ბაიტი|$1 ბაიტი}})",
        "historyempty": "(ცარიელი)",
        "history-feed-title": "რედაქტირების ისტორია",
        "history-feed-description": "ამ გვერდის შესწორებათა ისტორია ვიკიში",
-       "history-feed-item-nocomment": "$1  $2-ზე",
+       "history-feed-item-nocomment": "$1 $2-ზე",
        "history-feed-empty": "თქვენს მიერ მოძიებული გვერდი არ არსებობს.\nშესაძლოა იგი წაშლილ იქნა ვიკიდან, ან მისი სათაური შეიცვალა.\nსცადეთ [[Special:Search|searching on the wiki]] მსგავსი გვერდების სანახავად.",
        "history-edit-tags": "არჩეული ვერსიების ტეგების შეცვლა",
        "rev-deleted-comment": "(რეზიუმე წაიშალა)",
        "foreign-structured-upload-form-label-own-work": "ეს ჩემი პირადი ნამუშევარია",
        "foreign-structured-upload-form-label-infoform-categories": "კატეგორიები",
        "foreign-structured-upload-form-label-infoform-date": "თარიღი",
+       "foreign-structured-upload-form-label-not-own-work-local-local": "შეგიძლიათ სცადოთ [[Special:Upload|მთავარი ატვირთვის გვერდი]].",
        "foreign-structured-upload-form-label-own-work-message-shared": "მე ვადასტურებ, რომ ამ ფაილზე საავტორო უფლებების მფლობელი ვარ და ვთანხმდები ამ ფაილის შეუქცევადად განთავსებაზე ვიკისაწყობში [https://creativecommons.org/licenses/by-sa/4.0/deed.ka Creative Commons Attribution-ShareAlike 4.0] ლიცენზიით, აგრეთვე ვეთანხმები [https://wikimediafoundation.org/wiki/Terms_of_Use გამოყენების წესებს].",
+       "foreign-structured-upload-form-2-label-noderiv": "<strong>არ უნდა შეიცავდეს</strong> სხვის ნამუშევარს, ასევე არ უნდა იგრძნობოდეს სხვისი ნამუშევრის გავლენა",
+       "foreign-structured-upload-form-2-label-useful": "უნდა იყოს სხვებისთვის <strong>საგანმანათლებლო და სასარგებლო</strong>",
        "foreign-structured-upload-form-3-label-yes": "დიახ",
        "foreign-structured-upload-form-3-label-no": "არა",
        "backend-fail-stream": "ფაილი $1 ტრანსლირება ვერ მოხერხდა.",
        "movenosubpage": "ამ გვერდს არა აქვს ქვეგვერდები",
        "movereason": "მიზეზი:",
        "revertmove": "გაუქმება",
-       "delete_and_move_text": "==საჭიროა წაშლა==\n\nსტატია დასახელებით „[[:$1]]“ უკვე არსებობს. გსურთ მისი წაშლა გადატანისთვის ადგილის დასათმობად?",
+       "delete_and_move_text": "სტატია დასახელებით „[[:$1]]“ უკვე არსებობს.\nგსურთ მისი წაშლა გადატანისთვის ადგილის დასათმობად?",
        "delete_and_move_confirm": "დიახ, წაშალეთ ეს გვერდი",
        "delete_and_move_reason": "წაშლილია „[[$1]]“-დან გადატანისთვის ადგილის დასათმობად",
        "selfmove": "წყარო და დანიშნულების სათაურები მსგავსია; შეუძლებელია გვერდის საკუთარ თავზე გადატანა.",
        "move-leave-redirect": "გადამისამართების დატოვება",
        "protectedpagemovewarning": "'''ყურადღება.''' ეს არის დაცული გვერდი. მისი გადატანა მხოლოდ ადმინისტრატორებს შეუძლია.\nიხილეთ დაცვის ჟურნალის ჩანაწერი ინფორმაციისთვის:",
        "semiprotectedpagemovewarning": "'''ყურადღება.''' ეს გვერდი დაცულია, მისი გადატანა მხოლოდ დარეგისტრირებულ მომხმარებლებს შეუძლიათ.\nიხილეთ დაცვის ჟურნალის ჩანაწერი ინფორმაციისთვის:",
-       "move-over-sharedrepo": "==ფაილი არსებობს==\n[[:$1]] არსებობს საზიარო საცავში. ფაილის ამ სათაურზე გადმოტანა საზიარო ფაილს გადაფარავს.",
+       "move-over-sharedrepo": "[[:$1]] არსებობს გაზიარებულ საცავში. ფაილის ამ სათაურზე გადატანა გაზიარებულ ფაილს გადაეწერება.",
        "file-exists-sharedrepo": "არჩეული ფაილის სახელი უკვე გამოყენებულია საზიარო საცავში.\nგთხოვთ სხვა სახელი აირჩიოთ.",
        "export": "გვერდების ექსპორტი",
        "exporttext": "თქვენ შეგიძლიათ ტექსტებისა, ცვლილებათა ჟურნალის და XML გვერდების ექსპორტირება, რომელიც შეიძლება შემდეგ [[Special:Import|გადატანილი]] იქნას სხვა ვიკიპროექტში, რომელიც მუშაობს MediaWiki-ზე.\n\nგვერდის ექსპორტირებისთვის შეიყვანეთ მათი სახელები თითო ხაზზე და აირჩიეთ, თუ გსურთ სტატიის ყველა ვერსიის გადატანა, თუ მხოლოდ ბოლო ვერსიისა.\n\nთქვენ შეგიძლიათ ასევე გამოიყენოთ სპეციალური მისამართი გვერდის მხოლოდ ბოლო ვერსიის საექსპორტოდ. მაგალითად [[{{MediaWiki:Mainpage}}]]  ეს არის მისამართი [[{{#Special:Export}}/{{MediaWiki:Mainpage}}]].",
        "lastmodifiedatby": "ეს გვერდი ბოლოს შეიცვალა $2, $1  $3-ით.",
        "othercontribs": "$1-ს ნამუშევრის მიხედვით.",
        "others": "სხვები",
-       "siteusers": "{{SITENAME}}-ის {{PLURAL:$2|მომხმარებელი|მომხმარებლები|}} $1",
+       "siteusers": "{{SITENAME}}-ის {{PLURAL:$2|{{GENDER:$1|მომხმარებელი}}|მომხმარებლები}} $1",
        "anonusers": "{{SITENAME}} ანონიმური {{PLURAL:$2|მომხმარებელი|მომხმარებლები}} $1",
        "creditspage": "წვლილი",
        "nocredits": "აქ ამ გვერდისთვის ხელმისაწვდომი ინფორმაცია არ არსებობს.",
        "svg-long-error": "არასწორი SVG ფაილი: $1",
        "show-big-image": "თავდაპირველი ფაილი",
        "show-big-image-preview": "ზომა წინასწარი გადახედვისას: $1.",
+       "show-big-image-preview-differ": "ამ $2 ფაილის $3 წინასწარი გადახედვის ზომაა: $1.",
        "show-big-image-other": "სხვა {{PLURAL:$2|გაფართოება|გაფართოება}}: $1.",
        "show-big-image-size": "$1 × $2 პიქსელი",
        "file-info-gif-looped": "დარგოლილი",
        "scarytranscludefailed-httpstatus": "[ვერ მოხერხდა თარგის ჩატვირთვა $1-თვის: HTTP $2]",
        "scarytranscludetoolong": "[URL ძალიან გრძელია]",
        "deletedwhileediting": "'''ყურადღება''': ეს გვერდი წაიშალა მას შემდეგ, რაც თქვენ მისი რედაქტირება დაიწყეთ!",
-       "confirmrecreate": "მომხმარებელმა [[User:$1|$1]] ([[User talk:$1|განხილვა]]) წაშალა ეს გვერდი მას შემდეგ რაც თქვენ დაიწყეთ რედაქტირება შემდეგი მიზეზით:\n: ''$2''\nგთხოვთ დაადასტუროთ, რომ ნამდვილად გსურთ ამ გვერდის აღდგენა.",
-       "confirmrecreate-noreason": "მომხმარებელმა [[User:$1|$1]] ([[User talk:$1|განხილვა]]) წაშალა ეს გვერდი მას შემდეგ, რაც თქვენ დაიწყეთ მისი რედაქტირება. გთხოვთ, დარწმუნდით, რომ თქვენ ნამდვილად გსურთ ამ გვერდის ხელახლა შექმნა.",
+       "confirmrecreate": "მომხმარებელმა [[User:$1|$1]] ([[User talk:$1|განხილვა]]) წაშალა ეს გვერდი მას შემდეგ რაც თქვენ დაიწყეთ რედაქტირება შემდეგი მიზეზით:\n: <em>$2</em>\nგთხოვთ დაადასტუროთ, რომ ნამდვილად გსურთ ამ გვერდის ხელახლა შექმნა.",
+       "confirmrecreate-noreason": "მომხმარებელმა [[User:$1|$1]] ([[User talk:$1|განხილვა]]) {{GENDER:$1|წაშალა}} ეს გვერდი მას შემდეგ, რაც თქვენ დაიწყეთ მისი რედაქტირება. გთხოვთ, დარწმუნდით, რომ თქვენ ნამდვილად გსურთ ამ გვერდის ხელახლა შექმნა.",
        "recreate": "აღადგინე",
        "unit-pixel": "პქ",
        "confirm_purge_button": "კარგი",
        "version-hook-subscribedby": "ჩაწერილია",
        "version-version": "($1)",
        "version-no-ext-name": "[სახელის გარეშე]",
-       "version-svn-revision": "(r$2)",
        "version-license": "მედიავიკის ლიცენზია",
        "version-ext-license": "ლიცენზია",
        "version-ext-colheader-name": "გაფართოებები",
        "htmlform-cloner-delete": "წაშლა",
        "htmlform-cloner-required": "აუცილებელია სულ მცირე ერთი მნიშვნელობა.",
        "htmlform-title-badnamespace": "[[:$1]] არ მდებარეობს \"{{ns:$2}}\"-ის სახელთა სივრცეში.",
+       "htmlform-title-not-creatable": "$1\" არ არის მართებული გვერდის სათაური",
        "htmlform-title-not-exists": "$1 არ არსებობს.",
        "htmlform-user-not-exists": "<strong>$1</strong> არ არსებობს.",
        "htmlform-user-not-valid": "<strong>$1</strong> არ არის სწორი მომხმარებლის სახელი.",
        "logentry-newusers-create2": "მომხმარებლის ანგარიში $3 {{GENDER:$2|შექმნა}} მომხმარებელმა $1",
        "logentry-newusers-byemail": "მომხმარებლის ანგარიში $3 {{GENDER:$2|შექმნა}} მომხმარებელმა $1 და პაროლი გაგზავნა ელ. ფოსტით",
        "logentry-newusers-autocreate": "ავტომატურად {{GENDER:$2|შეიქმნა}} მომხმარებლის ანგარიში $1",
+       "logentry-protect-protect": "$1-მ {{GENDER:$2|დაიცვა}} $3 $4",
+       "logentry-protect-protect-cascade": "$1-მ {{GENDER:$2|დაიცვა}} $3 $4 [კასკადური]",
+       "logentry-protect-modify": "$1-მ {{GENDER:$2|შეცვალა}} დაცვის დონე $3 $4-სთვის",
+       "logentry-protect-modify-cascade": "$1 {{GENDER:$2|შეცვალა}} დაცვის დონე $3 $4 [კასკადური]",
        "logentry-rights-rights": "მომხმარებელმა $1 {{GENDER:$2|შეცვალა}} ჯგუფის წევრობა $3-თვის $4-დან $5-ზე",
        "logentry-rights-rights-legacy": "მომხმარებელმა $1 {{GENDER:$2|შეცვალა}} ჯგუფის წევრობა $3-თვის",
        "logentry-rights-autopromote": "მომხმარებელი $1 ავტომატურად იქნა {{GENDER:$2|გადაყვანილი}} $4–დან $5–ში",
index a82d4d1..15d9801 100644 (file)
        "throttled-mailpassword": "비밀번호 재설정 이메일을 이미 최근 {{PLURAL:$1|$1시간}} 안에 보냈습니다.\n악용을 방지하기 위해 비밀번호 재설정 메일은 {{PLURAL:$1|$1시간}}마다 오직 하나씩만 보낼 수 있습니다.",
        "mailerror": "메일을 보내는 중 오류: $1",
        "acct_creation_throttle_hit": "당신의 IP 주소를 이용한 방문자가 이전에 이미 {{PLURAL:$1|계정 $1개}}를 만들어, 계정 만들기 한도를 초과하였습니다.\n따라서 지금은 이 IP 주소로는 더 이상 계정을 만들 수 없습니다.",
-       "emailauthenticated": "이메일 주소는 $2 에 $3 에서 인증되었습니다.",
+       "emailauthenticated": "이메일 주소가 $2 $3에 인증되었습니다.",
        "emailnotauthenticated": "이메일 주소를 인증하지 않았습니다.\n이메일 확인 절차를 거치지 않으면 다음 이메일 기능을 사용할 수 없습니다.",
        "noemailprefs": "이 기능을 사용하기 위해서는 사용자 환경 설정에서 이메일 주소를 설정해야 합니다.",
        "emailconfirmlink": "이메일 주소 확인",
index 1086375..9be1218 100644 (file)
        "upload-too-many-redirects": "URL yra per daug kartų peradresuotas",
        "upload-http-error": "Įvyko HTTP klaida: $1",
        "upload-copy-upload-invalid-domain": "Pakrovimų kopijos yra neleidžiamos iš šio domeno.",
+       "upload-foreign-cant-upload": "Šis vikis nėra sukonfigūruotas failų įkėlimui į nurodytą išorinę failų talpyklą.",
        "upload-dialog-title": "Įkelti failą",
        "upload-dialog-button-cancel": "Atšaukti",
        "upload-dialog-button-done": "Atlikta",
index 623ab53..8d79620 100644 (file)
@@ -17,7 +17,8 @@
                        "灰太狼Wolffy55",
                        "RalfX",
                        "Davidzdh",
-                       "Nemo bis"
+                       "Nemo bis",
+                       "飞舞回堂前"
                ]
        },
        "tog-underline": "鏈墊線:",
        "viewsourceold": "察源碼",
        "editlink": "纂",
        "viewsourcelink": "察源碼",
-       "editsectionhint": "纂 $1",
+       "editsectionhint": "纂段:$1",
        "toc": "章",
        "showtoc": "示",
        "hidetoc": "藏",
        "prefs-displayrc": "示項",
        "prefs-displaywatchlist": "示項",
        "prefs-diffs": "異",
-       "email-address-validity-valid": "電郵有效之",
-       "email-address-validity-invalid": "貢一效之電郵",
        "userrights": "秉治權任",
        "userrights-lookup-user": "司社",
        "userrights-user-editname": "簿名:",
        "right-blockemail": "鎖簿無電郵",
        "right-hideuser": "鎖簿名,予藏眾",
        "right-ipblock-exempt": "繞IP鎖、自鎖與圍鎖",
-       "right-proxyunbannable": "繞Proxy之自鎖",
        "right-unblockself": "自解鎖",
        "right-protect": "改錮級與纂錮頁",
        "right-editprotected": "纂錮頁(無連錮)",
        "upload-options": "貢項",
        "watchthisupload": "派哨",
        "filename-bad-prefix": "獻檔以'''「$1」'''首,常由相機瞎造,惠更述之。",
-       "upload-success-subj": "檔案安矣",
-       "upload-success-msg": "爾自[$2]之貢安矣,見於此:[[:{{ns:file}}:$1]]",
-       "upload-failure-subj": "貢問",
-       "upload-failure-msg": "爾自[$2]之貢現問也:\n\n$1",
-       "upload-warning-subj": "貢警",
-       "upload-warning-msg": "爾自[$2]之貢出問。爾可回[[Special:Upload/stash/$1|貢表]]修此問。",
        "upload-proto-error": "協訂錯誤",
        "upload-too-many-redirects": "網址含多轉",
        "upload-http-error": "發一HTTP之錯:$1",
        "movelogpagetext": "頁遷如下:",
        "movereason": "因",
        "revertmove": "還",
-       "delete_and_move": "刪遷",
        "delete_and_move_text": "==准刪==\n\n往遷\"[[:$1]]\"存,刪之以替乎?",
        "delete_and_move_confirm": "刪之",
        "delete_and_move_reason": "為遷而刪之",
        "tooltip-pt-logout": "凡事盡,乘雲飄",
        "tooltip-pt-createaccount": "勸君增簿以登,然非必須之舉",
        "tooltip-ca-talk": "求異見、辯是非、妥紛擾",
-       "tooltip-ca-edit": "拓文意、校誤謬、潤辭藻",
+       "tooltip-ca-edit": "纂是頁",
        "tooltip-ca-addsection": "有言議,添新要",
        "tooltip-ca-viewsource": "文函緘,讀源老",
        "tooltip-ca-history": "誌流衍、備謄本、修惡盜",
        "tooltip-ca-move": "安居所,嚮正道",
        "tooltip-ca-watch": "哨此報",
        "tooltip-ca-unwatch": "撤此哨",
-       "tooltip-search": "索大典,籲自曉",
+       "tooltip-search": "尋於{{SITENAME}}",
        "tooltip-search-go": "確合契,躍步到",
        "tooltip-search-fulltext": "尋通篇,列倣傚",
        "tooltip-p-logo": "返卷首,訪露朝",
        "tooltip-t-contributions": "同肩戰,苦功高",
        "tooltip-t-emailuser": "言未猶,書信捎",
        "tooltip-t-upload": "貢彩件、獻樂謠",
-       "tooltip-t-specialpages": "å¥\87æ\80ªæ±\82ï¼\8cç\89¹æ\9f¥æ\89¾",
+       "tooltip-t-specialpages": "å±\95ç\9b¡å¥\87é \81",
        "tooltip-t-print": "備印墨,整版貌",
        "tooltip-t-permalink": "鏈緊焊,橋吊牢",
        "tooltip-ca-nstab-main": "閱文稿",
        "tooltip-ca-nstab-user": "返齋寮",
        "tooltip-ca-nstab-media": "聽媒紹",
-       "tooltip-ca-nstab-special": "特查報,謝纂校",
+       "tooltip-ca-nstab-special": "是爲奇頁,謝纂校",
        "tooltip-ca-nstab-project": "探爐灶",
        "tooltip-ca-nstab-image": "觀揮毫",
        "tooltip-ca-nstab-mediawiki": "聞官耗",
        "specialpages": "特查",
        "specialpages-note": "* 準特查。\n* <strong class=\"mw-specialpagerestricted\">限特查。</strong>",
        "specialpages-group-maintenance": "護報",
-       "specialpages-group-other": "它之奇頁",
+       "specialpages-group-other": "奇頁",
        "specialpages-group-login": "登/增",
        "specialpages-group-changes": "近易與誌",
        "specialpages-group-media": "媒報兼呈",
index 5c5c1db..e0d5e8d 100644 (file)
        "resetpass_submit": "Поставете лозинка и најавете се",
        "changepassword-success": "Вашата лозинка е успешно сменета!",
        "changepassword-throttled": "Имате премногу обиди за најава за кратко време.\nПочекајте $1 пред да се обидете повторно.",
+       "botpasswords-label-appid": "Име на ботот:",
+       "botpasswords-label-create": "Создај",
+       "botpasswords-label-update": "Поднови",
+       "botpasswords-label-cancel": "Откажи",
+       "botpasswords-label-delete": "Избриши",
+       "botpasswords-label-resetpassword": "Ставете нова лозинка",
+       "botpasswords-label-grants": "Применливи доделувања:",
        "resetpass_forbidden": "Лозинките не може да се менуваат",
        "resetpass-no-info": "Мора да сте најавени ако сакате да имате директен пристап до оваа страница.",
        "resetpass-submit-loggedin": "Смени лозинка",
        "log-title-wildcard": "Пребарај наслови кои почнуваат со овој текст",
        "showhideselectedlogentries": "Прикажи/скриј одбрани записи",
        "log-edit-tags": "Измени ознаки на одредени дневнички записи",
+       "checkbox-select": "Одбери: $1",
+       "checkbox-all": "Сите",
+       "checkbox-none": "Ништо",
+       "checkbox-invert": "Избери обратно",
        "allpages": "Сите страници",
        "nextpage": "Следна страница ($1)",
        "prevpage": "Претходна страница ($1)",
        "lockedbyandtime": "(од $1 на $2 цо $3 ч.)",
        "move-page": "Премести $1",
        "move-page-legend": "Премести страница",
-       "movepagetext": "Со ÐºÐ¾Ñ\80иÑ\81Ñ\82еÑ\9aеÑ\82о Ð½Ð° Ð¾Ð²Ð¾Ñ\98 Ð¾Ð±Ñ\80азеÑ\86 Ð¼Ð¾Ð¶ÐµÑ\82е Ð´Ð° Ð¿Ñ\80еименÑ\83ваÑ\82е Ñ\81Ñ\82Ñ\80аниÑ\86а, Ð¿Ñ\80емеÑ\81Ñ\82Ñ\83ваÑ\98Ñ\9cи Ñ\98а Ñ\86елаÑ\82а Ð½ÐµÑ\98зина Ð¸Ñ\81Ñ\82оÑ\80иÑ\98а Ð¿Ð¾Ð´ Ð½Ð¾Ð²Ð¾ Ð¸Ð¼Ðµ.\nСÑ\82аÑ\80иоÑ\82 Ð½Ð°Ñ\81лов Ñ\9cе Ñ\81Ñ\82ане Ð¿Ñ\80енаÑ\81оÑ\87Ñ\83ваÑ\87ка Ñ\81Ñ\82Ñ\80аниÑ\86а ÐºÐ¾Ð½ Ð½Ð¾Ð²Ð¸Ð¾Ñ\82 Ð½Ð°Ñ\81лов.\nÐ\90вÑ\82омаÑ\82Ñ\81ки Ð¼Ð¾Ð¶ÐµÑ\82е Ð´Ð° Ð³Ð¸ Ð¿Ð¾Ð´Ð½Ð¾Ð²Ð¸Ñ\82е Ð¿Ñ\80енаÑ\81оÑ\87Ñ\83ваÑ\9aаÑ\82а ÐºÐ¾Ð¸ Ð¿Ð¾ÐºÐ°Ð¶Ñ\83вааÑ\82 ÐºÐ¾Ð½ Ð¿Ñ\80вобиÑ\82ниоÑ\82 Ð½Ð°Ñ\81лов.\nÐ\90ко Ð½Ðµ Ð¸Ð·Ð±ÐµÑ\80еÑ\82е Ð°Ð²Ñ\82омаÑ\82Ñ\81ко Ð¿Ð¾Ð´Ð½Ð¾Ð²Ñ\83ваÑ\9aе, Ð¿Ñ\80овеÑ\80еÑ\82е Ð½Ð° [[Special:DoubleRedirects|двоÑ\98ни]] Ð¸Ð»Ð¸ [[Special:BrokenRedirects|пÑ\80екинаÑ\82и Ð¿Ñ\80енаÑ\81оÑ\87Ñ\83ваÑ\9aа]].\nÐ\9dа Ð²Ð°Ñ\81 Ðµ Ð¾Ð´Ð³Ð¾Ð²Ð¾Ñ\80ноÑ\81Ñ\82а Ð´Ð° Ñ\81е Ð¾Ñ\81игÑ\83Ñ\80аÑ\82е Ð´ÐµÐºÐ° Ð²Ñ\80Ñ\81киÑ\82е Ñ\9cе Ð¿Ñ\80одолжаÑ\82 Ð´Ð° Ð½Ð°Ñ\81оÑ\87Ñ\83вааÑ\82 Ñ\82амÑ\83 Ð·Ð° ÐºÐ°Ð´Ðµ Ñ\81е Ð¿Ñ\80едвидени.\n\nÐ\98маÑ\98Ñ\82е Ð¿Ñ\80едвид Ð´ÐµÐºÐ° Ñ\81Ñ\82Ñ\80аниÑ\86аÑ\82а '''нема''' Ð´Ð° Ð±Ð¸Ð´Ðµ Ð¿Ñ\80емеÑ\81Ñ\82ена Ð°ÐºÐ¾ Ð²ÐµÑ\9cе Ð¿Ð¾Ñ\81Ñ\82ои Ñ\81Ñ\82Ñ\80аниÑ\86а Ñ\81о Ð½Ð¾Ð²Ð¸Ð¾Ñ\82 Ð½Ð°Ñ\81лов, Ð¾Ñ\81вен Ð°ÐºÐ¾ Ðµ Ð½Ðµ Ðµ Ð¿Ñ\80енаÑ\81оÑ\87Ñ\83ваÑ\9aе Ð¸ Ð½ÐµÐ¼Ð° Ð¸Ñ\81Ñ\82оÑ\80иÑ\98а Ð½Ð° Ð¼Ð¸Ð½Ð°Ñ\82и Ñ\83Ñ\80едÑ\83ваÑ\9aа. Ð¢Ð¾Ð° Ð·Ð½Ð°Ñ\87и Ð´ÐµÐºÐ° Ð¼Ð¾Ð¶ÐµÑ\82е Ð´Ð° Ñ\98а Ð¿Ñ\80еименÑ\83ваÑ\82е Ñ\81Ñ\82Ñ\80аниÑ\86аÑ\82а ÐºÐ°ÐºÐ¾ Ñ\88Ñ\82о Ð±Ð¸Ð»Ð° Ð¿Ñ\80еÑ\82Ñ\85одно Ð´Ð¾ÐºÐ¾Ð»ÐºÑ\83 Ñ\81Ñ\82е Ð½Ð°Ð¿Ñ\80авиле Ð³Ñ\80еÑ\88ка Ð±ÐµÐ· Ð´Ð° Ñ\98а Ð¿Ñ\80екÑ\80иеÑ\82е Ð¿Ð¾Ñ\81Ñ\82оеÑ\87каÑ\82а Ñ\81Ñ\82Ñ\80аниÑ\86а.\n\n'''Ð\9fÑ\80едÑ\83пÑ\80едÑ\83ваÑ\9aе!'''\nОва може да биде драстична и неочекувана промена за популарна страница;\nосигурајте се дека сте ги разбрале последиците од ова пред да продолжите.",
-       "movepagetext-noredirectfixer": "Со ÐºÐ¾Ñ\80иÑ\81Ñ\82еÑ\9aеÑ\82о Ð½Ð° Ð¾Ð²Ð¾Ñ\98 Ð¾Ð±Ñ\80азеÑ\86 Ð¼Ð¾Ð¶ÐµÑ\82е Ð´Ð° Ð¿Ñ\80еименÑ\83ваÑ\82е Ñ\81Ñ\82Ñ\80аниÑ\86а, Ð¿Ñ\80емеÑ\81Ñ\82Ñ\83ваÑ\98Ñ\9cи Ñ\98а Ñ\86елаÑ\82а Ð½ÐµÑ\98зина Ð¸Ñ\81Ñ\82оÑ\80иÑ\98а Ð¿Ð¾Ð´ Ð½Ð¾Ð²Ð¾ Ð¸Ð¼Ðµ.\nСÑ\82аÑ\80иоÑ\82 Ð½Ð°Ñ\81лов Ñ\9cе Ñ\81Ñ\82ане Ð¿Ñ\80енаÑ\81оÑ\87Ñ\83ваÑ\87ка Ñ\81Ñ\82Ñ\80аниÑ\86а ÐºÐ¾Ð½ Ð½Ð¾Ð²Ð¸Ð¾Ñ\82 Ð½Ð°Ñ\81лов.\nÐ\90вÑ\82омаÑ\82Ñ\81ки Ð¼Ð¾Ð¶ÐµÑ\82е Ð´Ð° Ð³Ð¸ Ð¿Ð¾Ð´Ð½Ð¾Ð²Ð¸Ñ\82е Ð¿Ñ\80енаÑ\81оÑ\87Ñ\83ваÑ\9aаÑ\82а ÐºÐ¾Ð¸ Ð¿Ð¾ÐºÐ°Ð¶Ñ\83вааÑ\82 ÐºÐ¾Ð½ Ð¿Ñ\80вобиÑ\82ниоÑ\82 Ð½Ð°Ñ\81лов.\nÐ\9dе Ð·Ð°Ð±Ð¾Ñ\80аваÑ\98Ñ\82е Ð´Ð° Ð¿Ñ\80овеÑ\80иÑ\82е [[Special:DoubleRedirects|двоÑ\98ни]] Ð¸ [[Special:BrokenRedirects|пÑ\80екинаÑ\82и Ð¿Ñ\80енаÑ\81оÑ\87Ñ\83ваÑ\9aа]].\nÐ\9dа Ð²Ð°Ñ\81 Ðµ Ð¾Ð´Ð³Ð¾Ð²Ð¾Ñ\80ноÑ\81Ñ\82а Ð´Ð° Ñ\81е Ð¾Ñ\81игÑ\83Ñ\80аÑ\82е Ð´ÐµÐºÐ° Ð²Ñ\80Ñ\81киÑ\82е Ñ\9cе Ð¿Ñ\80одолжаÑ\82 Ð´Ð° Ð½Ð°Ñ\81оÑ\87Ñ\83вааÑ\82 Ñ\82амÑ\83 Ð·Ð° ÐºÐ°Ð´Ðµ Ñ\81е Ð¿Ñ\80едвидени.\n\nÐ\98маÑ\98Ñ\82е Ð¿Ñ\80едвид Ð´ÐµÐºÐ° Ñ\81Ñ\82Ñ\80аниÑ\86аÑ\82а '''Ð\9dÐ\95Ð\9cÐ\90''' Ð´Ð° Ð±Ð¸Ð´Ðµ Ð¿Ñ\80емеÑ\81Ñ\82ена Ð°ÐºÐ¾ Ð²ÐµÑ\9cе Ð¿Ð¾Ñ\81Ñ\82ои Ñ\81Ñ\82Ñ\80аниÑ\86а Ñ\81о Ð½Ð¾Ð²Ð¸Ð¾Ñ\82 Ð½Ð°Ñ\81лов, Ð¾Ñ\81вен Ð°ÐºÐ¾ Ðµ Ð¿Ñ\80азна Ð¸Ð»Ð¸ Ð°ÐºÐ¾ Ðµ Ð¿Ñ\80енаÑ\81оÑ\87Ñ\83ваÑ\9aе Ð¸ Ð½ÐµÐ¼Ð° Ð¸Ñ\81Ñ\82оÑ\80иÑ\98а Ð½Ð° Ð¼Ð¸Ð½Ð°Ñ\82и Ñ\83Ñ\80едÑ\83ваÑ\9aа. Ð¢Ð¾Ð° Ð·Ð½Ð°Ñ\87и Ð´ÐµÐºÐ° Ð¼Ð¾Ð¶ÐµÑ\82е Ð´Ð° Ñ\98а Ð¿Ñ\80еименÑ\83ваÑ\82е Ñ\81Ñ\82Ñ\80аниÑ\86аÑ\82а ÐºÐ°ÐºÐ¾ Ñ\88Ñ\82о Ð±Ð¸Ð»Ð° Ð¿Ñ\80еÑ\82Ñ\85одно Ð´Ð¾ÐºÐ¾Ð»ÐºÑ\83 Ñ\81Ñ\82е Ð½Ð°Ð¿Ñ\80авиле Ð³Ñ\80еÑ\88ка Ð±ÐµÐ· Ð´Ð° Ñ\98а Ð¿Ñ\80екÑ\80иеÑ\82е Ð¿Ð¾Ñ\81Ñ\82оеÑ\87каÑ\82а Ñ\81Ñ\82Ñ\80аниÑ\86а.\n\n'''Ð\9fРÐ\95Ð\94УÐ\9fРÐ\95Ð\94УÐ\92Ð\90Ð\8aÐ\95!'''\nОва може да биде драстична и неочекувана промена за популарна страница;\nосигурајте се дека сте ги разбрале последиците од ова пред да продолжите.",
+       "movepagetext": "Со ÐºÐ¾Ñ\80иÑ\81Ñ\82еÑ\9aеÑ\82о Ð½Ð° Ð¾Ð²Ð¾Ñ\98 Ð¾Ð±Ñ\80азеÑ\86 Ð¼Ð¾Ð¶ÐµÑ\82е Ð´Ð° Ð¿Ñ\80еименÑ\83ваÑ\82е Ñ\81Ñ\82Ñ\80аниÑ\86а, Ð¿Ñ\80емеÑ\81Ñ\82Ñ\83ваÑ\98Ñ\9cи Ñ\98а Ñ\86елаÑ\82а Ð½ÐµÑ\98зина Ð¸Ñ\81Ñ\82оÑ\80иÑ\98а Ð¿Ð¾Ð´ Ð½Ð¾Ð²Ð¾ Ð¸Ð¼Ðµ.\nСÑ\82аÑ\80иоÑ\82 Ð½Ð°Ñ\81лов Ñ\9cе Ñ\81Ñ\82ане Ð¿Ñ\80енаÑ\81оÑ\87Ñ\83ваÑ\87ка Ñ\81Ñ\82Ñ\80аниÑ\86а ÐºÐ¾Ð½ Ð½Ð¾Ð²Ð¸Ð¾Ñ\82 Ð½Ð°Ñ\81лов.\nÐ\90вÑ\82омаÑ\82Ñ\81ки Ð¼Ð¾Ð¶ÐµÑ\82е Ð´Ð° Ð³Ð¸ Ð¿Ð¾Ð´Ð½Ð¾Ð²Ð¸Ñ\82е Ð¿Ñ\80енаÑ\81оÑ\87Ñ\83ваÑ\9aаÑ\82а ÐºÐ¾Ð¸ Ð¿Ð¾ÐºÐ°Ð¶Ñ\83вааÑ\82 ÐºÐ¾Ð½ Ð¿Ñ\80вобиÑ\82ниоÑ\82 Ð½Ð°Ñ\81лов.\nÐ\90ко Ð½Ðµ Ð¸Ð·Ð±ÐµÑ\80еÑ\82е Ð°Ð²Ñ\82омаÑ\82Ñ\81ко Ð¿Ð¾Ð´Ð½Ð¾Ð²Ñ\83ваÑ\9aе, Ð¿Ñ\80овеÑ\80еÑ\82е Ð½Ð° [[Special:DoubleRedirects|двоÑ\98ни]] Ð¸Ð»Ð¸ [[Special:BrokenRedirects|пÑ\80екинаÑ\82и Ð¿Ñ\80енаÑ\81оÑ\87Ñ\83ваÑ\9aа]].\nÐ\9dа Ð²Ð°Ñ\81 Ðµ Ð¾Ð´Ð³Ð¾Ð²Ð¾Ñ\80ноÑ\81Ñ\82а Ð´Ð° Ñ\81е Ð¾Ñ\81игÑ\83Ñ\80аÑ\82е Ð´ÐµÐºÐ° Ð²Ñ\80Ñ\81киÑ\82е Ñ\9cе Ð¿Ñ\80одолжаÑ\82 Ð´Ð° Ð½Ð°Ñ\81оÑ\87Ñ\83вааÑ\82 Ñ\82амÑ\83 Ð·Ð° ÐºÐ°Ð´Ðµ Ñ\81е Ð¿Ñ\80едвидени.\n\nÐ\98маÑ\98Ñ\82е Ð¿Ñ\80едвид Ð´ÐµÐºÐ° Ñ\81Ñ\82Ñ\80аниÑ\86аÑ\82а '''нема''' Ð´Ð° Ð±Ð¸Ð´Ðµ Ð¿Ñ\80емеÑ\81Ñ\82ена Ð°ÐºÐ¾ Ð²ÐµÑ\9cе Ð¿Ð¾Ñ\81Ñ\82ои Ñ\81Ñ\82Ñ\80аниÑ\86а Ñ\81о Ð½Ð¾Ð²Ð¸Ð¾Ñ\82 Ð½Ð°Ñ\81лов, Ð¾Ñ\81вен Ð°ÐºÐ¾ Ðµ Ð½Ðµ Ðµ Ð¿Ñ\80енаÑ\81оÑ\87Ñ\83ваÑ\9aе Ð¸ Ð½ÐµÐ¼Ð° Ð¸Ñ\81Ñ\82оÑ\80иÑ\98а Ð½Ð° Ð¼Ð¸Ð½Ð°Ñ\82и Ñ\83Ñ\80едÑ\83ваÑ\9aа. Ð¢Ð¾Ð° Ð·Ð½Ð°Ñ\87и Ð´ÐµÐºÐ° Ð¼Ð¾Ð¶ÐµÑ\82е Ð´Ð° Ñ\98а Ð¿Ñ\80еименÑ\83ваÑ\82е Ñ\81Ñ\82Ñ\80аниÑ\86аÑ\82а ÐºÐ°ÐºÐ¾ Ñ\88Ñ\82о Ð±Ð¸Ð»Ð° Ð¿Ñ\80еÑ\82Ñ\85одно Ð´Ð¾ÐºÐ¾Ð»ÐºÑ\83 Ñ\81Ñ\82е Ð½Ð°Ð¿Ñ\80авиле Ð³Ñ\80еÑ\88ка Ð±ÐµÐ· Ð´Ð° Ñ\98а Ð¿Ñ\80екÑ\80иеÑ\82е Ð¿Ð¾Ñ\81Ñ\82оеÑ\87каÑ\82а Ñ\81Ñ\82Ñ\80аниÑ\86а.\n\n'''Ð\9dапомена:'''\nОва може да биде драстична и неочекувана промена за популарна страница;\nосигурајте се дека сте ги разбрале последиците од ова пред да продолжите.",
+       "movepagetext-noredirectfixer": "Со ÐºÐ¾Ñ\80иÑ\81Ñ\82еÑ\9aеÑ\82о Ð½Ð° Ð¾Ð²Ð¾Ñ\98 Ð¾Ð±Ñ\80азеÑ\86 Ð¼Ð¾Ð¶ÐµÑ\82е Ð´Ð° Ð¿Ñ\80еименÑ\83ваÑ\82е Ñ\81Ñ\82Ñ\80аниÑ\86а, Ð¿Ñ\80емеÑ\81Ñ\82Ñ\83ваÑ\98Ñ\9cи Ñ\98а Ñ\86елаÑ\82а Ð½ÐµÑ\98зина Ð¸Ñ\81Ñ\82оÑ\80иÑ\98а Ð¿Ð¾Ð´ Ð½Ð¾Ð²Ð¾ Ð¸Ð¼Ðµ.\nСÑ\82аÑ\80иоÑ\82 Ð½Ð°Ñ\81лов Ñ\9cе Ñ\81Ñ\82ане Ð¿Ñ\80енаÑ\81оÑ\87Ñ\83ваÑ\87ка Ñ\81Ñ\82Ñ\80аниÑ\86а ÐºÐ¾Ð½ Ð½Ð¾Ð²Ð¸Ð¾Ñ\82 Ð½Ð°Ñ\81лов.\nÐ\90вÑ\82омаÑ\82Ñ\81ки Ð¼Ð¾Ð¶ÐµÑ\82е Ð´Ð° Ð³Ð¸ Ð¿Ð¾Ð´Ð½Ð¾Ð²Ð¸Ñ\82е Ð¿Ñ\80енаÑ\81оÑ\87Ñ\83ваÑ\9aаÑ\82а ÐºÐ¾Ð¸ Ð¿Ð¾ÐºÐ°Ð¶Ñ\83вааÑ\82 ÐºÐ¾Ð½ Ð¿Ñ\80вобиÑ\82ниоÑ\82 Ð½Ð°Ñ\81лов.\nÐ\9dе Ð·Ð°Ð±Ð¾Ñ\80аваÑ\98Ñ\82е Ð´Ð° Ð¿Ñ\80овеÑ\80иÑ\82е [[Special:DoubleRedirects|двоÑ\98ни]] Ð¸ [[Special:BrokenRedirects|пÑ\80екинаÑ\82и Ð¿Ñ\80енаÑ\81оÑ\87Ñ\83ваÑ\9aа]].\nÐ\9dа Ð²Ð°Ñ\81 Ðµ Ð¾Ð´Ð³Ð¾Ð²Ð¾Ñ\80ноÑ\81Ñ\82а Ð´Ð° Ñ\81е Ð¾Ñ\81игÑ\83Ñ\80аÑ\82е Ð´ÐµÐºÐ° Ð²Ñ\80Ñ\81киÑ\82е Ñ\9cе Ð¿Ñ\80одолжаÑ\82 Ð´Ð° Ð½Ð°Ñ\81оÑ\87Ñ\83вааÑ\82 Ñ\82амÑ\83 Ð·Ð° ÐºÐ°Ð´Ðµ Ñ\81е Ð¿Ñ\80едвидени.\n\nÐ\98маÑ\98Ñ\82е Ð¿Ñ\80едвид Ð´ÐµÐºÐ° Ñ\81Ñ\82Ñ\80аниÑ\86аÑ\82а '''Ð\9dÐ\95Ð\9cÐ\90''' Ð´Ð° Ð±Ð¸Ð´Ðµ Ð¿Ñ\80емеÑ\81Ñ\82ена Ð°ÐºÐ¾ Ð²ÐµÑ\9cе Ð¿Ð¾Ñ\81Ñ\82ои Ñ\81Ñ\82Ñ\80аниÑ\86а Ñ\81о Ð½Ð¾Ð²Ð¸Ð¾Ñ\82 Ð½Ð°Ñ\81лов, Ð¾Ñ\81вен Ð°ÐºÐ¾ Ðµ Ð¿Ñ\80азна Ð¸Ð»Ð¸ Ð°ÐºÐ¾ Ðµ Ð¿Ñ\80енаÑ\81оÑ\87Ñ\83ваÑ\9aе Ð¸ Ð½ÐµÐ¼Ð° Ð¸Ñ\81Ñ\82оÑ\80иÑ\98а Ð½Ð° Ð¼Ð¸Ð½Ð°Ñ\82и Ñ\83Ñ\80едÑ\83ваÑ\9aа. Ð¢Ð¾Ð° Ð·Ð½Ð°Ñ\87и Ð´ÐµÐºÐ° Ð¼Ð¾Ð¶ÐµÑ\82е Ð´Ð° Ñ\98а Ð¿Ñ\80еименÑ\83ваÑ\82е Ñ\81Ñ\82Ñ\80аниÑ\86аÑ\82а ÐºÐ°ÐºÐ¾ Ñ\88Ñ\82о Ð±Ð¸Ð»Ð° Ð¿Ñ\80еÑ\82Ñ\85одно Ð´Ð¾ÐºÐ¾Ð»ÐºÑ\83 Ñ\81Ñ\82е Ð½Ð°Ð¿Ñ\80авиле Ð³Ñ\80еÑ\88ка Ð±ÐµÐ· Ð´Ð° Ñ\98а Ð¿Ñ\80екÑ\80иеÑ\82е Ð¿Ð¾Ñ\81Ñ\82оеÑ\87каÑ\82а Ñ\81Ñ\82Ñ\80аниÑ\86а.\n\n'''Ð\9dапомена:'''\nОва може да биде драстична и неочекувана промена за популарна страница;\nосигурајте се дека сте ги разбрале последиците од ова пред да продолжите.",
        "movepagetalktext": "Ако го штиклирате кутивчево, соодветната страница за разговор ќе биде автоматски преместена на нов наслов, освен ако таму веќе постои страница за разговор што не е празна.\n\nВо тој случај, ќе треба да ја преместите или споите страницата рачно, доколку сакате.",
        "moveuserpage-warning": "'''Предупредување:''' На пат сте да преместите корисничка страница. Имајте предвид дека само страницата ќе биде преместена, а самиот корисник ''нема'' да биде преименуван.",
        "movecategorypage-warning": "<strong>Предупредување:</strong> Преместувате категориска страница. Имајте предвид дека ќе се премести само страницата, а страниците во старата категорија <em>нема</em> да се прекатегоризираат во новата.",
        "movenosubpage": "Оваа страница нема потстраници.",
        "movereason": "Причина:",
        "revertmove": "врати",
-       "delete_and_move_text": "==Потребно бришење==\nЦелната статија „[[:$1]]“ веќе постои.\nДали сакате да ја избришете за да ослободите место за преместувањето?",
+       "delete_and_move_text": "Целната статија „[[:$1]]“ веќе постои.\nДали сакате да ја избришете за да ослободите место за преместувањето?",
        "delete_and_move_confirm": "Да, избриши ја страницата",
        "delete_and_move_reason": "Избришано за да се ослободи место за преместувањето од „[[$1]]“",
        "selfmove": "Појдовната и целната страница се истоветни;\nне можам да преместам.",
        "move-leave-redirect": "Направи пренасочување",
        "protectedpagemovewarning": "'''Предупредување:'''  Оваа страница е заштитена, така што само може да ја преместуваат само корисници со администраторски привилегии.\nЗа ваша информација, подолу е прикажана последната ставка во дневникот на измени:",
        "semiprotectedpagemovewarning": "'''Напомена:'''  Оваа страница е заштитена, така што може да ја преместуваат само регистрирани корисници.\nЗа ваша информација, подолу е прикажана последната ставка во дневникот на измени:",
-       "move-over-sharedrepo": "== Податотеката постои ==\n[[:$1]] постои на заедничко складиште. Ако податотеката ја преместите на овој наслов, тоа ќе ја потисне заедничката податотека.",
+       "move-over-sharedrepo": "[[:$1]] постои на заедничко складиште. Ако податотеката ја преместите на овој наслов, тоа ќе ја потисне заедничката податотека.",
        "file-exists-sharedrepo": "Одбраното име на податотеката веќе се користи на заедничко складиште.\nОдберете друго име.",
        "export": "Извоз на страници",
        "exporttext": "Можете да го извезете текстот и историјата на уредување на избрана страница или група на страници во XML формат.\nОвие податоци може да бидат вчитани на некое друго вики кое се користи со МедијаВики преку [[Special:Import|увезување на страница]].\n\nЗа извезување на страници, внесете ги насловите во полето прикажано подолу, еден наслов на статија во ред, потоа изберете дали сакате да ја извезете само последната преработка или и сите постари преработки.\n\nАко ја сакате само тековната верзија, би можеле да искористите врска од видот [[{{#Special:Export}}/{{MediaWiki:Mainpage}}]] за страницата „[[{{MediaWiki:Mainpage}}]]“.",
        "tooltip-feed-rss": "RSS емитување за оваа страница",
        "tooltip-feed-atom": "Атом-емитување за оваа страница",
        "tooltip-t-contributions": "Список на придонеси {{GENDER:$1|на овој корисник}}",
-       "tooltip-t-emailuser": "Испрати е-пошта на овој корисник",
+       "tooltip-t-emailuser": "Испрати е-пошта {{GENDER:$1|на овој корисник}}",
        "tooltip-t-info": "Повеќе информаици за страницава",
        "tooltip-t-upload": "Подигни податотеки",
        "tooltip-t-specialpages": "Список на сите службени страници",
        "lastmodifiedatby": "Последната промена на страницава е извршена на $1 г Сво $2 ч. Промената ја направи $3.",
        "othercontribs": "Засновано на работата на $1.",
        "others": "други",
-       "siteusers": "{{PLURAL:$2|корисникот|корисниците}} на {{SITENAME}} $1",
+       "siteusers": "{{SITENAME}} {{PLURAL:$2|{{GENDER:$1|корисник}}|корисници}} $1",
        "anonusers": "{{PLURAL:$2|анонимен корисник|анонимни корисници}} на {{SITENAME}} $1",
        "creditspage": "Автори на страницата",
        "nocredits": "Не постојат податоци за авторите на оваа страница.",
        "version-hook-subscribedby": "Претплатено од",
        "version-version": "($1)",
        "version-no-ext-name": "[нема име]",
-       "version-svn-revision": "прер. $1",
        "version-license": "Лиценца на МедијаВики",
        "version-ext-license": "Лиценца",
        "version-ext-colheader-name": "Додаток",
        "redirect-page": "Назнака на страницата",
        "redirect-revision": "Преработка на страницата",
        "redirect-file": "Име на податотека",
+       "redirect-logid": "Назнака на дневникот",
        "redirect-not-exists": "Вредноста не е најдена",
        "fileduplicatesearch": "Барање на дуплирани податотеки",
        "fileduplicatesearch-summary": "Пребарување на дуплирани податотеки по тарабни вредности.",
        "expand_templates_preview_fail_html": "<em>Бидејќи {{SITENAME}} има овозможено сиров HTML и се јави губиток на седнички податоци, прегледот е скриен како мерка на претпазливост против напади со JavaScript.</em>\n\n<strong>Ако ова е е легитимен обид за преглед, тогаш обидете се повторно.</strong>\nАко не работи и тогаш, [[Special:UserLogout|одјавете се]] и повторно најавете се.",
        "expand_templates_preview_fail_html_anon": "<em>Бидејќи {{SITENAME}} има овозможено сиров HTML, а вие не сте најавени, прегледот е скриен како мерка на претпазливост против напади со JavaScript.</em>\n\n<strong>Ако ова е е легитимен обид за преглед, тогаш обидете се повторно.</strong>\nАко не работи и тогаш, [[Special:UserLogout|одјавете се]] и повторно најавете се.",
        "expand_templates_input_missing": "Треба да внесете некаков текст.",
-       "pagelanguage": "Ð\98збоÑ\80ник Ð·Ð° Ñ\98азик Ð½Ð° Ñ\81Ñ\82Ñ\80аниÑ\86аÑ\82а",
+       "pagelanguage": "Ð\9cенÑ\83ваÑ\9aе Ñ\98азик Ð½Ð° Ñ\81Ñ\82Ñ\80аниÑ\86а",
        "pagelang-name": "Страница",
        "pagelang-language": "Јазик",
        "pagelang-use-default": "Користи стандарден јазик",
        "mw-widgets-titleinput-description-new-page": "страницата сè уште не постои",
        "mw-widgets-titleinput-description-redirect": "пренасочување кон $1",
        "api-error-blacklisted": "Одберете поинаков, описен наслов.",
+       "sessionprovider-generic": "$1 седници",
+       "sessionprovider-mediawiki-session-cookiesessionprovider": "седници со колачиња",
        "randomrootpage": "Случајна основна страница"
 }
index 4628e81..d7670a0 100644 (file)
@@ -12,7 +12,8 @@
                        "Zorigt",
                        "לערי ריינהארט",
                        "아라",
-                       "Sembuk"
+                       "Sembuk",
+                       "Munkhzaya.E"
                ]
        },
        "tog-underline": "Линкүүдийн доогуур зураас зур:",
        "createaccountreason": "Шалтгаан:",
        "createacct-reason": "Шалтгаан",
        "createacct-reason-ph": "Өөр бүртгэл үүсгэх шалтгаан",
-       "createacct-captcha": "Аюулгүй байдлын хяналт",
-       "createacct-imgcaptcha-ph": "Дээр харагдаж буй бичвэрийг оруулна уу",
        "createacct-submit": "Бүртгүүлэх",
        "createacct-another-submit": "Өөр нэгэн хэрэглэгч бүртгэх",
        "createacct-benefit-heading": "{{SITENAME}}-г тан шиг хүмүүс хийж байна.",
        "passwordreset-emailtext-ip": "Хэн нэгэн ($1 гэсэн IP хаягаас) {{SITENAME}} ($4) дээр таны бүртгэлийн сануулга авахаар хүссэн байна. Дараах {{PLURAL:$3|бүртгэл|бүртгэл}}\nуг е-шуудантай холбоотой:\n\n$2\n\n{{PLURAL:$3|Уг түр хэрэглэх нууц үг|Уг түр хэрэглэх нууц үгүүд}} нь {{PLURAL:$5|нэг өдрийн|$5 өдрийн}} дотор устах болно.\nТа уг нууц үгээр нэвтэрч, түүнийг шинэчлэх хэрэгтэй. Хэрэв өөр нэгэн уг хүсэлтийг явуулсан бол \nэсвэл өөрийн ориг нууц үгээ санаж байгаад түүнийгээ өөрчлөхийг хүсэхгүй байгаа бол энэ захиаг үл ойшоож \nэнгийнээр нэвтэрч болно.",
        "passwordreset-emailtext-user": "{{SITENAME}} дээрх $1 хэрэглэгч {{SITENAME}} ($4) дээр өөрийн тань бүртгэл дээр сануулга хүссэн байна. \nДараах {{PLURAL:$3|бүртгэл|бүртгэлүүд}} уг е-шуудантай холбоотой байна:\n\n$2\n\nЭнэ {{PLURAL:$3|түр нууц үг|түр нууц үгс}} {{PLURAL:$5|нэг өдрийн дараа|$5 өдрийн дараа}} устах болно.\nТүүгээр нэвтэрч ороод нууц үгээ шинэчилнэ үү. Энэ сануулгыг өөр хэн нэгэн хийсэн, эсвэл та\nнууц үгээ санаж байгаа бол энэ захиаг анхааралгүйгээр хуучнаараа ороход болно.",
        "passwordreset-emailelement": "Хэрэглэгчийн нэр: \n$1\n\nТүр зуурын нууц үг: \n$2",
-       "passwordreset-emailsent": "Нууц үг солин емайл илгээсэн.",
+       "passwordreset-emailsentemail": "Нууц үг солин емайл илгээсэн.",
        "passwordreset-emailsent-capture": "Доор харагдаж байгаа нь танируу илгээсэн нууц үг ресет хийх емайл.",
        "passwordreset-emailerror-capture": "Доор харагдаж байгаа нууц үг ресет хийх емайл үүссэх боловч {{GENDER:$2|хэрэглэгчид}} илгээхэд алдаа гарлаа : $1",
        "changeemail": "Цахим шуудангийн хаяг солих",
-       "changeemail-text": "Энэ маягтийг бөглөж цахим шуудангийн хаягаа солино уу. Өөрчлөлт хийхийн тулд нууц үгээ оруулна уу.",
+       "changeemail-header": "Цахим шуудангийн бүртгэлийн хаяг солих",
        "changeemail-no-info": "Энэ хуудсыг үзэхэд хэрэглэгчийн нэрээр орсон байх шаардлагатай.",
        "changeemail-oldemail": "Одоогийн цахим шуудан:",
        "changeemail-newemail": "Шинэ цахим шуудангийн хаяг:",
        "prefs-diffs": "Ялгаанууд",
        "prefs-help-prefershttps": "Гараад орох уг тохиргоо идэвхижнэ.",
        "prefs-tabs-navigation-hint": "Зөвлөмж: Баруун зүүн сумаар таб хооронд шилжиж болно.",
-       "email-address-validity-valid": "Цахим шуудан хүчинтэй байна",
-       "email-address-validity-invalid": "и-майл хаягаа зөв оруулна уу.",
        "userrights": "Хэрэглэгчдийн эрхийн удирдлага",
        "userrights-lookup-user": "Хэрэглэгчдийн бүлгүүдийг удирдах",
        "userrights-user-editname": "Хэрэглэгчийн нэрээ оруулна уу:",
        "right-blockemail": "Хэрэглэгчийг мэйл явуулахаас түгжих",
        "right-hideuser": "Хэрэглэгчийн нэрийг түгжиж нийтээс нуух",
        "right-ipblock-exempt": "IP-н түгжээ, автомат түгжээ, бүсийн түгжээг тойрч гарах",
-       "right-proxyunbannable": "Проксинуудын автомат түгжээг тойрч гарах",
        "right-unblockself": "Өөрт хийсэн түгжээг тайлах",
        "right-protect": "Хамгаалалтын түвшингүүдийг өөрчилж хамгаалагдсан хуудсуудыг засварлах",
        "right-editprotected": "Хамгаалагдсан хуудсуудыг \"{{int:protect-level-sysop}}\" хэлбэрээр засварлах",
        "filewasdeleted": "Өмнө нь ийм нэртэй файл оруулагдсан бөгөөд дараа нь устгагдсан байна.\nТа үүнийг дахин оруулахын өмнө $1-г шалгаж үзнэ үү.",
        "filename-bad-prefix": "Таны оруулж байгаа файлын нэр '''\"$1\"'''-р эхэлж байна. Энэ нь файлыг тодорхойлойлоогүй, голдуу дижитал аппаратын автоматаар гаргадаг нэр болно.\nФайланд түүнийг илүү сайн тодорхойлсон нэр өгнө үү.",
        "filename-prefix-blacklist": " #<!-- leave this line exactly as it is --> <pre>\n# Syntax is as follows:\n#   * Everything from a \"#\" character to the end of the line is a comment\n#   * Every non-blank line is a prefix for typical filenames assigned automatically by digital cameras\nCIMG # Casio\nDSC_ # Nikon\nDSCF # Fuji\nDSCN # Nikon\nDUW # зарим гар утаснууд\nIMG # ерөнхий\nJD # Jenoptik\nMGP # Pentax\nPICT # бусад.\n #</pre> <!-- leave this line exactly as it is -->",
-       "upload-success-subj": "Файлыг амжилттай орууллаа",
-       "upload-success-msg": "[$2]-с амжилттай оруулав. Энд байна: [[:{{ns:file}}:$1]]",
-       "upload-failure-subj": "Оруулах үеийн асуудал",
-       "upload-failure-msg": "[$2]-с оруулахад асуудал үүсчээ:\n\n$1",
-       "upload-warning-subj": "Оруулах үеийн анхааруулга",
-       "upload-warning-msg": "[$2]-с хийсэн оруулалтад асуудал үүсэв. [[Special:Upload/stash/$1|Оруулах талбар]] руу буцаж энэ асуудлыг шийдвэрлэж болно.",
        "upload-proto-error": "Буруу протокол",
        "upload-proto-error-text": "Файл оруулахад хэрэгтэй URL-үүд нь <code>http://</code> эсвэл <code>ftp://</code>-р эхлэсэн байх шаардлагатай.",
        "upload-file-error": "Дотоод алдаа",
        "movenosubpage": "Энэ хуудас нь дэд хуудасгүй.",
        "movereason": "Шалтгаан:",
        "revertmove": "хуучин төлөвт шилжүүлэх",
-       "delete_and_move": "Устгаад зөөх",
        "delete_and_move_text": "==Устгалын шаардав==\nЗорьсон хуудас \"[[:$1]]\"-г нь урьд нь оруулсан байна.\nТа зөөхөд зай гаргахын тулд устгах уу?",
        "delete_and_move_confirm": "Тийм, хуудсыг устга",
        "delete_and_move_reason": "[[$1]] -с зөөхөд зай гаргахын тулд устгагдсан",
        "newimages-summary": "Энэ тусгай хуудсанд хамгийн сүүлд оруулагдсан файлуудыг үзүүлнэ.",
        "newimages-legend": "Шүүлтүүр",
        "newimages-label": "Файлын нэр (эсвэл түүний нэг хэсэг):",
+       "newimages-hidepatrolled": "Шалгасан файлуудыг нуух",
        "noimages": "Харах юмгүй.",
        "ilsubmit": "Хайлт",
        "bydate": "Огноогоор",
        "duration-millennia": "$1 {{PLURAL:$1|мянган|мянган}}",
        "expand_templates_input": "Оруулах бичиг:",
        "expand_templates_output": "Үр дүн",
-       "expand_templates_remove_comments": "Товч агуулгыг авч хаях"
+       "expand_templates_remove_comments": "Товч агуулгыг авч хаях",
+       "pagelanguage": "Хуудасны хэлийг өөрчлөх"
 }
index e0e6be6..f807b8d 100644 (file)
@@ -72,7 +72,8 @@
                        "M!dgard",
                        "Matma Rex",
                        "Robin van der Vliet",
-                       "Catrope"
+                       "Catrope",
+                       "Edoderoo"
                ]
        },
        "tog-underline": "Koppelingen onderstrepen:",
        "tog-enotifrevealaddr": "Mijn e-mailadres weergeven in e-mailberichten",
        "tog-shownumberswatching": "Het aantal gebruikers weergeven dat deze pagina volgt",
        "tog-oldsig": "Bestaande ondertekening:",
-       "tog-fancysig": "Als wikitekst behandelen (zonder automatische koppeling)",
+       "tog-fancysig": "Handtekening als wikitekst behandelen (zonder automatische koppeling)",
        "tog-uselivepreview": "Livevoorvertoning gebruiken",
        "tog-forceeditsummary": "Een melding geven bij een lege bewerkingssamenvatting",
        "tog-watchlisthideown": "Eigen bewerkingen op mijn volglijst verbergen",
        "databaseerror-query": "Zoekopdracht: $1",
        "databaseerror-function": "Functie: $1",
        "databaseerror-error": "Fout: $1",
+       "transaction-duration-limit-exceeded": "Deze transactie ($1) is afgebroken omdat de limiet van $2 {{PLURAL:$2|seconde|seconden}} is bereikt. Hiermee worden grote achterstanden bij het repliceren voorkomen. \nWanneer u meerdere items tegelijk bewerkt, probeer het dan in meerdere kleinere opdrachten te doen.",
        "laggedslavemode": "<strong>Waarschuwing:</strong> in deze pagina zijn recente wijzigingen mogelijk nog niet verwerkt.",
        "readonly": "Database geblokkeerd",
        "enterlockreason": "Geef een reden op voor de blokkade en geef op wanneer die waarschijnlijk wordt opgeheven",
        "missingarticle-rev": "(versienummer: $1)",
        "missingarticle-diff": "(Wijziging: $1, $2)",
        "readonly_lag": "De database is automatisch vergrendeld terwijl de ondergeschikte databaseservers synchroniseren met de hoofdserver.",
+       "nonwrite-api-promise-error": "De HTTP-header 'Promise-Non-Write-API-Action' was meegestuurd, maar het verzoek behelsde een API-schrijfverzoek.",
        "internalerror": "Interne fout",
        "internalerror_info": "Interne fout: $1",
        "internalerror-fatal-exception": "Fatale fout van type \"$1\"",
        "virus-scanfailed": "scannen is mislukt (code $1)",
        "virus-unknownscanner": "onbekend antivirusprogramma:",
        "logouttext": "<strong>U bent nu afgemeld.</strong>\n\nSommige pagina's kunnen blijven weergegeven alsof u nog aangemeld bent, totdat u uw browsercache leegt.",
-       "cannotlogoutnow-title": "Niet mogelijk om nu uit te loggen",
-       "cannotlogoutnow-text": "Uitloggen is niet mogelijk bij het gebruik van $1.",
+       "cannotlogoutnow-title": "Niet mogelijk om nu af te melden",
+       "cannotlogoutnow-text": "Afmelden is niet mogelijk bij het gebruik van $1.",
        "welcomeuser": "Welkom, $1!",
        "welcomecreation-msg": "Uw account is aangemaakt.\nIndien gewenst kunt u uw [[Special:Preferences|voorkeuren]] voor {{SITENAME}} aanpassen.",
        "yourname": "Gebruikersnaam:",
        "remembermypassword": "Aanmeldgegevens onthouden (maximaal $1 {{PLURAL:$1|dag|dagen}})",
        "userlogin-remembermypassword": "Aangemeld blijven",
        "userlogin-signwithsecure": "Beveiligde verbinding gebruiken",
-       "cannotloginnow-title": "Niet mogelijk om nu in te loggen",
-       "cannotloginnow-text": "Inloggen is niet mogelijk bij het gebruik van $1.",
+       "cannotloginnow-title": "Niet mogelijk om aan te melden",
+       "cannotloginnow-text": "Aanmelden is niet mogelijk bij het gebruik van $1.",
        "yourdomainname": "Uw domein:",
        "password-change-forbidden": "U kunt uw wachtwoord niet wijzigen in deze wiki.",
        "externaldberror": "Er is een fout opgetreden bij het aanmelden bij de database of u hebt geen toestemming uw externe gebruiker bij te werken.",
        "changepassword-success": "Uw wachtwoord is gewijzigd.",
        "changepassword-throttled": "U heeft recentelijk te veel mislukte aanmeldpogingen gedaan.\nWacht alstublieft $1 voordat u het opnieuw probeert.",
        "botpasswords": "Botwachtwoorden",
+       "botpasswords-summary": "<em>Botwachtwoorden</em> zorgen voor toegang tot de API via een gebruikersaccount zonder gebruik te maken van de aanmeldgegevens van dat account. De gebruikersrechten die beschikbaar zijn kunnen afwijken indien er aangemeld is met een botwachtwoord.\n\nAls u niet weet wat de gevolgen hiervan zijn, is het handiger om dit ook dan niet te doen. Niemand hoort u te vragen om een botwachtwoord aan te maken en deze vervolgens aan hem of haar te geven.",
        "botpasswords-disabled": "Botwachtwoorden zijn uitgeschakeld.",
        "botpasswords-no-central-id": "Om botwachtwoorden te gebruiken, moet u ingelogd zijn met een gecentraliseerd account",
        "botpasswords-existing": "Bestaande botwachtwoorden",
        "botpasswords-label-cancel": "Annuleren",
        "botpasswords-label-delete": "Verwijderen",
        "botpasswords-label-resetpassword": "Het wachtwoord opnieuw instellen",
+       "botpasswords-label-grants": "Van toepassing zijnde rechten:",
+       "botpasswords-help-grants": "Iedere toestemming geeft toegang tot de opgegeven gebruikersrechten die de gebruiker al heeft. Zie [[Special:ListGrants|overzicht van rechten]] voor meer informatie.",
        "botpasswords-label-restrictions": "Gebruiksbeperkingen:",
        "botpasswords-label-grants-column": "Toegewezen",
        "botpasswords-bad-appid": "De botnaam \"$1\" is niet geldig.",
        "botpasswords-updated-body": "Het botwachtwoord \"$1\" is succesvol bijgewerkt.",
        "botpasswords-deleted-title": "Botwachtwoord verwijderd",
        "botpasswords-deleted-body": "Het botwachtwoord \"$1\" is verwijderd.",
+       "botpasswords-newpassword": "Het nieuwe wachtwoord om aan te melden met <strong>$1</strong> is nu <strong>$2</strong>. <em>Bewaar dit goed voor toekomstig gebruik.</em>",
        "botpasswords-no-provider": "BotPasswordsSessionProvider is niet beschikbaar.",
-       "botpasswords-restriction-failed": "Botwachtwoord-beperkingen maken het aanmelden onmogelijk.",
+       "botpasswords-restriction-failed": "Botwachtwoordbeperkingen maken het aanmelden onmogelijk.",
+       "botpasswords-invalid-name": "De gebruikersnaam mag niet het scheidingsteken van het botwachtwoord (\"$1\") bevatten.",
        "botpasswords-not-exist": "Gebruiker \"$1\" heeft geen botwachtwoord genaamd \"$2\"",
        "resetpass_forbidden": "Wachtwoorden kunnen niet gewijzigd worden",
        "resetpass-no-info": "U dient aangemeld zijn voordat u deze pagina kunt gebruiken.",
        "accmailtext": "Een willekeurig gegenereerd wachtwoord voor [[User talk:$1|$1]] is verzonden naar $2. Het kan worden gewijzigd op de pagina \"[[Special:ChangePassword|wachtwoord wijzigen]]\" na het aanmelden.",
        "newarticle": "(Nieuw)",
        "newarticletext": "Deze pagina bestaat niet.\nTyp in het onderstaande veld om de pagina aan te maken (meer informatie staat op de [$1 hulppagina]).\nGebruik de knop <strong>Terug</strong> in uw browser als u hier per ongeluk terecht bent gekomen.",
-       "anontalkpagetext": "----''Deze overlegpagina hoort bij een anonieme gebruiker die geen gebruikersnaam heeft of deze niet gebruikt.\nDaarom wordt het IP-adres ter identificatie gebruikt.\nHet is mogelijk dat meerdere personen hetzelfde IP-adres gebruiken.\nMogelijk ontvangt u hier berichten die niet voor u bedoeld zijn.\nAls u dat wilt voorkomen, [[Special:UserLogin/signup|registreer u]] of [[Special:UserLogin|meld u aan]] om verwarring met andere anonieme gebruikers te voorkomen.''",
+       "anontalkpagetext": "----\n<em>Deze overlegpagina hoort bij een anonieme gebruiker die geen gebruikersnaam heeft of deze niet gebruikt.</em>\nDaarom wordt het IP-adres ter identificatie gebruikt.\nHet is mogelijk dat meerdere personen hetzelfde IP-adres gebruiken.\nMogelijk ontvangt u hier berichten die niet voor u bedoeld zijn.\nAls u dat wilt voorkomen, [[Special:UserLogin/signup|registreer u]] of [[Special:UserLogin|meld u aan]] om verwarring met andere anonieme gebruikers te voorkomen.",
        "noarticletext": "Deze pagina bevat geen tekst.\nU kunt [[Special:Search/{{PAGENAME}}|naar deze term zoeken]] in andere pagina's, <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} de logboeken doorzoeken] of [{{fullurl:{{FULLPAGENAME}}|action=edit}} deze pagina bewerken]</span>.",
        "noarticletext-nopermission": "Deze pagina bevat geen tekst.\nU kunt [[Special:Search/{{PAGENAME}}|naar deze term zoeken]] in andere pagina's of\n<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} de logboeken doorzoeken]</span>, maar u mag de pagina niet aanmaken.",
        "missing-revision": "De versie #$1 van de pagina \"{{FULLPAGENAME}}\" bestaat niet.\n\nDit wordt meestal veroorzaakt door het volgen van een verouderde koppeling naar een pagina die is verwijderd.\nMeer gegevens zijn mogelijk te vinden in het [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} verwijderingslogboek].",
        "prefs-info": "Basisinformatie",
        "prefs-i18n": "Taalinstellingen",
        "prefs-signature": "Ondertekening",
-       "prefs-dateformat": "Datumopmaak:",
+       "prefs-dateformat": "Datumopmaak",
        "prefs-timeoffset": "Tijdverschil",
        "prefs-advancedediting": "Algemene instellingen",
        "prefs-editor": "Tekstverwerker",
        "userrights": "Gebruikersrechtenbeheer",
        "userrights-lookup-user": "Gebruikersgroepen beheren",
        "userrights-user-editname": "Voer een gebruikersnaam in:",
-       "editusergroup": "{{GENDER:$1|Gebruiker}}sgroepen wijzigen",
+       "editusergroup": "{{GENDER:$1|Gebruikersgroepen}} wijzigen",
        "editinguser": "Bezig met wijzigen van de gebruikersrechten van gebruiker '''[[User:$1|$1]]''' $2",
        "userrights-editusergroup": "Gebruikersgroepen wijzigen",
-       "saveusergroups": "{{GENDER:$1|Gebruiker}}sgroepen opslaan",
+       "saveusergroups": "{{GENDER:$1|Gebruikersgroepen}} opslaan",
        "userrights-groupsmember": "Lid van:",
        "userrights-groupsmember-auto": "Impliciet lid van:",
        "userrights-groups-help": "U kunt de groepen wijzigen waar deze gebruiker lid van is.\n* Een aangekruist vakje betekent dat de gebruiker lid is van de groep.\n* Een niet aangekruist vakje betekent dat de gebruiker geen lid is van de groep.\n* Een \"*\" betekent dat u een gebruiker niet uit een groep kunt verwijderen nadat u die hebt toegevoegd of vice versa.",
        "right-createpage": "Pagina's aanmaken",
        "right-createtalk": "Overlegpagina's aanmaken",
        "right-createaccount": "Nieuwe gebruikers aanmaken",
-       "right-autocreateaccount": "Automatisch inloggen met een extern gebruikersaccount",
+       "right-autocreateaccount": "Automatisch aanmelden met een extern gebruikersaccount",
        "right-minoredit": "Bewerkingen als klein markeren",
        "right-move": "Pagina's hernoemen",
        "right-move-subpages": "Pagina's inclusief subpagina's verplaatsen",
        "grant-group-administration": "Beheerdershandelingen uitvoeren",
        "grant-group-other": "Diverse handelingen",
        "grant-blockusers": "Gebruikers (de)blokkeren",
-       "grant-createaccount": "Gebruikers aanmaken",
+       "grant-createaccount": "Accounts aanmaken",
        "grant-createeditmovepage": "Pagina's aanmaken, bewerken en hernoemen",
-       "grant-delete": "Pagina's, wijzigingen en vermeldingen in het logboek verwijderen",
+       "grant-delete": "Pagina's, wijzigingen en logboekregels verwijderen",
        "grant-editinterface": "De naamruimte MediaWiki en CSS en JavaScript van gebruikers bewerken",
-       "grant-editmycssjs": "Uw eigen CSS/JavaScript bewerken",
+       "grant-editmycssjs": "Eigen CSS en JavaScript bewerken",
        "grant-editmyoptions": "Eigen voorkeuren instellen",
-       "grant-editmywatchlist": "Uw eigen volglijst bewerken",
+       "grant-editmywatchlist": "Eigen volglijst bewerken",
        "grant-editpage": "Bestaande pagina's bewerken",
        "grant-editprotected": "Beveiligde pagina's bewerken",
        "grant-highvolume": "Veel bewerkingen in korte tijd maken",
        "grant-uploadfile": "Nieuwe bestanden uploaden",
        "grant-basic": "Basisrechten",
        "grant-viewdeleted": "Verwijderde bestanden en pagina's bekijken",
-       "grant-viewmywatchlist": "Uw volglijst bekijken",
+       "grant-viewmywatchlist": "Eigen volglijst bekijken",
        "newuserlogpage": "Logboek nieuwe gebruikers",
        "newuserlogpagetext": "Hieronder staan de nieuw ingeschreven gebruikers",
        "rightslog": "Gebruikersrechtenlogboek",
        "upload-too-many-redirects": "De URL bevatte te veel doorverwijzingen",
        "upload-http-error": "Er is een HTTP-fout opgetreden: $1",
        "upload-copy-upload-invalid-domain": "Uploaden per kopie is niet beschikbaar vanuit dit domein.",
+       "upload-foreign-cant-upload": "Deze wiki is niet geconfigureerd om bestanden te uploaden naar de buiten deze wiki geplaatste file repository.",
        "upload-dialog-title": "Bestand uploaden",
        "upload-dialog-button-cancel": "Annuleren",
        "upload-dialog-button-done": "Afgerond",
        "upload-form-label-infoform-name": "Naam",
        "upload-form-label-infoform-name-tooltip": "Een korte beschrijvende naam voor het bestand, die als de bestandsnaam wordt gebruikt. U kunt platte tekst met spaties gebruiken. Neem de bestandsextensie niet op.",
        "upload-form-label-infoform-description": "Beschrijving",
+       "upload-form-label-infoform-description-tooltip": "Beschrijf kort alles wat voor het werk van belang is.\nBenoem voor een afbeelding de belangrijkste zaken die zijn afgebeeld, alsmede de plaats of de gelegenheid.",
        "upload-form-label-usage-title": "Gebruik",
        "upload-form-label-usage-filename": "Bestandsnaam",
        "foreign-structured-upload-form-label-own-work": "Dit is mijn eigen werk",
        "wlshowlast": "Laatste $1 uur, $2 dagen bekijken",
        "watchlist-hide": "Verbergen",
        "watchlist-submit": "Weergeven",
-       "wlshowtime": "Periode om te weergeven:",
+       "wlshowtime": "Weer te geven periode:",
        "wlshowhideminor": "kleine bewerkingen",
        "wlshowhidebots": "bots",
        "wlshowhideliu": "geregistreerde gebruikers",
        "lockedbyandtime": "(door $1 om $3 op $2)",
        "move-page": "\"$1\" hernoemen",
        "move-page-legend": "Pagina hernoemen",
-       "movepagetext": "Door middel van het onderstaande formulier kunt u een pagina hernoemen.\nDe geschiedenis gaat mee naar de nieuwe pagina.\n* De oude naam wordt automatisch een doorverwijzing naar de nieuwe pagina.\n* Koppelingen naar de oude pagina worden niet aangepast.\n* De pagina's die doorverwijzen naar de oorspronkelijke paginanaam worden automatisch bijgewerkt.\nAls u dit niet wenst, controleer dan of er geen [[Special:DoubleRedirects|dubbele]] of [[Special:BrokenRedirects|onjuiste doorverwijzingen]] zijn ontstaan.\n\nEen pagina kan '''alleen''' hernoemd worden als de nieuwe paginanaam niet bestaat of een doorverwijspagina zonder verdere geschiedenis is.\n\n'''Waarschuwing!'''\nVoor veel bekeken pagina's kan het hernoemen drastische en onvoorziene gevolgen hebben.\nZorg ervoor dat u die gevolgen overziet voordat u deze handeling uitvoert.",
-       "movepagetext-noredirectfixer": "Door middel van het onderstaande formulier kunt u een pagina en alle bijbehorende oude versies hernoemen.\nDe oude naam wordt automatisch een doorverwijzing naar de nieuwe pagina.\nControleer dan of er geen [[Special:DoubleRedirects|dubbele]] of [[Special:BrokenRedirects|onjuiste doorverwijzingen]] zijn ontstaan.\n\nEen pagina kan '''alleen''' hernoemd worden als de nieuwe paginanaam niet bestaat of een doorverwijspagina zonder verdere geschiedenis is.\nU kunt dus een pagina die per ongeluk is hernoemd terug hernoemen en u kunt een bestaande pagina niet overschrijven. \n\n'''Waarschuwing!'''\nVoor veel bekeken pagina's kan het hernoemen drastische en onvoorziene gevolgen hebben.\nZorg ervoor dat u die gevolgen overziet voordat u deze handeling uitvoert.",
+       "movepagetext": "Door middel van het onderstaande formulier kunt u een pagina hernoemen.\nDe geschiedenis gaat mee naar de nieuwe pagina.\n* De oude naam wordt automatisch een doorverwijzing naar de nieuwe pagina.\n* Koppelingen naar de oude pagina worden niet aangepast.\n* De pagina's die doorverwijzen naar de oorspronkelijke paginanaam worden automatisch bijgewerkt.\nAls u dit niet wenst, controleer dan of er geen [[Special:DoubleRedirects|dubbele]] of [[Special:BrokenRedirects|onjuiste doorverwijzingen]] zijn ontstaan.\n\nEen pagina kan <strong>alleen</strong> hernoemd worden als de nieuwe paginanaam niet bestaat of een doorverwijspagina zonder verdere geschiedenis is.\n\n<strong>Opmerking:</strong>\nVoor veel bekeken pagina's kan het hernoemen drastische en onvoorziene gevolgen hebben.\nZorg ervoor dat u die gevolgen overziet voordat u deze handeling uitvoert.",
+       "movepagetext-noredirectfixer": "Door middel van het onderstaande formulier kunt u een pagina en alle bijbehorende oude versies hernoemen.\nDe oude naam wordt automatisch een doorverwijzing naar de nieuwe pagina.\nControleer dan of er geen [[Special:DoubleRedirects|dubbele]] of [[Special:BrokenRedirects|onjuiste doorverwijzingen]] zijn ontstaan.\n\nEen pagina kan <strong>alleen</strong> hernoemd worden als de nieuwe paginanaam niet bestaat of een doorverwijspagina zonder verdere geschiedenis is.\nU kunt dus een pagina die per ongeluk is hernoemd terug hernoemen en u kunt een bestaande pagina niet overschrijven. \n\n<strong>Opmerking:</strong>\nVoor veel bekeken pagina's kan het hernoemen drastische en onvoorziene gevolgen hebben.\nZorg ervoor dat u die gevolgen overziet voordat u deze handeling uitvoert.",
        "movepagetalktext": "Als u het onderstaande vinkje selecteert, krijgt de bijbehorende overlegpagina automatisch een andere naam, tenzij de overlegpagina onder de nieuwe naam al bestaat.\n\nIn dit geval moet u de pagina handmatig hernoemen of samenvoegen.",
        "moveuserpage-warning": "'''Waarschuwing:''' u gaat een gebruikerspagina hernoemen. Houd er rekening mee dat alleen de pagina wordt hernoemd, ''niet'' de gebruiker.",
        "movecategorypage-warning": "<strong>Waarschuwing:</strong> U staat op het punt een categoriepagina te hernoemen. Houdt u er rekening mee dat alleen de categoriepagina zelf hernoemd wordt; pagina's in de oude categorie worden <em>niet</em> automatisch naar de nieuwe verplaatst.",
        "version-libraries-license": "Licentie",
        "version-libraries-description": "Beschrijving",
        "version-libraries-authors": "Auteurs",
-       "redirect": "Doorverwijzen op bestandsnaam, gebruikersnummer, paginanummer, of versienummer",
+       "redirect": "Doorverwijzen op bestandsnaam, gebruikers-, pagina-, versie- of logboekregelnummer",
        "redirect-legend": "Doorverwijzen naar een bestand of pagina",
-       "redirect-summary": "Deze speciale pagina verwijst door naar een bestand (als een bestandsnaam wordt opgegeven), een pagina (als een paginanummer of versienummer wordt opgegeven) of een gebruikerspagina (als een gebruikersnummer wordt opgegeven). Gebruik: [[{{#Special:Redirect}}/file/Voorbeeld.jpg]], [[{{#Special:Redirect}}/page/64308]], [[{{#Special:Redirect}}/revision/328429]] of [[{{#Special:Redirect}}/user/101]].",
+       "redirect-summary": "Deze speciale pagina verwijst door naar een bestand (als een bestandsnaam wordt opgegeven), een pagina (als een paginanummer of versienummer wordt opgegeven), een gebruikerspagina (als een gebruikersnummer wordt opgegeven) of een logboekregel (als een logboekregel-ID wordt opgegeven). Gebruik: [[{{#Special:Redirect}}/file/Voorbeeld.jpg]], [[{{#Special:Redirect}}/page/64308]], [[{{#Special:Redirect}}/revision/328429]], [[{{#Special:Redirect}}/user/101]] of [[{{#Special:Redirect}}/logid/186]].",
        "redirect-submit": "OK",
        "redirect-lookup": "Opzoeken:",
        "redirect-value": "Waarde:",
        "redirect-page": "Pagina-ID",
        "redirect-revision": "Paginaversie",
        "redirect-file": "Bestandsnaam",
+       "redirect-logid": "Logboekregel-ID",
        "redirect-not-exists": "Waarde niet gevonden",
        "fileduplicatesearch": "Duplicaatbestanden zoeken",
        "fileduplicatesearch-summary": "Duplicaatbestanden zoeken op basis van de hashwaarde.",
        "logentry-suppress-block": "$1 {{GENDER:$2|heeft}} {{GENDER:$4|$3}} geblokkeerd voor de duur van $5 $6",
        "logentry-suppress-reblock": "$1 {{GENDER:$2|heeft}} de blokkade voor {{GENDER:$4|$3}} aangepast. Deze vervalt nu op $5 $6",
        "logentry-import-upload": "$1 {{GENDER:$2|heeft}} $3 geïmporteerd via een bestandsupload",
+       "logentry-import-upload-details": "$1 {{GENDER:$2|heeft}} $3 door middel van een bestandsupload geïmporteerd ($4 {{PLURAL:$4|versie|versies}})",
        "logentry-import-interwiki": "$1 {{GENDER:$2|heeft}} $3 geïmporteerd vanuit een andere wiki",
+       "logentry-import-interwiki-details": "$1 {{GENDER:$2|heeft}} $3 uit $5 geïmporteerd ($4 {{PLURAL:$4|versie|versies}})",
        "logentry-merge-merge": "$1 {{GENDER:$2|heeft}} $3 samengevoegd naar $4 (versies tot en met $5)",
        "logentry-move-move": "$1 {{GENDER:$2|heeft}} pagina $3 hernoemd naar $4",
        "logentry-move-move-noredirect": "$1 {{GENDER:$2|heeft}} de pagina $3 hernoemd naar $4 zonder een doorverwijzing achter te laten",
        "expand_templates_preview_fail_html": "<em>Omdat voor {{SITENAME}} ruwe HTML is ingeschakeld, en er sessiegegevens verloren zijn gegaan, is de voorvertoning verborgen als voorzorgmaatregel tegen JavaScriptaanvallen.</em>\n\n<strong>Als dit een legitieme poging is voor het weergeven van een voorvertoning, probeer het dan opnieuw.</strong>\nAls het dan nog steeds niet werkt, probeer dan [[Special:UserLogout|af te melden]] en opnieuw aan te melden.",
        "expand_templates_preview_fail_html_anon": "<em>Omdat in {{SITENAME}} ruwe HTML is ingeschakeld en u niet bent aangemeld, is de voorvertoning verborgen als voorzorgsmaatregel tegen de JavaScriptaanvallen.</em>\n\n<strong>Als dit een legitieme poging is voor het maken van een voorvertoning, [[Special:UserLogin|meld u dan aan]] en probeer het opnieuw.</strong>",
        "expand_templates_input_missing": "U moet wel iets invullen.",
-       "pagelanguage": "Paginataal kiezen",
+       "pagelanguage": "Paginataal wijzigen",
        "pagelang-name": "Pagina",
        "pagelang-language": "Taal",
        "pagelang-use-default": "Standaard taal gebruiken",
        "pagelang-select-lang": "Taal selecteren",
-       "pagelang-submit": "Verzenden",
+       "pagelang-submit": "Opslaan",
        "right-pagelang": "Paginataal wijzigen",
        "action-pagelang": "paginataal te wijzigen",
        "log-name-pagelang": "Logboek taalwijzigingen",
        "log-description-pagelang": "Dit is een logboek van wijzigingen van de taal van pagina's.",
-       "logentry-pagelang-pagelang": "$1 heeft de taal van de pagina \"$3\" gewijzigd van $4 naar $5.",
+       "logentry-pagelang-pagelang": "$1 heeft de paginataal van $3 {{GENDER:$2|gewijzigd}} van $4 naar $5",
        "default-skin-not-found": "Het standaard uiterlijk voor de wiki, dat is ingesteld in <code dir=\"ltr\">$wgDefaultSkin</code> as <code>$1</code>, is niet beschikbaar.\n\nUw installatie heeft {{PLURAL:$4|het volgende uiterlijk|de volgende uiterlijken}}. Zie [https://www.mediawiki.org/wiki/Manual:Skin_configuration Handboek: uiterlijk instellen] voor meer informatie over hoe u het uiterlijk instelt en een standaard uiterlijk aangeeft.\n\n$2\n\n; Als u MediaWiki zojuist hebt geïnstalleerd:\n: U hebt waarschijnlijk geïnstalleerd via git, or direct vanuit de broncode via een andere methode. Deze melding is verwacht. Installeer één of meer van de [https://www.mediawiki.org/wiki/Category:All_skins beschikbare uiterlijken op mediawiki.org], door:\n:* De [https://www.mediawiki.org/wiki/Download tarball te downloaden], die meerdere uiterlijken en uitbreidingen bevat. U kunt de map <code>skins/</code> daar uit kopiëren;\n:* Het downloaden van tarballs voor uiterlijken van [https://www.mediawiki.org/wiki/Special:SkinDistributor mediawiki.org];\n:* [https://www.mediawiki.org/wiki/Download_from_Git#Using_Git_to_download_MediaWiki_skins Git gebruiken voor het downloaden van uiterlijken].\n: Als u dit doet en u bent MediaWikiontwikkelaar, heeft dit geen invloed op uw gitrepository.\n\n; Als u MediaWiki net hebt bijgewerkt:\n: In MediaWiki 1.24 en nieuwere versies worden geïnstalleerde uiterlijken niet langer automatisch ingeschakeld (zie [https://www.mediawiki.org/wiki/Manual:Skin_autodiscovery Handboek: uiterlijken automatisch vinden]). U kunt de volgende {{PLURAL:$5|regel|regels}} kopieren naar <code>LocalSettings.php</code> om alle op dit moment geïnstalleerde uiterlijken in te schakelen:\n\n<pre dir=\"ltr\">$3</pre>\n\n; In het geval u zojuist <code>LocalSettings.php</code> hebt aangepast:\n: Controleer de namen van de uiterlijken op spelfouten.",
        "default-skin-not-found-no-skins": "Het standaard uiterlijk voor uw wiki, als aangegeven in <code>$wgDefaultSkin</code> als <code>$1</code>, is niet beschikbaar.\n\nU hebt geen geïnstalleerde uiterlijken.\n\n; Als u MediaWiki zojuist hebt geïnstalleerd:\n: U hebt waarschijnlijk geïnstalleerd via git, or direct vanuit de broncode via een andere methode. Deze melding is verwacht. Sinds MediaWiki 1.24 staan er geen skins meer in de hoofdrepository. Installeer één of meer van de [https://www.mediawiki.org/wiki/Category:All_skins beschikbare uiterlijken op mediawiki.org], door:\n:* De [https://www.mediawiki.org/wiki/Download tarball te downloaden], die meerdere uiterlijken en uitbreidingen bevat. U kunt de map <code>skins/</code> daar uit kopiëren;\n:* Het downloaden van tarballs voor uiterlijken van [https://www.mediawiki.org/wiki/Special:SkinDistributor mediawiki.org];\n:* [https://www.mediawiki.org/wiki/Download_from_Git#Using_Git_to_download_MediaWiki_skins Git gebruiken voor het downloaden van uiterlijken].\n: Als u dit doet en u bent MediaWikiontwikkelaar, heeft dit geen invloed op uw gitrepository. Zie [https://www.mediawiki.org/wiki/Manual:Skin_configuration Manual: Skinconfiguratie] voor meer informatie over hoe skins in te schakelen en een standaard te kiezen.",
        "default-skin-not-found-row-enabled": "* <code>$1</code> / $2 (ingeschakeld)",
        "mw-widgets-titleinput-description-new-page": "pagina bestaat nog niet",
        "mw-widgets-titleinput-description-redirect": "doorverwijzing naar $1",
        "api-error-blacklisted": "Kies een andere, beschrijvende naam.",
+       "sessionmanager-tie": "Het is niet mogelijk om meerdere authenticatietypen voor verzoeken te combineren: $1.",
        "sessionprovider-generic": "$1 sessies",
        "sessionprovider-mediawiki-session-cookiesessionprovider": "sessies gebaseerd op cookies",
        "sessionprovider-nocookies": "Cookies kunnen uitgeschakeld zijn. Zorg ervoor dat u cookies hebt ingeschakeld en probeer het opnieuw.",
index d214eec..26e87c0 100644 (file)
        "contributions": "{{GENDER:$1|Brukarbidrag}}",
        "contributions-title": "Bidrag av $1",
        "mycontris": "Bidrag",
+       "anoncontribs": "Bidrag",
        "contribsub2": "For {{GENDER:$3|$1}} ($2)",
        "nocontribs": "Det vart ikkje funne nokon endringar gjorde av denne brukaren.",
        "uctop": "(gjeldande)",
        "javascripttest-pagetext-frameworks": "Vel eitt av dei fylgjande utrøyningsrammeverka: $1",
        "javascripttest-pagetext-skins": "Vel ei drakt som utrøyningane skal køyrast med:",
        "javascripttest-qunit-intro": "Sjå [$1 utrøyningsdokumentasjon] på mediawiki.org.",
-       "tooltip-pt-userpage": "Brukarsida di",
+       "tooltip-pt-userpage": "{{GENDER:|Brukarsida}} di",
        "tooltip-pt-anonuserpage": "Brukarsida for ip-adressa du endrar under",
-       "tooltip-pt-mytalk": "Diskusjonssida di",
+       "tooltip-pt-mytalk": "{{GENDER:|Diskusjonssida}} di",
        "tooltip-pt-anontalk": "Diskusjon om endringar gjorde av denne ip-adressa",
-       "tooltip-pt-preferences": "Innstillingane dine",
+       "tooltip-pt-preferences": "{{GENDER:|Innstillingane}} dine",
        "tooltip-pt-watchlist": "Liste over sidene du overvakar.",
-       "tooltip-pt-mycontris": "Liste over bidraga dine",
+       "tooltip-pt-mycontris": "{{GENDER:|Liste}} over bidraga dine",
        "tooltip-pt-login": "Det er ikkje obligatorisk å logga inn, men medfører mange fordelar.",
        "tooltip-pt-logout": "Logg ut",
        "tooltip-pt-createaccount": "Me oppfordrar til at du oppretter ein konto og loggar inn, men det er ikkje påkravd.",
        "logentry-newusers-create2": "Brukarkontoen $3 vart {{GENDER:$2|oppretta}} av $1",
        "logentry-newusers-byemail": "Brukarkontoen $3 vart {{GENDER:$2|oppretta}} av $1 og passord vart sendt med e-post",
        "logentry-newusers-autocreate": "Brukarkontoen $1 vart {{GENDER:$2|oppretta}} av seg sjølv",
+       "logentry-protect-protect": "$1 {{GENDER:$2|verna}} $3 $4",
        "logentry-rights-rights": "$1 {{GENDER:$2|endra}} gruppemedlemskap for $3 frå $4 til $5",
        "logentry-rights-rights-legacy": "$1 {{GENDER:$2|endra}} gruppemedlemskap for $3",
        "logentry-rights-autopromote": "$1 vart automatisk {{GENDER:$2|forfremja}} frå $4 til $5",
index 114e694..cc18bde 100644 (file)
        "scarytranscludefailed-httpstatus": "[Pobranie szablonu dla $1 nie powiodło się: HTTP $2]",
        "scarytranscludetoolong": "[zbyt długi adres URL]",
        "deletedwhileediting": "'''Uwaga!''' Ta strona została usunięta po tym, jak rozpoczął{{GENDER:|eś|aś|eś(‐aś)}} jej edycję!",
-       "confirmrecreate": "{{GENDER:$1|Użytkownik|Użytkowniczka}} [[User:$1|$1]] ([[User talk:$1|dyskusja]]) {{GENDER:$1|usunął|usunęła}} tę stronę po tym, jak rozpocząłeś/rozpoczęłaś jego edycję, podając jako powód usunięcia:\n: <em>$2</em>\nPotwierdź, że na pewno chcesz odtworzyć tę stronę.",
-       "confirmrecreate-noreason": "{{GENDER:$1|Użytkownik|Użytkowniczka}} [[User:$1|$1]] ([[User talk:$1|dyskusja]]) {{GENDER:$1|usunął|usunęła}} tę stronę po tym, jak rozpocząłeś/rozpoczęłaś jego edycję. Potwierdź, że naprawdę chcesz odtworzyć tę stronę.",
+       "confirmrecreate": "{{GENDER:$1|Użytkownik|Użytkowniczka}} [[User:$1|$1]] ([[User talk:$1|dyskusja]]) {{GENDER:$1|usunął|usunęła}} tę stronę po tym, jak rozpocząłeś/rozpoczęłaś jej edycję, podając jako powód usunięcia:\n: <em>$2</em>\nPotwierdź, że na pewno chcesz odtworzyć tę stronę.",
+       "confirmrecreate-noreason": "{{GENDER:$1|Użytkownik|Użytkowniczka}} [[User:$1|$1]] ([[User talk:$1|dyskusja]]) {{GENDER:$1|usunął|usunęła}} tę stronę po tym, jak rozpocząłeś/rozpoczęłaś jej edycję. Potwierdź, że naprawdę chcesz odtworzyć tę stronę.",
        "recreate": "Utwórz powtórnie",
        "confirm_purge_button": "Wyczyść",
        "confirm-purge-top": "Wyczyścić pamięć podręczną dla tej strony?",
index 8a153dd..0c17172 100644 (file)
        "october-date": "$1 de outubro",
        "november-date": "$1 de novembro",
        "december-date": "$1 de dezembro",
+       "period-am": "AM",
+       "period-pm": "PM",
        "pagecategories": "{{PLURAL:$1|Categoria|Categorias}}",
        "category_header": "Páginas na categoria \"$1\"",
        "subcategories": "Subcategorias",
        "laggedslavemode": "'''Aviso:''' A página pode não conter as atualizações mais recentes.",
        "readonly": "Base de dados bloqueada (limitada a leituras)",
        "enterlockreason": "Introduza um motivo para bloquear, incluindo uma estimativa de quando será desbloqueada",
-       "readonlytext": "A base de dados está bloqueada para impedir a inserção e modificação de dados, provavelmente para uma manutenção de rotina, após a qual a situação será normalizada.\n\nO administrador que a bloqueou deu a seguinte explicação: $1",
+       "readonlytext": "A base de dados está atualmente bloqueada para novas entradas e outras modificações, provavelmente para uma manutenção de rotina, após a qual voltará à sua normalidade.\n\nO administrador que a bloqueou deu a seguinte explicação: $1",
        "missing-article": "A base de dados não encontrou o texto de uma página que deveria ter encontrado, com o nome \"$1\" $2.\n\nGeralmente, esta situação ocorre ao clicar numa ligação para diferenças desatualizada ou para o histórico de uma página que tenha sido removida.\n\nSe nenhuma destas situações se verifica, pode ter encontrado um defeito no programa.\nAnote a URL e reporte este incidente a um [[Special:ListUsers/sysop|administrador]], por favor.",
        "missingarticle-rev": "(revisão#: $1)",
        "missingarticle-diff": "(Dif.: $1, $2)",
        "mypreferencesprotected": "Não tem permissão para editar as suas preferências.",
        "ns-specialprotected": "Não é possível editar páginas especiais.",
        "titleprotected": "Este título foi protegido contra criação por [[User:$1|$1]].\nA justificação dada foi \"''$2''\".",
-       "filereadonlyerror": "Não é possível modificar o ficheiro \"$1\" porque o repositório de ficheiros \"$2\" está em modo de leitura.\n\nO administrador que efetuou o bloqueio deu a seguinte explicação: \"$3\".",
+       "filereadonlyerror": "Não é possível modificar o ficheiro \"$1\" porque o repositório de ficheiros \"$2\" está em modo de leitura.\n\nO administrador do sistema que efetuou o bloqueio deu a seguinte explicação: \"$3\".",
        "invalidtitle-knownnamespace": "Título inválido com o domínio \"$2\" e texto \"$3\"",
        "invalidtitle-unknownnamespace": "Título inválido com número de domínio $1 desconhecido e texto \"$2\"",
        "exception-nologin": "Não está autenticado",
        "virus-unknownscanner": "antivírus desconhecido:",
        "logouttext": "<strong>Já não está autenticado.</strong>\n\nTenha em atenção que algumas páginas poderão continuar a ser apresentadas como se ainda estivesse autenticado até limpar a ''cache'' do seu navegador.",
        "cannotlogoutnow-title": "Não é possível encerrar a sessão agora",
+       "cannotlogoutnow-text": "Não pode encerrar a sessão quando utilizar $1.",
        "welcomeuser": "Bem-vindo, $1!",
        "welcomecreation-msg": "A sua conta foi criada.\nNão se esqueça de personalizar as suas [[Special:Preferences|preferências]].",
        "yourname": "Nome de utilizador(a):",
        "userlogin-remembermypassword": "Manter-me autenticado",
        "userlogin-signwithsecure": "Usar uma ligação segura",
        "cannotloginnow-title": "Não é possível iniciar sessão agora",
+       "cannotloginnow-text": "Não pode iniciar a sessão quando utilizar $1.",
        "yourdomainname": "O seu domínio:",
        "password-change-forbidden": "Não pode alterar palavras-passe nesta wiki.",
        "externaldberror": "Ocorreu um erro externo à base de dados durante a autenticação ou não lhe é permitido atualizar a sua conta externa.",
        "changepassword-success": "A sua palavra-passe foi alterada!",
        "changepassword-throttled": "Realizou demasiadas tentativas de início de sessão com esta conta.\nAguarde $1 antes de tentar novamente, por favor.",
        "botpasswords": "Palavras-passe de robô",
+       "botpasswords-summary": "As <em>palavras-passe de robô</em> permitem o acesso a uma conta de utilizador através da API sem utilizar as principais credenciais de login da conta. Os direitos de um utilizador, ao iniciar sessão com uma palavra-passe de robô, podem estar limitados.\n\nSe não sabe o que o leva a fazer isso, provavelmente não deveria fazê-lo. Ninguém deve solicitar que gere uma destas palavras-passe e a entregue.",
+       "botpasswords-disabled": "As palavras-passe de robô estão desactivadas.",
+       "botpasswords-no-central-id": "Para utilizar palavras-passe de robô, deve iniciar sessão com uma conta centralizada.",
+       "botpasswords-existing": "Palavras-passe de robô existentes",
        "botpasswords-createnew": "Criar uma nova palavra-passe para robô",
+       "botpasswords-editexisting": "Editar uma palavra-passe de robô existente",
        "botpasswords-label-appid": "Nome do robô:",
        "botpasswords-label-create": "Criar",
        "botpasswords-label-update": "Atualizar",
        "botpasswords-label-cancel": "Cancelar",
        "botpasswords-label-delete": "Eliminar",
        "botpasswords-label-resetpassword": "Redefinir palavra-passe",
+       "botpasswords-label-grants": "Permissões aplicáveis:",
        "botpasswords-label-restrictions": "Restrições de uso:",
+       "botpasswords-label-grants-column": "Concedido",
+       "botpasswords-bad-appid": "O nome do robô \"$1\" não é válido.",
+       "botpasswords-insert-failed": "Falhou ao adicionar o nome do robô \"$1\". Já foi adicionado?",
        "botpasswords-update-failed": "Falha ao atualizar o nome do robô \"$1\". Será que foi eliminado?",
        "botpasswords-created-title": "Criada palavra-passe para o robô",
        "botpasswords-created-body": "A palavra-passe para o robô \"$1\" foi criada com sucesso.",
+       "botpasswords-updated-title": "A palavra-passe de robô foi actualizada.",
+       "botpasswords-updated-body": "A palavra-passe de robô \"$1\" foi actualizada com sucesso.",
+       "botpasswords-deleted-title": "Palavra-passe de robô eliminada",
+       "botpasswords-deleted-body": "A palavra-passe de robô \"$1\" foi eliminada.",
        "botpasswords-newpassword": "A nova palavra-passe para iniciar sessão com <strong>$1</strong> é <strong>$2</strong>. Por favor, recorde-se dela para futura referência.</em>",
+       "botpasswords-no-provider": "BotPasswordsSessionProvider não está disponível.",
        "resetpass_forbidden": "Não é possível alterar palavras-passe",
        "resetpass-no-info": "Precisa de iniciar sessão para aceder diretamente a esta página.",
        "resetpass-submit-loggedin": "Alterar palavra-passe",
        "right-changetags": "Adicionar ou remover [[Special:Tags|etiquetas]] arbitrárias em revisões e entradas de registo individuais",
        "grant-generic": "Pacote de direitos \"$1\"",
        "grant-group-page-interaction": "Interagir com páginas",
-       "grant-group-file-interaction": "Interagir com multimédia",
+       "grant-group-file-interaction": "Interagir com conteúdo multimédia",
        "grant-group-watchlist-interaction": "Interagir com a sua lista de vigiados",
        "grant-group-email": "Enviar correio electrónico",
        "grant-group-high-volume": "Realizar actividades em grande quantidade",
        "action-createpage": "criar páginas",
        "action-createtalk": "criar páginas de discussão",
        "action-createaccount": "criar esta conta de utilizador",
+       "action-autocreateaccount": "criar automaticamente esta conta de utilizador externa",
        "action-history": "ver histórico desta página",
        "action-minoredit": "marcar esta edição como uma edição menor",
        "action-move": "mover esta página",
        "upload-form-label-infoform-description": "Descrição",
        "upload-form-label-usage-title": "Uso",
        "upload-form-label-usage-filename": "Nome do ficheiro",
+       "foreign-structured-upload-form-label-own-work": "Este é minha obra própria",
        "foreign-structured-upload-form-label-infoform-categories": "Categorias",
        "foreign-structured-upload-form-label-infoform-date": "Data",
        "foreign-structured-upload-form-label-own-work-message-local": "Confirmo que estou a carregar este ficheiro segundo as condições de serviço e política de licenças de {{SITENAME}}.",
+       "foreign-structured-upload-form-label-not-own-work-message-local": "Se não é capaz de carregar este ficheiro sob as políticas de {{SITENAME}}, por favor feche esta janela e tente outro método.",
        "foreign-structured-upload-form-label-not-own-work-local-local": "Poderá querer experimentar [[Special:Upload|a página padrão de carregamento]].",
+       "foreign-structured-upload-form-label-own-work-message-default": "Entendo que estou a carregar este ficheiro em um repositório partilhado. Confirmo que estou a fazê-lo cumprindo com os termos de serviço e com as políticas de licenciamento dali.",
+       "foreign-structured-upload-form-label-not-own-work-message-default": "Se não é capaz de carregar este ficheiro sob as políticas do repositório partilhado, por favor feche esta janela e tente outro método.",
+       "foreign-structured-upload-form-label-not-own-work-local-default": "Pode querer tentar utilizar [[Special:Upload|a página de carregamento em {{SITENAME}}]], se este ficheiro puder ser carregado de acordo com suas políticas.",
+       "foreign-structured-upload-form-label-own-work-message-shared": "Confirmo que sou o proprietário dos direitos autorais deste ficheiro, e aceito liberar irrevogavelmente este ficheiro para o Wikimedia Commons nos termos da licença [https://creativecommons.org/licenses/by-sa/4.0/ Creative Commons Atribuição-CompartilhaIgual 4.0], e concordo com os [https://wikimediafoundation.org/wiki/Terms_of_Use Termos de Utilização].",
+       "foreign-structured-upload-form-label-not-own-work-message-shared": "Se não é o proprietário dos direitos autorais deste ficheiro, ou caso deseje liberá-lo sob uma licença diferente, considere utilizar o [https://commons.wikimedia.org/wiki/Special:UploadWizard Assistente de Envio de Ficheiros do Commons].",
+       "foreign-structured-upload-form-label-not-own-work-local-shared": "Pode querer tentar utilizar [[Special:Upload|a página de carregamento em {{SITENAME}}]], se o sítio aceitar o carregamento deste ficheiro de acordo com suas políticas.",
        "foreign-structured-upload-form-2-label-intro": "Obrigado por doar uma imagem para utilização em {{SITENAME}}. Deverá continuar apenas se cumprir algumas condições:",
+       "foreign-structured-upload-form-2-label-ownwork": "Deve ser inteiramente <strong>sua obra própria</strong>, não apenas retirada da Internet",
+       "foreign-structured-upload-form-2-label-noderiv": "Não pode conter <strong>nenhuma obra de qualquer outra pessoa</strong>, ou inspirado por elas",
+       "foreign-structured-upload-form-2-label-useful": "Deve ser <strong>educativo e útil</strong> para ensinar a outros",
+       "foreign-structured-upload-form-2-label-ccbysa": "Deve estar <strong>aceito para publicar para sempre</strong> na Internet nos termos da licença [https://creativecommons.org/licenses/by-sa/4.0/ Creative Commons Atribuição-CompartilhaIgual 4.0]",
+       "foreign-structured-upload-form-2-label-alternative": "Caso nenhum dos itens acima for o correcto, ainda pode ser capaz de carregar este ficheiro ao utilizar o [https://commons.wikimedia.org/wiki/Special:UploadWizard Assistente para Envio de Ficheiros do Commons], desde que esteja disponível sob uma licença livre.",
        "foreign-structured-upload-form-3-label-yes": "Sim",
        "foreign-structured-upload-form-3-label-no": "Não",
        "foreign-structured-upload-form-4-label-bad": "Não pode carregar imagens encontradas num motor de busca ou descarregadas de outros sítios.",
        "wlshowtime": "Período de tempo a mostrar:",
        "wlshowhideminor": "edições menores",
        "wlshowhidebots": "robôs",
-       "wlshowhideliu": "usuários registrados",
-       "wlshowhideanons": "usuários anônimos",
+       "wlshowhideliu": "utilizadores registados",
+       "wlshowhideanons": "utilizadores anónimos",
        "wlshowhidepatr": "edições patrulhadas",
        "wlshowhidemine": "minhas edições",
        "wlshowhidecategorization": "categorização de páginas",
index 61aaeaa..e619964 100644 (file)
        "version-hook-subscribedby": "Shown in [[Special:Version]]",
        "version-version": "{{Optional}}\nUsed in [[Special:Version]]. Preceded by the MediaWiki extension name.\n\nParameters:\n* $1 - version number of the extension",
        "version-no-ext-name": "Used in [[Special:Version]], in the rows of the main table when a name for an extension is not provided.",
-       "version-svn-revision": "{{Identical|Revision}}{{optional}}\nUsed in [[Special:Version]], preceeding the Subversion revision numbers of the extensions loaded inside brackets, like this: \"({{int:version-revision}} r012345\"). Parameters:\n* $1 - (Unused) directory revision number or empty string\n* $2 - checkout revision number",
        "version-license": "Used specifically for the MediaWiki software.\n\nUsed as heading in [[Special:Version]].",
        "version-ext-license": "Used in [[Special:Version]].\n\nUsed as label for the link pointing to the extension's license page. e.g. [[Special:Version/License/Maps]]\n{{Identical|License}}",
        "version-ext-colheader-name": "Column header for the name of an extension.\n{{Identical|Extension}}",
        "version-libraries-license": "Column header for the library's license\n{{Identical|License}}",
        "version-libraries-description": "Column header for the library's description\n{{Identical|Description}}",
        "version-libraries-authors": "Column header for the library's authors\n{{Identical|Author}}",
-       "redirect": "{{doc-special|Redirect}}\nThis means \"Redirect by file'''name''', user '''ID''', page '''ID''', or revision ID\".",
+       "redirect": "{{doc-special|Redirect}}\nThis means \"Redirect by file '''name''', user '''ID''', page '''ID''', or revision ID\".",
        "redirect-legend": "Legend of fieldset around input box in [[Special:Redirect]]",
        "redirect-text": "Inside fieldset for [[Special:Redirect]]",
        "redirect-summary": "Shown at top of [[Special:Redirect]]",
index 71979dd..6f0cdc2 100644 (file)
        "botpasswords": "Parole roboți",
        "botpasswords-summary": "<em>Parolele de roboți</em> permit accesul la un cont de utilizator prin intermediul API-ului fără utilizarea identificatorilor de conectare principali ai contului. Este posibil ca drepturile de utilizator disponibile după conectarea cu parole de roboți să fie restricționate.\n\nDacă nu știți exact de ce ați recurge la această metodă, probabil ar trebui să nu o faceți. Nimeni nu ar trebui să vă ceară vreodată să generați acest tip de parolă și să le-o furnizați.",
        "botpasswords-disabled": "Parolele de roboți sunt dezactivate.",
+       "botpasswords-existing": "Parole de robot existente",
+       "botpasswords-label-restrictions": "Restricții de utilizare:",
        "resetpass_forbidden": "Parolele nu pot fi schimbate.",
        "resetpass-no-info": "Trebuie să fiți autentificat pentru a accesa această pagină direct.",
        "resetpass-submit-loggedin": "Modifică parola",
        "userrights": "Administrare permisiuni de utilizator",
        "userrights-lookup-user": "Administrare grupuri de utilizatori",
        "userrights-user-editname": "Introduceți un nume de utilizator:",
-       "editusergroup": "Modificare grup de utilizatori",
+       "editusergroup": "Modificare grup de {{GENDER:$1|utilizatori}}",
        "editinguser": "Modificarea permisiunilor de {{GENDER:$1|utilizator}} pentru <strong>[[User:$1|$1]]</strong> $2",
        "userrights-editusergroup": "Modificare grup de utilizatori",
-       "saveusergroups": "Salvează grupul de utilizatori",
+       "saveusergroups": "Salvează grupul de {{GENDER:$1|utilizatori}}",
        "userrights-groupsmember": "Membru al:",
        "userrights-groupsmember-auto": "Membru, implicit, al:",
        "userrights-groups-help": "Puteți schimba grupul căruia îi aparține utilizatorul:\n*Căsuța bifată înseamnă că utilizatorul aparține grupului respectiv.\n*Căsuța nebifată înseamnă că utilizatorul nu aparține grupului respectiv.\n*Steluța (*) indică faptul că utilizatorul nu poate fi eliminat din grup odată adăugat, sau invers.",
        "right-managechangetags": "Creează și șterge [[Special:Tags|etichete]] din baza de date",
        "right-applychangetags": "Aplică [[Special:Tags|etichete]] asociate modificărilor unui utilizator",
        "right-changetags": "Adaugă și înlătură [[Special:Tags|etichete]] arbitrare din versiuni și intrări de jurnal individuale",
+       "grant-basic": "Drepturi de bază",
        "newuserlogpage": "Jurnal utilizatori noi",
        "newuserlogpagetext": "Acesta este jurnalul creărilor conturilor de utilizator.",
        "rightslog": "Jurnal permisiuni de utilizator",
        "log-title-wildcard": "Caută titluri care încep cu acest text",
        "showhideselectedlogentries": "Arată/ascunde intrările selectate din jurnal",
        "log-edit-tags": "Modifică etichetele intrărilor de jurnal selectate",
+       "checkbox-select": "Selectare: $1",
+       "checkbox-all": "Toate",
+       "checkbox-none": "Niciuna",
+       "checkbox-invert": "Inversează",
        "allpages": "Toate paginile",
        "nextpage": "Pagina următoare ($1)",
        "prevpage": "Pagina anterioară ($1)",
        "listgrouprights-namespaceprotection-header": "Restricții de spațiu de nume",
        "listgrouprights-namespaceprotection-namespace": "Spațiu de nume",
        "listgrouprights-namespaceprotection-restrictedto": "Drept(uri) care permit(e) utilizatorului modificări",
+       "listgrants": "Permisiuni",
+       "listgrants-grant": "Permisiune",
+       "listgrants-rights": "Drepturi",
        "trackingcategories": "Categorii de urmărire",
        "trackingcategories-summary": "Această pagină conține categorii de urmărire care sunt populate în mod automat de către software-ul MediaWiki. Numele acestora se poate schimba modificând mesajele de sistem relevante din spațiul de nume {{ns:8}}.",
        "trackingcategories-msg": "Categorie de urmărire",
        "wlheader-showupdated": "Paginile care au fost modificate după ultima dumneavoastră vizită sunt afișate '''îngroșat'''.",
        "wlnote": "Mai jos se află {{PLURAL:$1|ultima schimbare|ultimele <strong>$1</strong> schimbări|ultimele <strong>$1</strong> de schimbări}} din {{PLURAL:$2|ultima oră|ultimele <strong>$2</strong> ore|ultimele <strong>$2</strong> de ore}}, așa cum era situația la $3, $4.",
        "wlshowlast": "Arată ultimele $1 ore $2 zile",
-       "watchlistall2": "toate",
        "watchlist-hide": "Ascunde",
        "watchlist-submit": "Afișează",
        "wlshowtime": "Perioada de timp de afișat:",
        "block-log-flags-hiddenname": "nume de utilizator ascuns",
        "range_block_disabled": "Abilitatea dezvoltatorilor de a bloca serii de adrese este dezactivată.",
        "ipb_expiry_invalid": "Dată de expirare invalidă.",
+       "ipb_expiry_old": "Timpul de expirare este din trecut.",
        "ipb_expiry_temp": "Blocarea numelor de utilizator ascunse trebuie să fie permanentă.",
        "ipb_hide_invalid": "Imposibil de suprimat acest cont; acesta are mai mult de {{PLURAL:$1|o modificare|$1 modificări|$1 de modificări}}.",
        "ipb_already_blocked": "„$1” este deja blocat",
        "movenosubpage": "Această pagină nu are subpagini.",
        "movereason": "Motiv:",
        "revertmove": "revenire",
-       "delete_and_move_text": "==Ștergere necesară==\n\nPagina destinație „[[:$1]]” există deja. Doriți să o ștergeți pentru a face loc redenumirii?",
+       "delete_and_move_text": "Pagina destinație „[[:$1]]” există deja. Doriți să o ștergeți pentru a face loc redenumirii?",
        "delete_and_move_confirm": "Da, șterge pagina.",
        "delete_and_move_reason": "Șters pentru a face loc redenumirii paginii „[[$1]]”",
        "selfmove": "Titlul sursei și al destinației este aceleași; nu puteți redenumi o pagină peste ea însăși.",
        "move-leave-redirect": "Lasă în urmă o redirecționare",
        "protectedpagemovewarning": "'''Atenție:''' această pagină a fost protejată astfel încât poate fi redenumită doar de către administratori.\nUltima intrare în jurnal este afișată mai jos pentru referință:",
        "semiprotectedpagemovewarning": "'''Observație: această pagină a fost protejată, putând fi redenumiră doar de către utilizatorii înregistrați.'''\nUltima intrare în jurnal este afișată mai jos pentru referință:",
-       "move-over-sharedrepo": "== Fișierul există ==\n[[:$1]] există deja într-un depozit partajat. Redenumirea fișierului la acest titlu va suprascrie fișierul partajat și îl va face inaccesibil.",
+       "move-over-sharedrepo": "[[:$1]] există deja într-un depozit partajat. Redenumirea fișierului la acest titlu va suprascrie fișierul partajat și îl va face inaccesibil.",
        "file-exists-sharedrepo": "Numele ales al fișierului este deja în utilizare într-un depozit împărțit.\nAlegeți un alt nume.",
        "export": "Exportare pagini",
        "exporttext": "Puteți exporta textul și istoricul unei pagini anume sau ale unui grup de pagini în XML.\nAcesta poate fi apoi importate în alt wiki care rulează software MediaWiki prin [[Special:Import|pagina de importare]].\n\nPentru a exporta, introduceți titlurile în căsuța de mai jos, unul pe linie, și alegeți dacă doriți să exportați doar această versiune sau și cele mai vechi, cu istoricul lor, sau versiunea curentă cu informații despre ultima modificare.\n\nÎn al doilea caz puteți folosi o legătură, de exemplu [[{{#Special:Export}}/{{MediaWiki:Mainpage}}]] pentru pagina „[[{{MediaWiki:Mainpage}}]]”.",
        "siteuser": "Utilizator {{SITENAME}} $1",
        "anonuser": "utlizator anonim $1 al {{SITENAME}}",
        "lastmodifiedatby": "Pagina a fost modificată pe $1, la $2 de către $3.",
-       "othercontribs": "Bazat pe munca lui $1.",
+       "othercontribs": "Bazat pe munca următorilor: $1.",
        "others": "alții",
-       "siteusers": "{{PLURAL:$2|Utilizator|Utilizatori}} {{SITENAME}} $1",
+       "siteusers": "{{PLURAL:$2|utilizator|utilizatori}} de la {{SITENAME}} $1",
        "anonusers": "{{PLURAL:$2|utilizator anonim|utilizatori anonimi}} $1 {{PLURAL:$2|al|ai}} {{SITENAME}}",
        "creditspage": "Credențiale",
        "nocredits": "Nu există credențiale disponibile pentru această pagină.",
        "pageinfo-category-files": "Număr de fișiere",
        "markaspatrolleddiff": "Marchează pagina ca verificată",
        "markaspatrolledtext": "Marchează această pagină ca verificată",
+       "markaspatrolledtext-file": "Marchează această versiune a fișierului ca verificată",
        "markedaspatrolled": "Pagină nouă verificată",
        "markedaspatrolledtext": "Versiunea selectată a paginii [[:$1]] a fost marcată ca verificată.",
        "rcpatroldisabled": "Opțiunea de verificare a modificărilor recente este dezactivată",
        "newimages-legend": "Filtru",
        "newimages-label": "Numele fișierului (sau parte din el):",
        "newimages-showbots": "Arată încărcările roboților",
+       "newimages-hidepatrolled": "Ascunde încărcările patrulate",
        "noimages": "Nimic de văzut.",
        "ilsubmit": "Caută",
        "bydate": "după dată",
        "scarytranscludefailed-httpstatus": "[Șiretlicul formatului a dat greș pentru $1: HTTP $2]",
        "scarytranscludetoolong": "[URL-ul este prea lung]",
        "deletedwhileediting": "'''Atenție''': Această pagină a fost ștearsă după ce ați început s-o modificați!",
-       "confirmrecreate": "Utilizatorul [[User:$1|$1]] ([[User talk:$1|discuție]]) a șters acest articol după ce ați început să contribuiți la el din motivul:\n: ''$2''\nVă rugăm să confirmați faptul că într-adevăr doriți să recreați acest articol.",
-       "confirmrecreate-noreason": "Utilizatorul [[User:$1|$1]] ([[User talk:$1|discuție]]) a șters această pagină după ce dumneavoastră ați început să o modificați. Vă rugăm să confirmați faptul că într-adevăr doriți să recreați această pagină.",
+       "confirmrecreate": "Utilizatorul [[User:$1|$1]] ([[User talk:$1|discuție]]) {{GENDER:$1|a șters}} acest articol după ce ați început să contribuiți la el din motivul:\n: <em>$2</em>\nVă rugăm să confirmați faptul că într-adevăr doriți să recreați acest articol.",
+       "confirmrecreate-noreason": "Utilizatorul [[User:$1|$1]] ([[User talk:$1|discuție]]) {{GENDER:$1|a șters}} această pagină după ce dumneavoastră ați început să o modificați. Vă rugăm să confirmați faptul că într-adevăr doriți să recreați această pagină.",
        "recreate": "Recreează",
        "confirm_purge_button": "OK",
        "confirm-purge-top": "Doriți să reîncărcați pagina?",
        "version-libraries-license": "Licență",
        "version-libraries-description": "Descriere",
        "version-libraries-authors": "Autori",
-       "redirect": "Redirecționare după fișier, utilizator, ID-ul paginii sau al versiunii",
+       "redirect": "Redirecționare după fișier, utilizator, ID-ul paginii, al versiunii sau al jurnalului",
        "redirect-legend": "Redirecționare către un fișier sau o pagină",
        "redirect-summary": "Această pagină specială vă redirecționează către un fișier (dat fiind un nume de fișier), o pagină (dat fiind ID-ul unei versiuni sau ID-ul unei pagini) sau o pagină de utilizator (dat fiind un ID numeric al utilizatorului). Utilizare: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/page/64308]], [[{{#Special:Redirect}}/revision/328429]] sau [[{{#Special:Redirect}}/user/101]].",
        "redirect-submit": "Du-te",
        "redirect-page": "ID pagină",
        "redirect-revision": "Versiune de pagină",
        "redirect-file": "Nume de fișier",
+       "redirect-logid": "ID jurnal",
        "redirect-not-exists": "Valoarea nu a fot găsită",
        "fileduplicatesearch": "Căutare fișiere duplicate",
        "fileduplicatesearch-summary": "Căutarea fișierelor duplicate bazată pe valorile hash.",
        "expand_templates_preview_fail_html": "<em>Întrucât la {{SITENAME}} este activat HTML brut și a avut loc o pierdere a sesiunii de date, previzualizarea a fost ascunsă ca măsură de precauție împotriva atacurilor prin JavaScript.</em>\n\n<strong>Dacă aceasta este o încercare legitimă de a previzualiza, încercați din nou.</strong>\nDacă nici astfel nu funcționează, încercați să [[Special:UserLogout|închideţi sesiunea]] şi să vă autentificaţi din nou.",
        "expand_templates_preview_fail_html_anon": "<em>Întrucât la {{SITENAME}} este activat HTML brut și nu v-ați autentificat, previzualizarea a fost ascunsă ca măsură de precauție împotriva atacurilor prin JavaScript.</em>\n\n<strong>Dacă aceasta este o încercare legitimă de a previzualiza, [[Special:UserLogin|autentificați-vă]] și încercați din nou.</strong>",
        "expand_templates_input_missing": "Trebuie să furnizați cel puțin un text ca date de intrare.",
-       "pagelanguage": "Selector limbă pagină",
+       "pagelanguage": "Modificare limbă pagină",
        "pagelang-name": "Pagină",
        "pagelang-language": "Limbă",
        "pagelang-use-default": "Folosește limba implicită",
        "action-pagelang": "modificați limba paginii",
        "log-name-pagelang": "Jurnal modificare limbă",
        "log-description-pagelang": "Acesta este un jurnal cu modificări ale limbii paginilor.",
-       "logentry-pagelang-pagelang": "$1 {{GENDER:$2|a modificat}} limba paginii pentru $3 din $4 în $5.",
+       "logentry-pagelang-pagelang": "$1 {{GENDER:$2|a schimbat}} limba pentru $3 din $4 în $5.",
        "default-skin-not-found": "Ups! Aspectul standard pentru wiki, definit în <code dir=\"ltr\">$wgDefaultSkin</code> ca <code>$1</code>, nu este disponibil.\n\nInstalarea dumneavoastră pare să includă {{PLURAL:$4|următorul aspect|următoarele aspecte}}. Vedeți [https://www.mediawiki.org/wiki/Manual:Skin_configuration Manual:Configurare aspecte] pentru informații despre cum {{PLURAL:$4|îl|le}} puteți activa și alege pe cel implicit.\n\n$2\n\n; Dacă tocmai ați instalat MediaWiki:\n: Probabil ați instalat folosind git sau direct din codul sursă print-o altă metodă. Acest lucru este normal. Încercați să instalați câteva aspecte din [https://www.mediawiki.org/wiki/Category:All_skins colecția de aspecte de la mediawiki.org]:\n:* Descărcând [https://www.mediawiki.org/wiki/Download instalatorul tarball], care este însoțit de câteva aspecte și extensii. Puteți copia directorul <code>skins/</code> din acesta.\n:* Descărcând arhive tar individuale cu aspecte de la [https://www.mediawiki.org/wiki/Special:SkinDistributor mediawiki.org].\n:* [https://www.mediawiki.org/wiki/Download_from_Git#Using_Git_to_download_MediaWiki_skins Utilizând Git pentru a descărca aspecte].\n: Această operațiune nu ar trebui să interfereze cu depozitul dumnevoastră git dacă sunteți dezvoltator MediaWiki.\n\n; Dacă tocmai ați actualizat MediaWiki:\n: Începând cu MediaWiki 1.24, aspectele instalate nu mai sunt activate în mod automat (vedeți [https://www.mediawiki.org/wiki/Manual:Skin_autodiscovery Manual:Autodescoperirea aspectelor]). Puteți copia {{PLURAL:$5|următoarea linie|următoarele linii}} în <code>LocalSettings.php</code> pentru a activa {{PLURAL:$5|aspectul instalat|toate aspectele instalate}}:\n\n<pre dir=\"ltr\">$3</pre>\n\n; Dacă tocmai ați modificat <code>LocalSettings.php</code>:\n: Verificați numele aspectelor pentru eventuale greșeli.",
        "default-skin-not-found-no-skins": "Ups! Aspectul standard pentru wiki, definit în <code>$wgDefaultSkin</code> ca <code>$1</code>, nu este disponibil.\n\nNu există aspecte instalate\n\n; Dacă tocmai ați instalat sau actualizat MediaWiki:\n: Probabil ați instalat folosind git sau direct din codul sursă print-o altă metodă. Acest lucru este normal. Începând cu MediaWiki 1.24, aspectele nu mai sunt incluse în depozitul principal. Încercați să instalați câteva aspecte din [https://www.mediawiki.org/wiki/Category:All_skins colecția de aspecte de la mediawiki.org]:\n:* Descărcând [https://www.mediawiki.org/wiki/Download instalatorul tarball], care este însoțit de câteva aspecte și extensii. Puteți copia directorul <code>skins/</code> din acesta.\n:* Descărcând arhive tar individuale cu aspecte de la [https://www.mediawiki.org/wiki/Special:SkinDistributor mediawiki.org].\n:* [https://www.mediawiki.org/wiki/Download_from_Git#Using_Git_to_download_MediaWiki_skins Utilizând Git pentru a descărca aspecte].\n: Această operațiune nu ar trebui să interfereze cu depozitul dumneavoastră git dacă sunteți dezvoltator MediaWiki. Vedeți [https://www.mediawiki.org/wiki/Manual:Skin_configuration Manual:Configurare aspecte] pentru informații despre cum puteți activa aspecte și alege pe cel implict.",
        "default-skin-not-found-row-enabled": "* <code>$1</code> / $2 (activat)",
        "mw-widgets-titleinput-description-new-page": "pagina nu există încă",
        "mw-widgets-titleinput-description-redirect": "redirecționare către $1",
        "api-error-blacklisted": "Vă rugăm să alegeți un alt titlu, mai descriptiv.",
+       "sessionprovider-generic": "sesiuni $1",
        "sessionprovider-mediawiki-session-cookiesessionprovider": "sesiuni pe bază de module cookie."
 }
index 87c383d..a8132b9 100644 (file)
@@ -87,7 +87,8 @@
                        "INS Pirat",
                        "Краснорядцева Елена",
                        "Frhdkazan",
-                       "Ядерный Трамвай"
+                       "Ядерный Трамвай",
+                       "Исмаил Садуев"
                ]
        },
        "tog-underline": "Подчёркивание ссылок:",
        "exif-jpegfilecomment": "Примечание JPEG-файла",
        "exif-keywords": "Ключевые слова",
        "exif-worldregioncreated": "Регион мира, где была сделана фотография",
-       "exif-countrycreated": "СÑ\82Ñ\80ана, Ð³Ð´Ðµ Ð±Ñ\8bла Ñ\81делана Ñ\84оÑ\82огÑ\80аÑ\84иÑ\8f",
+       "exif-countrycreated": "Ð\9cоÑ\85к, Ñ\81Ñ\83Ñ\80Ñ\82 Ð´Ð¸Ð½ Ñ\85илла Ð±Ð¾Ð»Ñ\83",
        "exif-countrycodecreated": "Код страны, где была сделана фотография",
        "exif-provinceorstatecreated": "Область, провинция или штат, где была сделана фотография",
-       "exif-citycreated": "Город, где была сделана фотография",
+       "exif-citycreated": "ГӀала, сурт дина хинйолу",
        "exif-sublocationcreated": "Район города, где была сделана фоторафия",
        "exif-worldregiondest": "Изображённый регион мира",
        "exif-countrydest": "Изображённая страна",
index 229fa0a..c52d7c4 100644 (file)
        "version-hook-subscribedby": "Пријављено од",
        "version-version": "($1)",
        "version-no-ext-name": "[нема имена]",
-       "version-svn-revision": "(изм. $2)",
        "version-license": "Медијавики лиценца",
        "version-ext-license": "Лиценца",
        "version-ext-colheader-name": "Екстензија",
index d65ea82..8aa46fd 100644 (file)
        "version-hook-subscribedby": "Prijavljeno od",
        "version-version": "($1)",
        "version-no-ext-name": "[nema imena]",
-       "version-svn-revision": "(izm. $2)",
        "version-license": "Medijaviki licenca",
        "version-ext-license": "Licenca",
        "version-ext-colheader-name": "Ekstenzija",
index e7b5d6b..8f0ae06 100644 (file)
        "grant-editpage": "Redigera befintliga sidor",
        "grant-editprotected": "Redigera skyddade sidor",
        "grant-highvolume": "Hög volymsredigering",
-       "grant-oversight": "Dölj användare och undertryck revideringar",
+       "grant-oversight": "Dölj användare och censurera versioner",
        "grant-patrol": "Patrullera ändringar på sidor",
        "grant-protect": "Skydda och ta bort skydd på sidor",
        "grant-rollback": "Rulla tillbaka ändringar på sidor",
        "upload-too-many-redirects": "URL-en innehöll för många omdirigeringar",
        "upload-http-error": "Ett HTTP-fel uppstod: $1",
        "upload-copy-upload-invalid-domain": "Uppladdning av kopior är inte tillgängligt från denna domän.",
-       "upload-foreign-cant-upload": "Denna wiki är inte konfigurerad för att ladda upp filer till den begärda främmande filförvar.",
+       "upload-foreign-cant-upload": "Denna wiki är inte konfigurerad för att ladda upp filer till det begärda externa filförvaret.",
        "upload-dialog-title": "Ladda upp fil",
        "upload-dialog-button-cancel": "Avbryt",
        "upload-dialog-button-done": "Klar",
        "tags-deactivate-not-allowed": "Det är inte möjligt att inaktivera taggen \"$1\".",
        "tags-deactivate-submit": "Inaktivera",
        "tags-apply-no-permission": "Du har inte behörighet att tillämpa taggar på dina ändringar",
-       "tags-apply-blocked": "Du kan inte använda(?) ändringsmärken när du är blockerad.",
+       "tags-apply-blocked": "Du kan inte ange ändringsmärken med dina ändringar medans du är blockerad.",
        "tags-apply-not-allowed-one": "Märket \"$1\" kan inte läggas till manuellt.",
        "tags-apply-not-allowed-multi": "Följande {{PLURAL:$2|märke|märken}} kan inte läggas till manuellt: $1",
        "tags-update-no-permission": "Du har inte behörighet att lägga till eller ta bort taggar från individuella sidversioner eller loggposter.",
        "mw-widgets-titleinput-description-new-page": "sidan existerar inte ännu",
        "mw-widgets-titleinput-description-redirect": "omdirigerar till $1",
        "api-error-blacklisted": "Välj en annan beskrivande titel.",
+       "sessionmanager-tie": "Kan inte kombinera flera begäransautentiseringstyper: $1.",
        "sessionprovider-generic": "$1-sessioner",
        "sessionprovider-mediawiki-session-cookiesessionprovider": "cookiebaserade sessioner",
        "sessionprovider-nocookies": "Cookies kan vara inaktiverade. Se till att du har cookies aktiverat och försök igen.",
index 3f92eb1..355e607 100644 (file)
        "log-title-wildcard": "ค้นหาชื่อเรื่องซึ่งขึ้นต้นด้วยข้อความนี้",
        "showhideselectedlogentries": "เปลี่ยนทัศนวิสัยของหน่วยปูมที่เลือก",
        "log-edit-tags": "ป้ายระบุการแก้ไขของรายการปูมที่เลือก",
+       "checkbox-select": "เลือก: $1",
+       "checkbox-all": "ทั้งหมด",
+       "checkbox-none": "ไม่เลือก",
+       "checkbox-invert": "กลับ",
        "allpages": "หน้าทั้งหมด",
        "nextpage": "หน้าถัดไป ($1)",
        "prevpage": "หน้าก่อนหน้า ($1)",
        "wlheader-showupdated": "หน้าที่มีการเปลี่ยนแปลงตั้งแต่คุณเยี่ยมครั้งสุดท้ายแสดงด้วย<strong>ตัวหนา</strong>",
        "wlnote": "ด้านล่างเป็น{{PLURAL:$1|การเปลี่ยนแปลงหลังสุด| <strong>$1</strong> การเปลี่ยนแปลงหลังสุด}} ใน{{PLURAL:$2|ชั่วโมง| <strong>$2</strong> ชั่วโมง}}ที่หลังสุด จนถึง $3, $4",
        "wlshowlast": "แสดง $1 ชั่วโมง $2 วันล่าสุด",
-       "watchlistall2": "ทั้งหมด",
        "watchlist-hide": "ซ่อน",
        "watchlist-submit": "แสดง",
        "wlshowtime": "ระยะเวลาที่แสดง:",
        "wlshowhideanons": "ผู้ใช้นิรนาม",
        "wlshowhidepatr": "การแก้ไขที่ตรวจสอบแล้ว",
        "wlshowhidemine": "การแก้ไขของฉัน",
+       "wlshowhidecategorization": "การจัดหมวดหมู่หน้า",
        "watchlist-options": "ตัวเลือกรายการเฝ้าดู",
        "watching": "กำลังเฝ้าดู...",
        "unwatching": "กำลังเลิกเฝ้าดู...",
        "tooltip-pt-preferences": "การตั้งค่าของคุณ",
        "tooltip-pt-watchlist": "รายการหน้าที่คุณกำลังเฝ้าดูการเปลี่ยนแปลง",
        "tooltip-pt-mycontris": "รายการหน้าที่คุณเขียน",
+       "tooltip-pt-anoncontribs": "รายการการแก้ไขจากเลขที่อยู่ไอพีนี้",
        "tooltip-pt-login": "สนับสนุนให้คุณล็อกอิน แต่ไม่บังคับ",
        "tooltip-pt-logout": "ล็อกเอาต์",
        "tooltip-pt-createaccount": "สนับสนุนให้คุณสร้างบัญชีและล็อกอิน แต่ไม่บังคับ",
        "pageinfo-category-files": "จำนวนไฟล์",
        "markaspatrolleddiff": "ทำเครื่องหมายว่าตรวจสอบแล้ว",
        "markaspatrolledtext": "ทำเครื่องหมายว่าหน้านี้ถูกตรวจสอบแล้ว",
+       "markaspatrolledtext-file": "ทำเครื่องหมายรุ่นไฟล์นี้ว่าตรวจสอบแล้ว",
        "markedaspatrolled": "ตรวจสอบแล้ว",
        "markedaspatrolledtext": "กำหนดรุ่นที่เลือกของ [[:$1]] ว่าตรวจสอบแล้ว",
        "rcpatroldisabled": "การตรวจสอบหน้าปรับปรุงล่าสุดถูกปิดใช้งาน",
        "newimages-legend": "ตัวกรอง",
        "newimages-label": "ชื่อไฟล์ (หรือส่วนหนึ่งของชื่อ):",
        "newimages-showbots": "แสดงไฟล์ที่บอตอัปโหลด",
+       "newimages-hidepatrolled": "ซ่อนการอัปโหลดที่ตรวจสอบแล้ว",
        "noimages": "ไม่มีให้ดู",
        "ilsubmit": "สืบค้น",
        "bydate": "ตามวันที่",
        "version-software-version": "รุ่น",
        "version-entrypoints-articlepath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgArticlePath เส้นทางบทความ]",
        "version-entrypoints-scriptpath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgScriptPath เส้นทางสคริปต์]",
-       "redirect": "การเปลี่ยนทางตามชื่อไฟล์ รหัสประจำผู้ใช้ หน้าหรือรุ่น",
+       "redirect": "การเปลี่ยนทางตามชื่อไฟล์ รหัสประจำผู้ใช้ หน้า รุ่นหรือปูม",
        "redirect-legend": "การเปลี่ยนทางไปยังไฟล์หรือหน้า",
        "redirect-summary": "หน้าพิเศษนี้เปลี่ยนทางไปยังไฟล์ (ระบุเป็นชื่อไฟล์) หน้า (ระบุเป็นรหัสรุ่นหรือรหัสหน้า) หรือหน้าผู้ใช้ (ระบุเป็นรหัสผู้ใช้ตัวเลข) การใช้งาน: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/page/64308]], [[{{#Special:Redirect}}/revision/328429]] หรือ [[{{#Special:Redirect}}/user/101]]",
        "redirect-submit": "ไป",
        "expand_templates_ok": "ตกลง",
        "expand_templates_remove_comments": "นำส่วนความเห็นออก",
        "expand_templates_preview": "ตัวอย่างผลแสดง",
-       "pagelanguage": "ตัวเลือกภาษาหน้า",
+       "expand_templates_input_missing": "คุณต้องให้ข้อความป้อนเข้าบ้าง",
+       "pagelanguage": "เปลี่ยนภาษาของหน้า",
        "pagelang-name": "หน้า",
        "pagelang-language": "ภาษา",
        "pagelang-use-default": "ใช้ภาษาโดยปริยาย",
        "pagelang-select-lang": "เลือกภาษา",
+       "pagelang-submit": "ส่ง",
        "right-pagelang": "เปลี่ยนภาษาหน้า",
        "action-pagelang": "เปลี่ยนภาษาหน้า",
        "log-name-pagelang": "ปูมการเปลี่ยนภาษา",
index 841dc31..a705263 100644 (file)
        "statistics-users": "Теркәлгән [[Special:ListUsers|кулланучылар]]",
        "statistics-users-active": "Актив кулланучылар",
        "statistics-users-active-desc": "{{PLURAL:$1|$1 көн }} өчендә нинди дә булса үзгәртүләр керткән кулланучылар",
+       "pageswithprop": "Үзенчәлекләре кабаттан билгеләнгән битләр",
+       "pageswithprop-legend": "Үзенчәлекләре кабаттан билгеләнгән битләр",
+       "pageswithprop-text": "Монда кайбер үзенчәлекләре кулдан яңартылган битләр күрсәтелгән.",
        "pageswithprop-prop": "Үзенчәлекнең атамасы:",
        "pageswithprop-submit": "Табу",
        "doubleredirects": "Икеләтә юнәлтүләр",
        "duration-days": "$1 {{PLURAL:$1|көн}}",
        "expandtemplates": "Үрнәкләрне ачу",
        "expand_templates_ok": "OK",
+       "mediastatistics": "Медиа хисабы",
        "special-characters-group-latin": "Латин",
        "special-characters-group-latinextended": "Латин (киңәйтелгән)",
        "special-characters-group-ipa": "ХФӘ (IPA)",
index 17cfff1..56a55de 100644 (file)
        "rcshowhidemine": "ذاتی ترامیم $1",
        "rcshowhidemine-show": "دکھاؤ",
        "rcshowhidemine-hide": "چھپائیں",
+       "rcshowhidecategorization": "صفحاتی زمرہ بندی $1",
        "rcshowhidecategorization-show": "دکھائیں",
        "rcshowhidecategorization-hide": "چھپائیں",
        "rclinks": "آخری $2 روز میں ہونے والی $1 تبدیلیوں کا مشاہدہ کریں<br />$3",
        "recentchangeslinked-title": "\"$1\" سے متعلقہ تبدیلیاں",
        "recentchangeslinked-summary": "یہ ان تبدیلیوں کی فہرست ہے جو حال ہی میں کسی مخصوص صفحہ سے مربوط صفحات (یا مخصوص زمرہ کے اراکین) میں کی گئی ہیں\n\n[[Special:Watchlist|آپ کی زیر نظر فہرست]] میں یہ صفحات متجل (bold) نظر آئیں گےـ",
        "recentchangeslinked-page": "صفحۂ منصوبہ دیکھئے",
+       "recentchanges-page-added-to-category": "[[:$1]] کو زمرہ میں شامل کیا گیا",
+       "recentchanges-page-added-to-category-bundled": "[[:$1]] اور {{PLURAL:$2|ایک صفحہ|$2 صفحات}} زمرہ میں شامل {{PLURAL:$2|کیا گیا|$2 کیے گئے}}",
+       "recentchanges-page-removed-from-category": "[[:$1]] کو زمرہ سے ہٹایا",
        "autochange-username": "میڈیاویکی خودکار تبدیلیاں",
        "upload": "فائل اثقال/اپلوڈ فائل",
        "uploadbtn": "زبراثقال ملف (اپ لوڈ فائل)",
        "watchlist-details": "آپ کی زیرِنظرفہرست پر {{PLURAL:$1|$1 صفحہ ہے|$1 صفحات ہیں}}، اِس میں تبادلۂ خیال صفحات کی تعداد شامل نہیں.",
        "wlnote": "نیچےآخری $1 تبدیلیاں ہیں جو کے پیچھلے <b>$2</b> گھنٹوں میں کی گئیں۔",
        "wlshowlast": "دکھائیں آخری $1 گھنٹے $2 دن",
-       "watchlistall2": "تمام",
        "watchlist-hide": "چھپائیں",
        "watchlist-submit": "دکھائیں",
        "wlshowhideminor": "معمولی ترامیم",
index 3999604..0bbeced 100644 (file)
@@ -10,7 +10,8 @@
                        "לערי ריינהארט",
                        "아라",
                        "Rachmat.Wahidi",
-                       "Macofe"
+                       "Macofe",
+                       "Robin van der Vliet"
                ]
        },
        "tog-underline": "Dislienükön yümis:",
        "nstab-template": "Samafomot",
        "nstab-help": "Yufapad",
        "nstab-category": "Klad",
+       "mainpage-nstab": "Cifapad",
        "nosuchaction": "Atos no mögon",
        "nosuchactiontext": "Dun peflagöl fa el URL no sevädon vüke.\nBa epenol eli URL neverätiko, u ba esukol yümi dobik.\nMögos i, das atos sinifon, das dabinon säkädil pö program fa {{SITENAME}} pageböl.",
        "nosuchspecialpage": "Pad patik at no dabinon",
        "createaccountmail": "me pot leäktronik",
        "createaccountreason": "Kod:",
        "createacct-reason": "Kod",
-       "createacct-imgcaptcha-ph": "Penolöd vödemi, keli logol löpo",
        "createacct-submit": "Jafön kali olik",
        "createacct-benefit-body1": "{{PLURAL:$1|redakam|redakams}}",
        "createacct-benefit-body2": "{{PLURAL:$1|pad|pads}}",
        "right-blockemail": "Blokön gitäti gebana ad sedön penedis leäktronik",
        "right-hideuser": "Blokön gebananemi, klänedölo oni de votikans",
        "right-ipblock-exempt": "Nedemön blokamis-IP, blokamis itjäfidik e grupiblokamis",
-       "right-proxyunbannable": "Nedemön blokamis itjäfidik pladulömas",
        "right-protect": "Votükön jelanivodis e redakön padis pejelöl",
        "right-editprotected": "Bevobön padis pejelöl äs \"{{int:protect-level-sysop}}\"",
        "right-editinterface": "Votükön gebanaloveikömi",
        "watchthisupload": "Galädolöd ragivi at",
        "filewasdeleted": "Ragiv labü nem at büo pelöpükon e poso pemoükon. Kontrololös eli $1 büä olöpükol oni dönu.",
        "filename-bad-prefix": "Nem ragiva fa ol palöpüköl primon me '''\"$1\"''': nem no bepenöl nomiko pagevöl itjäfidiko fa käms nulädik. Välolös, begö! nemi bepenöl pro ragiv olik.",
-       "upload-success-subj": "Löpükam eplöpon",
        "upload-proto-error": "Protok neverätik",
        "upload-proto-error-text": "Löpükam flagon elis URLs me <code>http://</code> u <code>ftp://</code> primölis.",
        "upload-file-error": "Pöl ninik",
        "contributions": "{{GENDER:$1|Gebanakeblünots}}",
        "contributions-title": "Gebanakeblünots pro $1",
        "mycontris": "Keblünots",
+       "anoncontribs": "Keblünots",
        "contribsub2": "{{GENDER:$3|Hiela|Jiela|Ela}} $1 ($2)",
        "nocontribs": "Votükams nonik petuvons me paramets at.",
        "uctop": "(anuik)",
        "movenosubpage": "Pad at no labon donapadis.",
        "movereason": "Kod:",
        "revertmove": "sädunön",
-       "delete_and_move": "Moükolöd e topätükolöd",
        "delete_and_move_text": "==Moükam peflagon==\n\nYeged nulik \"[[:$1]]\" ya dabinon. Vilol-li moükön oni ad jafön spadi pro topätükam?",
        "delete_and_move_confirm": "Si! moükolöd padi",
        "delete_and_move_reason": "Pemoükon ad jafön spadi pro topätükam se ''[[$1]]''",
index bd1b89d..39465f6 100644 (file)
        "nstab-image": "文件",
        "nstab-mediawiki": "信息",
        "nstab-template": "模板",
-       "nstab-help": "幫å¿\99é \81",
+       "nstab-help": "帮å¿\99页",
        "nstab-category": "分类",
        "mainpage-nstab": "封面",
        "nosuchaction": "嘸能操作",
        "changepassword-success": "密碼改好哉!\n能界登錄當中...",
        "changepassword-throttled": "侬试登录忒多次哉。等$1再试试看。",
        "resetpass_forbidden": "密码弗好更改",
-       "resetpass-no-info": "侬必须登录ä»\94å\86\8d好ç\9b´æ\8e¥è¿\9bå\85¥ç®\87å\8fªé¡µé\9d¢ã\80\82",
+       "resetpass-no-info": "侬必须登录è\91\97æ\89\8d好ç\9b´æ\8e¥è¿\9bå\85¥ç®\87å\8fªé¡µé\9d¢ã\80\82",
        "resetpass-submit-loggedin": "更改密码",
        "resetpass-submit-cancel": "取消",
        "resetpass-wrong-oldpass": "无效个临时或者现有密码。\n侬作兴已经成功拿密码改脱,或者已经请求一个新个临时密码。",
        "passwordreset-emailelement": "用户名:\n$1\n\n临时密码:\n$2",
        "changeemail": "更改或删脱电子邮箱地址",
        "changeemail-passwordrequired": "侬需要输入密码来确认本次更改。",
-       "changeemail-no-info": "侬必须登录著å\86\8d好ç\9b´æ\8e¥è¿\9bå\85¥ç®\87å\8fªé¡µé\9d¢ã\80\82",
+       "changeemail-no-info": "侬必须登录著æ\89\8d好ç\9b´æ\8e¥è¿\9bå\85¥ç®\87å\8fªé¡µé\9d¢ã\80\82",
        "changeemail-oldemail": "当前电子邮件地址:",
        "changeemail-newemail": "新个电子邮件地址:",
        "changeemail-password": "侬个{{SITENAME}}密码:",
        "nosuchsectiontext": "侬尝试编辑个章节弗存在。\n作兴是垃拉侬查看页面个辰光已经移动或者畀删除。",
        "loginreqtitle": "必须登录",
        "loginreqlink": "登录",
-       "loginreqpagetext": "侬必须$1再好查看其它页面。",
+       "loginreqpagetext": "请$1来望其他页面。",
        "accmailtitle": "密码已发送哉。",
        "accmailtext": "已经为[[User talk:$1|$1]]产生只随机密码,并且已经发送到$2。登录之后,侬可以垃拉<em>[[Special:ChangePassword|箇只页面]]</em>更改密码。",
        "newarticle": "(新)",
        "userpage-userdoesnotexist": "用户账户“<nowiki>$1</nowiki>”弗曾创建。请垃拉创建/编辑迭个页面前头先检查一记。",
        "userpage-userdoesnotexist-view": "用户账户“$1”弗曾创建。",
        "blocked-notice-logextract": "箇位用户箇歇畀封锁垃许。\n下头有最近个封锁纪录以供参考:",
-       "clearyourcache": "<strong>注意:</strong>垃拉保存之后,侬作兴要清除浏览器个缓存å\86\8d好ç\9c\8bè§\81æ\94¹å\8f\98ã\80\82\n* <strong>Firefoxæ\88\96Safariï¼\9a</strong>æ\8f¿ç\89¢â\80\9cShiftâ\80\9d个å\90\8cæ\97¶ç\82¹å\87»â\80\9cå\88·æ\96°â\80\9dï¼\8cæ\88\96æ\8f¿â\80\9cCtrl-F5â\80\9dæ\88\96â\80\9cCtrl-Râ\80\9dï¼\88Macä¸\8aæ\98¯â\80\9câ\8c\98-Râ\80\9dï¼\89\n* <strong>Google Chromeï¼\9a</strong>æ\8f¿â\80\9cCtrl-Shift-Râ\80\9dï¼\88Macä¸\8aæ\98¯â\80\9câ\8c\98-Shift-Râ\80\9dï¼\89\n* <strong>Internet Explorerï¼\9a</strong>æ\8f¿ç\89¢â\80\9cCtrlâ\80\9d个å\90\8cæ\97¶ç\82¹å\87»â\80\9cå\88·æ\96°â\80\9dï¼\8cæ\88\96æ\8f¿â\80\9cCtrl-F5â\80\9d\n* <strong>Operaï¼\9a</strong>å\9e\83æ\8b\89â\80\9cå·¥å\85·â\86\92é¦\96é\80\89项â\80\9dé\87\8cå\90\91æ¸\85é\99¤ç¼\93å­\98",
+       "clearyourcache": "<strong>注意:</strong>垃拉保存之后,侬作兴要清除浏览器个缓存æ\89\8d好ç\9c\8bè§\81æ\94¹å\8f\98ã\80\82\n* <strong>Firefoxæ\88\96Safariï¼\9a</strong>æ\8f¿ç\89¢â\80\9cShiftâ\80\9d个å\90\8cæ\97¶ç\82¹å\87»â\80\9cå\88·æ\96°â\80\9dï¼\8cæ\88\96æ\8f¿â\80\9cCtrl-F5â\80\9dæ\88\96â\80\9cCtrl-Râ\80\9dï¼\88Macä¸\8aæ\98¯â\80\9câ\8c\98-Râ\80\9dï¼\89\n* <strong>Google Chromeï¼\9a</strong>æ\8f¿â\80\9cCtrl-Shift-Râ\80\9dï¼\88Macä¸\8aæ\98¯â\80\9câ\8c\98-Shift-Râ\80\9dï¼\89\n* <strong>Internet Explorerï¼\9a</strong>æ\8f¿ç\89¢â\80\9cCtrlâ\80\9d个å\90\8cæ\97¶ç\82¹å\87»â\80\9cå\88·æ\96°â\80\9dï¼\8cæ\88\96æ\8f¿â\80\9cCtrl-F5â\80\9d\n* <strong>Operaï¼\9a</strong>å\9e\83æ\8b\89â\80\9cå·¥å\85·â\86\92é¦\96é\80\89项â\80\9dé\87\8cå\90\91æ¸\85é\99¤ç¼\93å­\98",
        "usercssyoucanpreview": "'''提示:''' 垃拉保存之前请用“{{int:showpreview}}”揿钮来测试新 CSS 。",
        "userjsyoucanpreview": "'''提示:''' 垃拉保存之前请用“{{int:showpreview}}”揿钮来测试新 JavaScript 。",
        "usercsspreview": "'''注意侬只是垃许预览侬个 CSS。'''\n'''还弗曾保存!'''",
        "copyrightwarning2": "请注意侬对{{SITENAME}}个所有贡献\n侪可能畀别个贡献者编辑,修改或删除。\n假使侬弗希望侬个文字畀任意修改搭仔再发布,请弗要提交。<br />\n侬同时也要向我伲保证侬提交个内容是侬自家所作,或得自一个弗受版权保护或相似自由个来源(参阅$1个细节)。\n''' 弗要垃拉弗曾获得授权个情况下头发表!'''",
        "longpageerror": "<strong>错误:侬提交个文本长度有$1KB,大于$2KB个顶大值。</strong>该文本弗能保存。",
        "readonlywarning": "<strong>警告:数据库锁定垃许维护,侬箇歇弗好保存侬个修改。</strong>侬作兴希望先拿侬个文字复制并保存到文本文件,等歇再修改。\n\n锁牢数据库个系统管理员有如下解释:$1",
-       "protectedpagewarning": "<strong>警告:此页已经畀保护,只有拥有管理员权限个用户å\86\8d好修æ\94¹ã\80\82</strong>æ\9c\80è¿\91个æ\97¥å¿\97å\9e\83æ\8b\89ä¸\8båº\95æ\8f\90ä¾\9b以便å\8f\82è\80\83ï¼\9a",
+       "protectedpagewarning": "<strong>警告:此页已经畀保护,只有拥有管理员权限个用户æ\89\8d好修æ\94¹ã\80\82</strong>æ\9c\80è¿\91个æ\97¥å¿\97å\9e\83æ\8b\89ä¸\8båº\95æ\8f\90ä¾\9b以便å\8f\82è\80\83ï¼\9a",
        "semiprotectedpagewarning": "'''注意:''' 本页面畀锁定,仅限注册用户编辑。\n最近个日志垃拉下底提供以便参考:",
-       "cascadeprotectedwarning": "<strong>警告:</strong>本页已经畀保护,只有拥有管理员权限个用户å\86\8d好修æ\94¹ï¼\8cå\9b ä¸ºæ\9c¬é¡µå·²ç\95\80ä¸\8båº\95ç\9c¼çº§è\81\94ä¿\9dæ\8a¤ä¸ª{{PLURAL:$1|ä¸\80å\8fª|å¤\9aå\8fª}}页é\9d¢æ\89\80åµ\8cå\85¥ï¼\9a",
+       "cascadeprotectedwarning": "<strong>警告:</strong>本页已经畀保护,只有拥有管理员权限个用户æ\89\8d好修æ\94¹ï¼\8cå\9b ä¸ºæ\9c¬é¡µå·²ç\95\80ä¸\8båº\95ç\9c¼çº§è\81\94ä¿\9dæ\8a¤ä¸ª{{PLURAL:$1|ä¸\80å\8fª|å¤\9aå\8fª}}页é\9d¢æ\89\80åµ\8cå\85¥ï¼\9a",
        "titleprotectedwarning": "'''警告:本页面已畀锁定,需要[[Special:ListGroupRights|指定权限]]方可创建。'''\n最近个日志垃拉下底提供以便参考:",
        "templatesused": "箇页有{{PLURAL:$1|个模板}}:",
        "templatesusedpreview": "{{PLURAL:$1|只模板}}垃拉箇趟预览里向拨使用:",
        "revdelete-selected-file": "已选择文件[[:$2]]个$1只版本:",
        "logdelete-selected": "选取$1个日志事件:",
        "revdelete-confirm": "假使侬想箇能介做个闲话,请确认侬已经清爽箇能介做个后果,外加箇个程序符合[[{{MediaWiki:Policy-url}}|政策]]。",
-       "revdelete-suppress-text": "<strong>只有</strong>出现下头眼情况å\86\8dåº\94é\98»æ­¢è®¿é\97®ï¼\9a\n* æ½\9cå\9c¨ä¸ªè¯½è°¤ä¿¡æ\81¯\n* å¼\97é\80\82å\90\88个个人信æ\81¯\n*: <em>家庭å\9c°å\9d\80ã\80\81ç\94µè¯\9då\8f·ç \81ã\80\81身份è¯\81å\8f·ç \81ç­\89ã\80\82</em>",
+       "revdelete-suppress-text": "<strong>只有</strong>出现下头眼情况æ\89\8dåº\94é\98»æ­¢è®¿é\97®ï¼\9a\n* æ½\9cå\9c¨ä¸ªè¯½è°¤ä¿¡æ\81¯\n* å¼\97é\80\82å\90\88个个人信æ\81¯\n*: <em>家庭å\9c°å\9d\80ã\80\81ç\94µè¯\9då\8f·ç \81ã\80\81身份è¯\81å\8f·ç \81ç­\89ã\80\82</em>",
        "revdelete-legend": "设置可见性之限制",
        "revdelete-hide-text": "修订文本",
        "revdelete-hide-image": "隐藏文件内容",
        "prefs-advancedwatchlist": "高级选项",
        "prefs-tabs-navigation-hint": "提示:侬可以用左、右箭头键来选项卡之间切换。",
        "userrights-user-editname": "输入用户名:",
-       "editusergroup": "编辑用户组",
+       "editusergroup": "编辑{{GENDER:$1|用户}}组",
+       "editinguser": "改动{{GENDER:$1|用户}}<strong>[[User:$1|$1]]</strong>个用户权限$2",
        "group-bot": "机器人",
        "group-sysop": "管理员",
        "group-bureaucrat": "行政员",
        "right-deleterevision": "删脱搭恢复页面个特定版本",
        "right-deletedhistory": "检视畀删脱个历史项目,弗包括相关文本",
        "right-browsearchive": "搜尋已刪頁",
+       "right-unblockself": "解封自家",
        "right-editusercss": "编辑其他用户个CSS文件",
        "right-edituserjs": "编辑其他用户个JavaScript文件",
        "right-editmyusercss": "编辑侬自家个用户CSS文件",
        "grant-group-page-interaction": "搭頁面互動",
        "grant-group-file-interaction": "搭媒體互動",
        "grant-group-watchlist-interaction": "搭侬个关注表互动",
-       "grant-group-email": "發電子信",
+       "grant-group-email": "发电子邮件",
+       "grant-createaccount": "建立账号",
+       "grant-createeditmovepage": "建立、编辑搭著捅荡页面",
        "grant-rollback": "畀修改擂轉到頁面",
        "grant-sendemail": "發電子信畀各許用戶",
        "newuserlogpage": "用户创建日志",
        "rcshowhideanons": "$1匿名用户",
        "rcshowhideanons-show": "显示",
        "rcshowhideanons-hide": "囥脱",
+       "rcshowhidepatr-hide": "囥脱",
        "rcshowhidemine": "$1我个编辑",
        "rcshowhidemine-show": "显示",
        "rcshowhidemine-hide": "囥脱",
        "uploadbtn": "上载文件",
        "reuploaddesc": "弗傳,轉到傳表單",
        "uploadnologin": "朆登录",
-       "uploadnologintext": "倷板定要$1再好上载文件。",
+       "uploadnologintext": "请$1来上载文件。",
        "uploaderror": "上载出错",
        "uploadtext": "拿下头只表格来上载文件。要查看或者搜寻之前上载个图片个说法,请到[[Special:FileList|已上载文件列表]],上载搭仔删脱也记录勒拉[[Special:Log/upload|上载日志]]里向。\n\n要勒拉页面里向摆进图片个说法,用下头该种形式个链接\n'''<nowiki>[[{{ns:file}}:文件.jpg]]</nowiki>''',\n'''<nowiki>[[{{ns:file}}:文件.png|替代文本]]</nowiki>''' 或者用\n'''<nowiki>[[{{ns:media}}:文件.ogg]]</nowiki>''' 直接链到文件。",
        "uploadlogpage": "文件上传日志",
        "categories": "页面分类",
        "categoriespagetext": "下底个{{PLURAL:$1|分类包括}}页面或者媒体文件。[[Special:UnusedCategories|未使用分类]]弗勒伊𡍲显示。另见[[Special:WantedCategories|需要个分类]]。",
        "deletedcontributions": "删脱个用户贡献",
+       "deletedcontributions-title": "删脱个用户贡献",
        "linksearch": "外部链接搜寻",
        "linksearch-ns": "名字空間:",
        "linksearch-ok": "搜尋",
        "wlheader-showupdated": "勒侬上趟查看之后畀修改个页面<strong>加粗</strong>显示。",
        "wlnote": "下底是{{PLURAL:$2|过去<strong>$2</strong>个钟头}}个{{PLURAL:$1|最后<strong>$1</strong>届更改}},截至$3 $4。",
        "wlshowlast": "显示上$1个钟头$2日天",
-       "watchlistall2": "全部",
+       "watchlist-hide": "囥脱",
+       "wlshowhidemine": "我个编辑",
        "watchlist-options": "监控列表选项",
        "watching": "监控……",
        "unwatching": "解除监控……",
        "undelete-search-submit": "搜尋",
        "namespace": "名字空间:",
        "invert": "反选择",
-       "tooltip-invert": "请选择该框来囥脱指定名字空间(搭有关名字空间,如果你选择)个页面更改",
+       "tooltip-invert": "打上扎钩头来囥脱选定名字空间个改动(如果勾选有关名字空间,箇么一道囥脱)",
        "namespace_association": "有关个名字空间",
-       "tooltip-namespace_association": "选中该复选框可包括搭选定名字空间有关个讨论页或子页面",
+       "tooltip-namespace_association": "打上扎钩头来加上搭选定名字空间搭界个讨论或主题名字空间",
        "blanknamespace": "(主)",
        "contributions": "{{GENDER:$1|用户}}贡献",
        "contributions-title": "$1个贡献",
        "year": "从箇年往前:",
        "sp-contributions-newbies": "只显示新用户个贡献",
        "sp-contributions-blocklog": "查封记录",
+       "sp-contributions-deleted": "删脱个用户贡献",
        "sp-contributions-talk": "讲张",
        "sp-contributions-search": "搜寻贡献记录",
        "sp-contributions-username": "IP地址要勿用户名:",
        "whatlinkshere-hidelinks": "$1链接",
        "whatlinkshere-filters": "过滤器",
        "blockip": "查封{{GENDER:$1|用户}}",
-       "blockiptext": "用下头个表单来禁止来自某一特定IP地址或用户名个修改权限。只有勒勒为仔防止破坏,及符合[[{{MediaWiki:Policy-url}}|政策]]个情况下底再好采取此行动。请勒勒下底输入一个具体个理由(譬如引述一只畀破坏个页面)。",
+       "blockiptext": "用下头个表单来禁止来自某一特定IP地址或用户名个修改权限。只有勒勒为仔防止破坏,及符合[[{{MediaWiki:Policy-url}}|政策]]个情况下底才好采取此行动。请勒勒下底输入一个具体个理由(譬如引述一只畀破坏个页面)。侬好用[https://zh.wikipedia.org/wiki/无类别域间路由 CIDR]语法查封IP地址段;允许个最大段是/$1(针对IPv4)搭/$2(针对IPv6)。",
        "ipaddressorusername": "IP地址或用户名:",
        "ipbreason": "理由:",
        "ipbsubmit": "封杀该个用户",
        "move-page-legend": "页面捅荡",
        "movepagetext": "用下底个表会重命名一只页面,全部历史侪移到新名字里。老个名字会变成戳到新名字个重定向页。注意检查[[Special:DoubleRedirects|双重重定向]]或者[[Special:BrokenRedirects|坏脱个重定向]]。倷有实概个责任,让链接仍旧链到俚笃应该链到个场化去。\n\n注意,如果新名字归面搭已经有页面个说话,老名字个页面'''弗'''会畀移动,除非归个是只空页面或者是只重定向并且呒不编辑历史。箇也就是讲,假使倷犯错误个说话,倷好拿一只重命名过个页面还原到原来个名字,但倷弗好覆盖一只已经来上个页面。\n\n<strong>警告!</strong>箇呒数会引起对一只热门页面剧烈个、想弗着个改变。来操作前头请倷确定倷已经充分了解行为个后果。",
        "movepagetalktext": "如果侬勾选此框,相关讨论页会自动移动到新标题,除非箇𡍲已经有著一只非空个讨论页。\n\n来箇种情况下底,如果有需要,侬必须手工移动或合并页面。",
-       "movenologintext": "倷板定要是å·²ç\99»è®°ç\94¨æ\88·ä¸\94å\8b\92æ\8b\89[[Special:UserLogin|ç\99»å½\95]]ç\8a¶æ\80\81ä¸\8b头å\86\8d好æ\8b¿é¡µé\9d¢æ\8d\85è\8d¡ã\80\82",
+       "movenologintext": "倷板定要是注å\86\8cç\94¨æ\88·å¹¶ä¸\94[[Special:UserLogin|ç\99»å½\95]]è\91\97æ\89\8d好æ\8b¿é¡µé\9d¢æ\8d\85è\8d¡ã\80\82",
        "newtitle": "新标题:",
        "move-watch": "监控来源以及目标页",
        "movepagebtn": "页面移动",
        "tooltip-feed-rss": "订阅本页",
        "tooltip-feed-atom": "此页个Atom 订阅",
        "tooltip-t-contributions": "{{GENDER:$1|箇位用户}}个贡献列表",
-       "tooltip-t-emailuser": "发电子信畀箇个用户",
+       "tooltip-t-emailuser": "发电子信畀{{GENDER:$1|箇位用户}}",
        "tooltip-t-upload": "上传文件",
        "tooltip-t-specialpages": "全部特殊页列表",
        "tooltip-t-print": "箇页个打印版",
        "tooltip-ca-nstab-main": "望内容页",
        "tooltip-ca-nstab-user": "查看用户页",
        "tooltip-ca-nstab-media": "查看媒体页",
-       "tooltip-ca-nstab-special": "箇是特æ®\8a页é\9d¢ï¼\8cå¼\97è\83½ç¼\96è¾\91",
+       "tooltip-ca-nstab-special": "箇是特å\88«é¡µé\9d¢ï¼\8cå¼\97好ç¼\96è¾\91",
        "tooltip-ca-nstab-project": "望项目页",
        "tooltip-ca-nstab-image": "望文件页",
        "tooltip-ca-nstab-mediawiki": "查看系统讯息",
        "confirmemail_body_changed": "用IP地址$1嗰人,(呒数是你侬)徕{{SITENAME}}里一个账号“$2”建起,用你侬个电子信箱地址。\n\n确认记箇账号是弗是你侬嘅,激活{{SITENAME}}里嗰电子信功能。用浏览器打开下向嗰链接:\n\n$3\n\n假使你侬*朆*注册过箇账号,揿下向嗰链接取消电子信确认:\n\n$5\n\n确认码会到$4过期。",
        "scarytranscludetoolong": "[URL忒长]",
        "deletedwhileediting": "<strong>警告:</strong>此页拉侬开始编辑之后已经畀删脱!",
-       "confirmrecreate": "用户[[User:$1|$1]] ([[User talk:$1|讲张]])勒拉倷开始编辑该页面之后拿俚删脱,理由是: : ''$2'' 请拿定章程,倷阿是真个要重建该页面。",
+       "confirmrecreate": "用户[[User:$1|$1]]([[User talk:$1|讲张]])勒拉倷开始编辑该页面之后拿俚{{GENDER:$1|删脱}},理由是:\n: <em>$2</em>\n请拿定章程,倷啊是真个要重建该页面。",
        "confirm_purge_button": "确定",
        "comma-separator": "、",
        "parentheses": "($1)",
        "revdelete-unrestricted": "已移除对管理员个限制",
        "logentry-block-block": "$1{{GENDER:$2|查封}}{{GENDER:$4|$3}},终止辰光为$5$6",
        "logentry-move-move": "$1{{GENDER:$2|捅荡}}页面$3到$4",
+       "logentry-move-move-noredirect": "$1{{GENDER:$2|捅荡}}页面$3到$4,弗留重定向",
        "logentry-newusers-create": "用户账号$1畀{{GENDER:$2|创建}}",
        "logentry-newusers-create2": "用户账号$3畀$1{{GENDER:$2|创建}}",
        "logentry-newusers-autocreate": "用户账号$1畀自动{{GENDER:$2|创建}}",
index 700d739..017da98 100644 (file)
@@ -87,7 +87,8 @@
                        "Cdz",
                        "凡人丶",
                        "Nbdd0121",
-                       "Apflu"
+                       "Apflu",
+                       "飞舞回堂前"
                ]
        },
        "tog-underline": "链接下划线:",
        "tooltip-invert": "请选择该框以隐藏指定名字空间(及相关名字空间,若被选择)的页面更改",
        "tooltip-whatlinkshere-invert": "勾选此框以隐藏来自选定名字空间内页面的链接。",
        "namespace_association": "关联的名字空间",
-       "tooltip-namespace_association": "选中此复选框可包括与选定名字空间相关的讨论页或子页面",
+       "tooltip-namespace_association": "选中此复选框可包括与选定名字空间相关的讨论或主题名字空间",
        "blanknamespace": "(主)",
        "contributions": "{{GENDER:$1|用户}}贡献",
        "contributions-title": "$1的用户贡献",
        "pageinfo-robot-index": "允许",
        "pageinfo-robot-noindex": "不允许",
        "pageinfo-watchers": "页面监视者数",
-       "pageinfo-visiting-watchers": "访问最近编辑的页面浏览者数量",
+       "pageinfo-visiting-watchers": "已访问最近编辑的页面监视者数",
        "pageinfo-few-watchers": "少于$1个监视者",
        "pageinfo-few-visiting-watchers": "这里可能有或可能没有观察用户正在访问最近编辑",
        "pageinfo-redirects-name": "至该页面的重定向数",
        "version-libraries-license": "许可协议",
        "version-libraries-description": "描述",
        "version-libraries-authors": "作者",
-       "redirect": "重定向(按文件、用户、页面、修订版本ID或日志ID)",
+       "redirect": "重定向(按文件、用户、页面、修订版本或日志ID)",
        "redirect-legend": "重定向至文件或页面",
        "redirect-summary": "本特殊页面可以跳转至一个文件(提供文件名)、页面(提供修订版本ID或页面ID)、用户页(提供数字用户ID)或日志记录(提供日志ID)。用法:[[{{#Special:Redirect}}/file/Example.jpg]]、[[{{#Special:Redirect}}/page/64308]]、[[{{#Special:Redirect}}/revision/328429]]、[[{{#Special:Redirect}}/user/101]]或[[{{#Special:Redirect}}/logid/186]]。",
        "redirect-submit": "提交",
index 2ac3e67..f39309c 100644 (file)
        "pageinfo-robot-index": "允許",
        "pageinfo-robot-noindex": "不允許",
        "pageinfo-watchers": "頁面監視者數",
-       "pageinfo-visiting-watchers": "最後一次編輯後參觀人數",
+       "pageinfo-visiting-watchers": "已訪問最近編輯的頁面監視者數",
        "pageinfo-few-watchers": "少於 $1 名監視者",
        "pageinfo-few-visiting-watchers": "參觀近期編輯的使用者可能為監視使用者",
        "pageinfo-redirects-name": "指向此頁面的重新導向頁面數量",
        "version-libraries-license": "授權條款",
        "version-libraries-description": "描述",
        "version-libraries-authors": "作者",
-       "redirect": "重新導向至檔案、使用者、頁面或修訂 ID",
+       "redirect": "重定向(按文件、用戶、頁面、修訂版本ID或日誌ID)",
        "redirect-legend": "重新導向至檔案或頁面",
        "redirect-summary": "此特殊頁面可用來重新導向至檔案 (指定檔案名稱)、頁面 (指定修訂 ID 或頁面 ID) 或使用者頁面 (指定使用者 ID)。用法:[[{{#Special:Redirect}}/file/Example.jpg]]、[[{{#Special:Redirect}}/page/64308]]、[[{{#Special:Redirect}}/revision/328429]] 或 [[{{#Special:Redirect}}/user/101]]。",
        "redirect-submit": "執行",
index 291920b..5a7f769 100644 (file)
@@ -84,7 +84,7 @@ abstract class Maintenance {
        protected $mQuiet = false;
        protected $mDbUser, $mDbPass;
 
-       // A description of the script, children should change this
+       // A description of the script, children should change this via addDescription()
        protected $mDescription = '';
 
        // Have we already loaded our user input?
index a2ea554..deab60b 100644 (file)
@@ -38,7 +38,7 @@ class AttachLatest extends Maintenance {
                $this->addOption( "fix", "Actually fix the entries, will dry run otherwise" );
                $this->addOption( "regenerate-all",
                        "Regenerate the page_latest field for all records in table page" );
-               $this->mDescription = "Fix page_latest entries in the page table";
+               $this->addDescription( 'Fix page_latest entries in the page table' );
        }
 
        public function execute() {
index 1569234..40a877f 100644 (file)
@@ -34,7 +34,7 @@ require_once __DIR__ . '/Benchmarker.php';
 class BenchHttpHttps extends Benchmarker {
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Benchmark HTTP request vs HTTPS request.";
+               $this->addDescription( 'Benchmark HTTP request vs HTTPS request.' );
        }
 
        public function execute() {
index 810937a..439947d 100644 (file)
@@ -34,7 +34,7 @@ require_once __DIR__ . '/Benchmarker.php';
 class BenchWikimediaBaseConvert extends Benchmarker {
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Benchmark for Wikimedia\\base_convert.";
+               $this->addDescription( 'Benchmark for Wikimedia\base_convert.' );
                $this->addOption( "inbase", "Input base", false, true );
                $this->addOption( "outbase", "Output base", false, true );
                $this->addOption( "length", "Size in digits to generate for input", false, true );
index 572c548..9acb93a 100644 (file)
@@ -31,7 +31,7 @@ require_once __DIR__ . '/Benchmarker.php';
 class BenchmarkDeleteTruncate extends Benchmarker {
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Benchmarks SQL DELETE vs SQL TRUNCATE.";
+               $this->addDescription( 'Benchmarks SQL DELETE vs SQL TRUNCATE.' );
        }
 
        public function execute() {
index 698a0f0..8f7f61d 100644 (file)
@@ -34,7 +34,7 @@ require_once __DIR__ . '/Benchmarker.php';
 class BenchIfSwitch extends Benchmarker {
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Benchmark if elseif... versus switch case.";
+               $this->addDescription( 'Benchmark if elseif... versus switch case.' );
        }
 
        public function execute() {
index 44c8e03..f34d27f 100644 (file)
@@ -41,7 +41,7 @@ function bfNormalizeTitleStrReplace( $str ) {
 class BenchStrtrStrReplace extends Benchmarker {
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Benchmark for strtr() vs str_replace().";
+               $this->addDescription( 'Benchmark for strtr() vs str_replace().' );
        }
 
        public function execute() {
index b742f66..bd18adb 100644 (file)
@@ -64,11 +64,10 @@ class BenchUtf8TitleCheck extends Benchmarker {
                $this->canRun = function_exists( 'mb_check_encoding' );
 
                if ( $this->canRun ) {
-                       $this->mDescription = "Benchmark for using a regexp vs. mb_check_encoding " .
-                               "to check for UTF-8 encoding.";
-                       mb_internal_encoding( 'UTF-8' );
+                       $this->addDescription( "Benchmark for using a regexp vs. mb_check_encoding " .
+                               "to check for UTF-8 encoding." );
                } else {
-                       $this->mDescription = "CANNOT RUN benchmark using mb_check_encoding: function not available.";
+                       $this->addDescription( 'CANNOT RUN benchmark using mb_check_encoding: function not available.' );
                }
        }
 
index 8446694..ea919ef 100644 (file)
@@ -34,7 +34,7 @@ require_once __DIR__ . '/Benchmarker.php';
 class BenchWfIsWindows extends Benchmarker {
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Benchmark for wfIsWindows.";
+               $this->addDescription( 'Benchmark for wfIsWindows.' );
        }
 
        public function execute() {
index 1446871..3106f89 100644 (file)
@@ -31,7 +31,7 @@ require_once __DIR__ . '/Benchmarker.php';
 class BenchmarkHooks extends Benchmarker {
        public function __construct() {
                parent::__construct();
-               $this->mDescription = 'Benchmark MediaWiki Hooks.';
+               $this->addDescription( 'Benchmark MediaWiki Hooks.' );
        }
 
        public function execute() {
index 9eca73c..e67d226 100644 (file)
@@ -31,7 +31,7 @@ require_once __DIR__ . '/Benchmarker.php';
 class BenchmarkPurge extends Benchmarker {
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Benchmark the Squid purge functions.";
+               $this->addDescription( 'Benchmark the Squid purge functions.' );
        }
 
        public function execute() {
index 5d98e1f..8687f81 100644 (file)
@@ -37,7 +37,7 @@ class ChangePassword extends Maintenance {
                $this->addOption( "user", "The username to operate on", false, true );
                $this->addOption( "userid", "The user id to operate on", false, true );
                $this->addOption( "password", "The password to use", true, true );
-               $this->mDescription = "Change a user's password";
+               $this->addDescription( "Change a user's password" );
        }
 
        public function execute() {
index 500fc35..985df56 100644 (file)
@@ -31,7 +31,7 @@ require_once __DIR__ . '/Maintenance.php';
 class CheckBadRedirects extends Maintenance {
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Check for bad redirects";
+               $this->addDescription( 'Check for bad redirects' );
        }
 
        public function execute() {
index 7a85d64..9ec61dc 100644 (file)
@@ -12,8 +12,8 @@ require_once __DIR__ . '/Maintenance.php';
 class CheckComposerLockUpToDate extends Maintenance {
        public function __construct() {
                parent::__construct();
-               $this->mDescription =
-                       'Checks whether your composer.lock file is up to date with the current composer.json';
+               $this->addDescription(
+                       'Checks whether your composer.lock file is up to date with the current composer.json' );
        }
 
        public function execute() {
index 9761927..9a8203f 100644 (file)
@@ -31,7 +31,7 @@ class CheckImages extends Maintenance {
 
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Check images to see if they exist, are readable, etc";
+               $this->addDescription( 'Check images to see if they exist, are readable, etc' );
                $this->setBatchSize( 1000 );
        }
 
index 2f533cf..889c903 100644 (file)
@@ -30,8 +30,8 @@ class CheckLess extends Maintenance {
 
        public function __construct() {
                parent::__construct();
-               $this->mDescription =
-                       'Checks LESS files for errors by running the LessTestSuite PHPUnit test suite';
+               $this->addDescription(
+                       'Checks LESS files for errors by running the LessTestSuite PHPUnit test suite' );
        }
 
        public function execute() {
index 30a23d3..4821e04 100644 (file)
@@ -36,7 +36,7 @@ class CheckSyntax extends Maintenance {
 
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Check syntax for all PHP files in MediaWiki";
+               $this->addDescription( 'Check syntax for all PHP files in MediaWiki' );
                $this->addOption( 'with-extensions', 'Also recurse the extensions folder' );
                $this->addOption(
                        'path',
index 6f4d170..1b9a1cc 100644 (file)
@@ -35,7 +35,7 @@ class CheckUsernames extends Maintenance {
 
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Verify that database usernames are actually valid";
+               $this->addDescription( 'Verify that database usernames are actually valid' );
                $this->setBatchSize( 1000 );
        }
 
index f1467d5..7f67b60 100644 (file)
@@ -33,7 +33,7 @@ class CleanupAncientTables extends Maintenance {
 
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Cleanup ancient tables and indexes";
+               $this->addDescription( 'Cleanup ancient tables and indexes' );
                $this->addOption( 'force', 'Actually run this script' );
        }
 
index 437abe9..2efd7ab 100644 (file)
@@ -33,7 +33,7 @@ class CleanupBlocks extends Maintenance {
 
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Cleanup user blocks with user names not matching the 'user' table";
+               $this->addDescription( "Cleanup user blocks with user names not matching the 'user' table" );
                $this->setBatchSize( 1000 );
        }
 
index e0a0f49..a79c2d3 100644 (file)
@@ -42,7 +42,7 @@ class CapsCleanup extends TableCleanup {
 
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Script to cleanup capitalization";
+               $this->addDescription( 'Script to cleanup capitalization' );
                $this->addOption( 'namespace', 'Namespace number to run caps cleanup on', false, true );
        }
 
index ab2d808..0110685 100644 (file)
@@ -42,7 +42,7 @@ class ImageCleanup extends TableCleanup {
 
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Script to clean up broken, unparseable upload filenames";
+               $this->addDescription( 'Script to clean up broken, unparseable upload filenames' );
        }
 
        protected function processRow( $row ) {
index 810fad9..19949bc 100644 (file)
@@ -34,7 +34,8 @@ class CleanupRemovedModules extends Maintenance {
 
        public function __construct() {
                parent::__construct();
-               $this->mDescription = 'Remove cache entries for removed ResourceLoader modules from the database';
+               $this->addDescription(
+                       'Remove cache entries for removed ResourceLoader modules from the database' );
                $this->addOption( 'batchsize', 'Delete rows in batches of this size. Default: 500', false, true );
        }
 
index b43ce81..020f5cd 100644 (file)
@@ -32,7 +32,7 @@ class CleanupSpam extends Maintenance {
 
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Cleanup all spam from a given hostname";
+               $this->addDescription( 'Cleanup all spam from a given hostname' );
                $this->addOption( 'all', 'Check all wikis in $wgLocalDatabases' );
                $this->addOption( 'delete', 'Delete pages containing only spam instead of blanking them' );
                $this->addArg(
index 07df1b1..574d5bd 100644 (file)
@@ -35,7 +35,7 @@ require_once __DIR__ . '/cleanupTable.inc';
 class TitleCleanup extends TableCleanup {
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Script to clean up broken, unparseable titles";
+               $this->addDescription( 'Script to clean up broken, unparseable titles' );
        }
 
        /**
index 70490e1..480059d 100644 (file)
@@ -37,7 +37,7 @@ class UploadStashCleanup extends Maintenance {
 
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Clean up abandoned files in temporary uploaded file stash";
+               $this->addDescription( 'Clean up abandoned files in temporary uploaded file stash' );
                $this->setBatchSize( 50 );
        }
 
index 16f7b61..d8c682b 100644 (file)
@@ -46,7 +46,7 @@ class WatchlistCleanup extends TableCleanup {
 
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Script to remove broken, unparseable titles in the Watchlist";
+               $this->addDescription( 'Script to remove broken, unparseable titles in the Watchlist' );
                $this->addOption( 'fix', 'Actually remove entries; without will only report.' );
        }
 
index 6a6527f..4b5773c 100644 (file)
@@ -32,7 +32,7 @@ class ClearInterwikiCache extends Maintenance {
 
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Clear all interwiki links for all languages from the cache";
+               $this->addDescription( 'Clear all interwiki links for all languages from the cache' );
        }
 
        public function execute() {
index 98441b6..e5f0bb3 100644 (file)
@@ -27,7 +27,7 @@ require_once __DIR__ . '/Maintenance.php';
 class CompareParserCache extends Maintenance {
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Parse random pages and compare output to cache.";
+               $this->addDescription( 'Parse random pages and compare output to cache.' );
                $this->addOption( 'namespace', 'Page namespace number', true, true );
                $this->addOption( 'maxpages', 'Number of pages to try', true, true );
        }
index e67c439..f2540c7 100644 (file)
@@ -43,7 +43,7 @@ class CompareParsers extends DumpIterator {
        public function __construct() {
                parent::__construct();
                $this->saveFailed = false;
-               $this->mDescription = "Run a file or dump with several parsers";
+               $this->addDescription( 'Run a file or dump with several parsers' );
                $this->addOption( 'parser1', 'The first parser to compare.', true, true );
                $this->addOption( 'parser2', 'The second parser to compare.', true, true );
                $this->addOption( 'tidy', 'Run tidy on the articles.', false, false );
index 3113533..eeb2e6d 100644 (file)
@@ -55,7 +55,7 @@ class ConvertExtensionToRegistration extends Maintenance {
 
        public function __construct() {
                parent::__construct();
-               $this->mDescription = 'Converts extension entry points to the new JSON registration format';
+               $this->addDescription( 'Converts extension entry points to the new JSON registration format' );
                $this->addArg( 'path', 'Location to the PHP entry point you wish to convert',
                        /* $required = */ true );
                $this->addOption( 'skin', 'Whether to write to skin.json', false, false );
index 15ca14b..fa9c574 100644 (file)
@@ -36,9 +36,9 @@ class ConvertLinks extends Maintenance {
 
        public function __construct() {
                parent::__construct();
-               $this->mDescription =
-                       "Convert from the old links schema (string->ID) to the new schema (ID->ID)."
-                               . "The wiki should be put into read-only mode while this script executes";
+               $this->addDescription(
+                       'Convert from the old links schema (string->ID) to the new schema (ID->ID). '
+                               . 'The wiki should be put into read-only mode while this script executes' );
 
                $this->addArg( 'logperformance', "Log performance to perfLogFilename.", false );
                $this->addArg(
index 11768c8..c245a1e 100644 (file)
@@ -34,7 +34,7 @@ class ConvertUserOptions extends Maintenance {
 
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Convert user options from old to new system";
+               $this->addDescription( 'Convert user options from old to new system' );
                $this->setBatchSize( 50 );
        }
 
index b39ff55..25073f7 100644 (file)
@@ -40,7 +40,7 @@ class CopyFileBackend extends Maintenance {
 
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Copy files in one backend to another.";
+               $this->addDescription( 'Copy files in one backend to another.' );
                $this->addOption( 'src', 'Backend containing the source files', true, true );
                $this->addOption( 'dst', 'Backend where files should be copied to', true, true );
                $this->addOption( 'containers', 'Pipe separated list of containers', true, true );
index a9c9547..42c2dd4 100644 (file)
@@ -34,7 +34,7 @@ require_once __DIR__ . '/Maintenance.php';
 class CopyJobQueue extends Maintenance {
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Copy jobs from one queue system to another.";
+               $this->addDescription( 'Copy jobs from one queue system to another.' );
                $this->addOption( 'src', 'Key to $wgJobQueueMigrationConfig for source', true, true );
                $this->addOption( 'dst', 'Key to $wgJobQueueMigrationConfig for destination', true, true );
                $this->addOption( 'type', 'Types of jobs to copy (use "all" for all)', true, true );
index c1a2022..e7d666a 100644 (file)
@@ -35,7 +35,7 @@ class CreateAndPromote extends Maintenance {
 
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Create a new user account and/or grant it additional rights";
+               $this->addDescription( 'Create a new user account and/or grant it additional rights' );
                $this->addOption(
                        'force',
                        'If acccount exists already, just grant it rights or change password.'
index c678712..87e7e08 100644 (file)
@@ -37,7 +37,7 @@ class GenerateCommonPassword extends Maintenance {
        public function __construct() {
                global $IP;
                parent::__construct();
-               $this->mDescription = "Generate CDB file of common passwords";
+               $this->addDescription( 'Generate CDB file of common passwords' );
                $this->addOption( 'limit', "Max number of passwords to write", false, true, 'l' );
                $this->addArg( 'inputfile', 'List of passwords (one per line) to use or - for stdin', true );
                $this->addArg(
index 94ebf87..92f1a91 100644 (file)
@@ -34,7 +34,7 @@ require_once __DIR__ . '/Maintenance.php';
 class DeleteArchivedFiles extends Maintenance {
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Deletes all archived images.";
+               $this->addDescription( 'Deletes all archived images.' );
                $this->addOption( 'delete', 'Perform the deletion' );
                $this->addOption( 'force', 'Force deletion of rows from filearchive' );
        }
index 9924eb0..2fb83fc 100644 (file)
@@ -35,8 +35,8 @@ require_once __DIR__ . '/Maintenance.php';
 class DeleteArchivedRevisions extends Maintenance {
        public function __construct() {
                parent::__construct();
-               $this->mDescription =
-                       "Deletes all archived revisions\nThese revisions will no longer be restorable";
+               $this->addDescription(
+                       "Deletes all archived revisions\nThese revisions will no longer be restorable" );
                $this->addOption( 'delete', 'Performs the deletion' );
        }
 
index 6c89e67..e8839c5 100644 (file)
@@ -39,7 +39,7 @@ class DeleteBatch extends Maintenance {
 
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Deletes a batch of pages";
+               $this->addDescription( 'Deletes a batch of pages' );
                $this->addOption( 'u', "User to perform deletion", false, true );
                $this->addOption( 'r', "Reason to delete page", false, true );
                $this->addOption( 'i', "Interval to sleep between deletions" );
index a5c6199..7e1d315 100644 (file)
@@ -33,8 +33,8 @@ require_once __DIR__ . '/Maintenance.php';
 class DeleteDefaultMessages extends Maintenance {
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Deletes all pages in the MediaWiki namespace" .
-                       " which were last edited by \"MediaWiki default\"";
+               $this->addDescription( 'Deletes all pages in the MediaWiki namespace' .
+                       ' which were last edited by "MediaWiki default"' );
        }
 
        public function execute() {
index e7bb866..f21f3e1 100644 (file)
@@ -30,8 +30,8 @@ require_once __DIR__ . '/Maintenance.php';
 class DeleteEqualMessages extends Maintenance {
        public function __construct() {
                parent::__construct();
-               $this->mDescription = 'Deletes all pages in the MediaWiki namespace that are equal to '
-                       . 'the default message';
+               $this->addDescription( 'Deletes all pages in the MediaWiki namespace that are equal to '
+                       . 'the default message' );
                $this->addOption( 'delete', 'Actually delete the pages (default: dry run)' );
                $this->addOption( 'delete-talk', 'Don\'t leave orphaned talk pages behind during deletion' );
                $this->addOption( 'lang-code', 'Check for subpages of this language code (default: root '
index f411148..123163f 100644 (file)
@@ -32,7 +32,7 @@ require_once __DIR__ . '/Maintenance.php';
 class DeleteOldRevisions extends Maintenance {
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Delete old (non-current) revisions from the database";
+               $this->addDescription( 'Delete old (non-current) revisions from the database' );
                $this->addOption( 'delete', 'Actually perform the deletion' );
                $this->addOption( 'page_id', 'List of page ids to work on', false );
        }
index 3d5c1a4..5f08b5a 100644 (file)
@@ -34,7 +34,8 @@ require_once __DIR__ . '/Maintenance.php';
 class DeleteOrphanedRevisions extends Maintenance {
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Maintenance script to delete revisions which refer to a nonexisting page";
+               $this->addDescription(
+                       'Maintenance script to delete revisions which refer to a nonexisting page' );
                $this->addOption( 'report', 'Prints out a count of affected revisions but doesn\'t delete them' );
        }
 
index 6cda784..4606d92 100644 (file)
@@ -33,7 +33,7 @@ class DeleteRevision extends Maintenance {
 
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Delete one or more revisions by moving them to the archive table";
+               $this->addDescription( 'Delete one or more revisions by moving them to the archive table' );
        }
 
        public function execute() {
index f9bb416..ed15fd1 100644 (file)
@@ -32,7 +32,7 @@ require_once __DIR__ . '/Maintenance.php';
 class DeleteSelfExternals extends Maintenance {
        public function __construct() {
                parent::__construct();
-               $this->mDescription = 'Delete self-references to $wgServer from externallinks';
+               $this->addDescription( 'Delete self-references to $wgServer from externallinks' );
                $this->mBatchSize = 1000;
        }
 
index 18737a4..1904325 100644 (file)
@@ -31,7 +31,7 @@ class DumpBackup extends BackupDumper {
        function __construct( $args = null ) {
                parent::__construct();
 
-               $this->mDescription = <<<TEXT
+               $this->addDescription( <<<TEXT
 This script dumps the wiki page or logging database into an
 XML interchange wrapper format for export or backup.
 
@@ -40,7 +40,8 @@ XML output is sent to stdout; progress reports are sent to stderr.
 WARNING: this is not a full database dump! It is merely for public export
          of your wiki. For full backup, see our online help at:
          https://www.mediawiki.org/wiki/Backup
-TEXT;
+TEXT
+               );
                $this->stderr = fopen( "php://stderr", "wt" );
                // Actions
                $this->addOption( 'full', 'Dump all revisions of every page' );
index d8bc3a4..eef535a 100644 (file)
@@ -40,7 +40,7 @@ abstract class DumpIterator extends Maintenance {
 
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Does something with a dump";
+               $this->addDescription( 'Does something with a dump' );
                $this->addOption( 'file', 'File with text to run.', false, true );
                $this->addOption( 'dump', 'XML dump to execute all revisions.', false, true );
                $this->addOption( 'from', 'Article from XML dump to start from.', false, true );
@@ -164,7 +164,7 @@ class SearchDump extends DumpIterator {
 
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Runs a regex in the revisions from a dump";
+               $this->addDescription( 'Runs a regex in the revisions from a dump' );
                $this->addOption( 'regex', 'Searching regex', true, true );
        }
 
index 74b500a..7139786 100644 (file)
@@ -40,7 +40,7 @@ require_once __DIR__ . '/Maintenance.php';
 class DumpLinks extends Maintenance {
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Quick demo hack to generate a plaintext link dump";
+               $this->addDescription( 'Quick demo hack to generate a plaintext link dump' );
        }
 
        public function execute() {
index 7511392..8169ef5 100644 (file)
@@ -93,13 +93,14 @@ class TextPassDumper extends BackupDumper {
        function __construct( $args = null ) {
                parent::__construct();
 
-               $this->mDescription = <<<TEXT
+               $this->addDescription( <<<TEXT
 This script postprocesses XML dumps from dumpBackup.php to add
 page text which was stubbed out (using --stub).
 
 XML input is accepted on stdin.
 XML output is sent to stdout; progress reports are sent to stderr.
-TEXT;
+TEXT
+               );
                $this->stderr = fopen( "php://stderr", "wt" );
 
                $this->addOption( 'stub', 'To load a compressed stub dump instead of stdin. ' .
index 026ac02..64884d5 100644 (file)
@@ -32,8 +32,8 @@ require_once __DIR__ . '/Maintenance.php';
 class UploadDumper extends Maintenance {
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Generates list of uploaded files which can be fed to tar or similar.
-By default, outputs relative paths against the parent directory of \$wgUploadDirectory.";
+               $this->addDescription( 'Generates list of uploaded files which can be fed to tar or similar.
+By default, outputs relative paths against the parent directory of $wgUploadDirectory.' );
                $this->addOption( 'base', 'Set base relative path instead of wiki include root', false, true );
                $this->addOption( 'local', 'List all local files, used or not. No shared files included' );
                $this->addOption( 'used', 'Skip local images that are not used' );
index b67a957..fc83a91 100644 (file)
@@ -31,7 +31,7 @@ require_once __DIR__ . '/Maintenance.php';
 class EditCLI extends Maintenance {
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Edit an article from the command line, text is from stdin";
+               $this->addDescription( 'Edit an article from the command line, text is from stdin' );
                $this->addOption( 'user', 'Username', false, true, 'u' );
                $this->addOption( 'summary', 'Edit summary', false, true, 's' );
                $this->addOption( 'minor', 'Minor edit', false, false, 'm' );
index 69a95e2..2fcdd14 100644 (file)
@@ -35,7 +35,7 @@ require_once __DIR__ . '/Maintenance.php';
 class EraseArchivedFile extends Maintenance {
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Erases traces of deleted files.";
+               $this->addDescription( 'Erases traces of deleted files.' );
                $this->addOption( 'delete', 'Perform the deletion' );
                $this->addOption( 'filename', 'File name', false, true );
                $this->addOption( 'filekey', 'File storage key (with extension) or "*"', true, true );
index 145c924..157a323 100644 (file)
@@ -15,7 +15,7 @@ require_once $basePath . '/maintenance/Maintenance.php';
 class ExportSites extends Maintenance {
 
        public function __construct() {
-               $this->mDescription = 'Exports site definitions the sites table to XML file';
+               $this->addDescription( 'Exports site definitions the sites table to XML file' );
 
                $this->addArg( 'file', 'A file to write the XML to (see docs/sitelist.txt). ' .
                        'Use "php://stdout" to write to stdout.', true
index cf12838..989e90a 100644 (file)
@@ -32,9 +32,10 @@ require_once __DIR__ . '/Maintenance.php';
 class FetchText extends Maintenance {
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Fetch the raw revision blob from an old_id.\n" .
+               $this->addDescription( "Fetch the raw revision blob from an old_id.\n" .
                        "NOTE: Export transformations are NOT applied. " .
-                       "This is left to backupTextPass.php";
+                       "This is left to backupTextPass.php"
+               );
        }
 
        /**
index 9dba818..feb927e 100644 (file)
@@ -32,7 +32,7 @@ require_once __DIR__ . '/Maintenance.php';
 class TestFileOpPerformance extends Maintenance {
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Test fileop performance";
+               $this->addDescription( 'Test fileop performance' );
                $this->addOption( 'b1', 'Backend 1', true, true );
                $this->addOption( 'b2', 'Backend 2', false, true );
                $this->addOption( 'srcdir', 'File source directory', true, true );
index 8c7e242..9022292 100644 (file)
@@ -124,7 +124,7 @@ class DeprecatedInterfaceFinder extends FileAwareNodeVisitor {
 class FindDeprecated extends Maintenance {
        public function __construct() {
                parent::__construct();
-               $this->mDescription = 'Find deprecated interfaces';
+               $this->addDescription( 'Find deprecated interfaces' );
        }
 
        public function getFiles() {
index f9c61c7..1cf818e 100644 (file)
@@ -49,7 +49,7 @@ class FindHooks extends Maintenance {
 
        public function __construct() {
                parent::__construct();
-               $this->mDescription = 'Find hooks that are undocumented, missing, or just plain wrong';
+               $this->addDescription( 'Find hooks that are undocumented, missing, or just plain wrong' );
                $this->addOption( 'online', 'Check against MediaWiki.org hook documentation' );
        }
 
index 5818ee2..2fad7ce 100644 (file)
@@ -25,7 +25,7 @@ class FindMissingFiles extends Maintenance {
        function __construct() {
                parent::__construct();
 
-               $this->mDescription = 'Find registered files with no corresponding file.';
+               $this->addDescription( 'Find registered files with no corresponding file.' );
                $this->addOption( 'start', 'Start after this file name', false, true );
                $this->addOption( 'mtimeafter', 'Only include files changed since this time', false, true );
                $this->addOption( 'mtimebefore', 'Only includes files changed before this time', false, true );
index 41650bd..2362957 100644 (file)
@@ -25,7 +25,7 @@ class FindOrphanedFiles extends Maintenance {
        function __construct() {
                parent::__construct();
 
-               $this->mDescription = "Find unregistered files in the 'public' repo zone.";
+               $this->addDescription( "Find unregistered files in the 'public' repo zone." );
                $this->addOption( 'subdir',
                        'Only scan files in this subdirectory (e.g. "a/a0")', false, true );
                $this->addOption( 'verbose', "Mention file paths checked" );
index 25ec342..18334d6 100644 (file)
@@ -32,8 +32,8 @@ require_once __DIR__ . '/Maintenance.php';
 class FixDefaultJsonContentPages extends LoggedUpdateMaintenance {
        public function __construct() {
                parent::__construct();
-               $this->mDescription =
-                               'Fix instances of JSON pages prior to them being the ContentHandler default';
+               $this->addDescription(
+                       'Fix instances of JSON pages prior to them being the ContentHandler default' );
                $this->setBatchSize( 100 );
        }
 
index ca551f8..8faca27 100644 (file)
@@ -35,7 +35,7 @@ require_once __DIR__ . '/Maintenance.php';
 class FixDoubleRedirects extends Maintenance {
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Script to fix double redirects";
+               $this->addDescription( 'Script to fix double redirects' );
                $this->addOption( 'async', 'Don\'t fix anything directly, just queue the jobs' );
                $this->addOption( 'title', 'Fix only redirects pointing to this page', false, true );
                $this->addOption( 'dry-run', 'Perform a dry run, fix nothing' );
index a44f8e5..d04e0c2 100644 (file)
@@ -34,8 +34,8 @@ require_once __DIR__ . '/Maintenance.php';
 class FixExtLinksProtocolRelative extends LoggedUpdateMaintenance {
        public function __construct() {
                parent::__construct();
-               $this->mDescription =
-                       "Fixes any entries in the externallinks table containing protocol-relative URLs";
+               $this->addDescription(
+                       'Fixes any entries in the externallinks table containing protocol-relative URLs' );
        }
 
        protected function getUpdateKey() {
index c2a748c..0fb3d38 100644 (file)
@@ -36,7 +36,7 @@ require_once __DIR__ . '/Maintenance.php';
 class FixTimestamps extends Maintenance {
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "";
+               $this->addDescription( '' );
                $this->addArg( 'offset', '' );
                $this->addArg( 'start', 'Starting timestamp' );
                $this->addArg( 'end', 'Ending timestamp' );
index d09760b..44ac220 100644 (file)
@@ -32,7 +32,7 @@ require_once __DIR__ . '/Maintenance.php';
 class FixUserRegistration extends Maintenance {
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Fix the user_registration field";
+               $this->addDescription( 'Fix the user_registration field' );
                $this->setBatchSize( 1000 );
        }
 
index b9c07fb..0b4f2ed 100644 (file)
@@ -35,7 +35,7 @@ require_once __DIR__ . '/Maintenance.php';
 class GenerateJsonI18n extends Maintenance {
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Build JSON messages files from a PHP messages file";
+               $this->addDescription( 'Build JSON messages files from a PHP messages file' );
 
                $this->addArg( 'phpfile', 'PHP file defining a $messages array', false );
                $this->addArg( 'jsondir', 'Directory to write JSON files to', false );
index c40d0ce..256824e 100644 (file)
@@ -145,7 +145,7 @@ class GenerateSitemap extends Maintenance {
         */
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Creates a sitemap for the site";
+               $this->addDescription( 'Creates a sitemap for the site' );
                $this->addOption(
                        'fspath',
                        'The file system path to save to, e.g. /tmp/sitemap; defaults to current directory',
index 5838201..b1140ec 100644 (file)
@@ -49,7 +49,7 @@ class GetConfiguration extends Maintenance {
 
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Get serialized MediaWiki site configuration";
+               $this->addDescription( 'Get serialized MediaWiki site configuration' );
                $this->addOption( 'regex', 'regex to filter variables with', false, true );
                $this->addOption( 'iregex', 'same as --regex but case insensitive', false, true );
                $this->addOption( 'settings', 'Space-separated list of wg* variables', false, true );
index 7365a2e..c2c6958 100644 (file)
@@ -31,7 +31,7 @@ require_once __DIR__ . '/Maintenance.php';
 class GetLagTimes extends Maintenance {
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Dump replication lag times";
+               $this->addDescription( 'Dump replication lag times' );
        }
 
        public function execute() {
index c858c38..81228cc 100644 (file)
@@ -32,7 +32,7 @@ class GetSlaveServer extends Maintenance {
        public function __construct() {
                parent::__construct();
                $this->addOption( "group", "Query group to check specifically" );
-               $this->mDescription = "Report the hostname of a slave server";
+               $this->addDescription( 'Report the hostname of a slave server' );
        }
 
        public function execute() {
index c4b8cc9..f519a79 100644 (file)
@@ -33,7 +33,7 @@ require_once __DIR__ . '/Maintenance.php';
 class GetTextMaint extends Maintenance {
        public function __construct() {
                parent::__construct();
-               $this->mDescription = 'Outputs page text to stdout';
+               $this->addDescription( 'Outputs page text to stdout' );
                $this->addOption( 'show-private', 'Show the text even if it\'s not available to the public' );
                $this->addArg( 'title', 'Page title' );
        }
index 5806ffc..7c452a6 100644 (file)
@@ -49,7 +49,8 @@ class BackupReader extends Maintenance {
                        ? 'ok'
                        : '(disabled; requires PHP bzip2 module)';
 
-               $this->mDescription = <<<TEXT
+               $this->addDescription(
+                       <<<TEXT
 This script reads pages from an XML file as produced from Special:Export or
 dumpBackup.php, and saves them into the current wiki.
 
@@ -61,7 +62,8 @@ Compressed XML files may be read directly:
 Note that for very large data sets, importDump.php may be slow; there are
 alternate methods which can be much faster for full site restoration:
 <https://www.mediawiki.org/wiki/Manual:Importing_XML_dumps>
-TEXT;
+TEXT
+               );
                $this->stderr = fopen( "php://stderr", "wt" );
                $this->addOption( 'report',
                        'Report position and speed after every n pages processed', false, true );
index 5dfd2a8..366594d 100644 (file)
@@ -32,7 +32,7 @@ require_once __DIR__ . '/Maintenance.php';
 class ImportSiteScripts extends Maintenance {
        public function __construct() {
                parent::__construct();
-               $this->mDescription = 'Import site scripts from a site';
+               $this->addDescription( 'Import site scripts from a site' );
                $this->addArg( 'api', 'API base url' );
                $this->addArg( 'index', 'index.php base url' );
                $this->addOption( 'username', 'User name of the script importer' );
index c5c00aa..8845c60 100644 (file)
@@ -15,7 +15,7 @@ require_once $basePath . '/maintenance/Maintenance.php';
 class ImportSites extends Maintenance {
 
        public function __construct() {
-               $this->mDescription = 'Imports site definitions from XML into the sites table.';
+               $this->addDescription( 'Imports site definitions from XML into the sites table.' );
 
                $this->addArg( 'file', 'An XML file containing site definitions (see docs/sitelist.txt). ' .
                        'Use "php://stdin" to read from stdin.', true
index 14d8420..70b6574 100644 (file)
@@ -32,7 +32,7 @@ require_once __DIR__ . '/Maintenance.php';
 class ImportTextFiles extends Maintenance {
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Reads in text files and imports their content to pages of the wiki";
+               $this->addDescription( 'Reads in text files and imports their content to pages of the wiki' );
                $this->addOption( 'user', 'Username to which edits should be attributed. ' .
                        'Default: "Maintenance script"', false, true, 'u' );
                $this->addOption( 'summary', 'Specify edit summary for the edits', false, true, 's' );
index dee5db8..5d0dcc6 100644 (file)
@@ -35,7 +35,7 @@ class InitEditCount extends Maintenance {
 Background mode will be automatically used if the server is MySQL 4.0
 (which does not support subqueries) or if multiple servers are listed
 in the load balancer, usually indicating a replication environment.' );
-               $this->mDescription = "Batch-recalculate user_editcount fields from the revision table";
+               $this->addDescription( 'Batch-recalculate user_editcount fields from the revision table' );
        }
 
        public function execute() {
index 8d26063..7e62b89 100644 (file)
@@ -33,7 +33,7 @@ require_once __DIR__ . '/Maintenance.php';
 class InitSiteStats extends Maintenance {
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Re-initialise the site statistics tables";
+               $this->addDescription( 'Re-initialise the site statistics tables' );
                $this->addOption( 'update', 'Update the existing statistics' );
                $this->addOption( 'active', 'Also update active users count' );
                $this->addOption( 'use-master', 'Count using the master database' );
index fddfc02..770251c 100644 (file)
@@ -33,7 +33,7 @@ class JSParseHelper extends Maintenance {
 
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Runs parsing/syntax checks on JavaScript files";
+               $this->addDescription( 'Runs parsing/syntax checks on JavaScript files' );
                $this->addArg( 'file(s)', 'JavaScript file to test', false );
        }
 
index 52f8201..9d92794 100644 (file)
@@ -31,7 +31,7 @@ require_once __DIR__ . '/Maintenance.php';
 class DatabaseLag extends Maintenance {
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Shows database lag";
+               $this->addDescription( 'Shows database lag' );
                $this->addOption( 'r', "Don't exit immediately, but show the lag every 5 seconds" );
        }
 
index d0e6e84..931718f 100644 (file)
@@ -32,7 +32,7 @@ require_once __DIR__ . '/../Maintenance.php';
 class AllTrans extends Maintenance {
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Get all messages as defined by the English language file";
+               $this->addDescription( 'Get all messages as defined by the English language file' );
        }
 
        public function execute() {
index 1463418..dc275ab 100644 (file)
@@ -34,7 +34,7 @@ class DateFormats extends Maintenance {
 
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Test various language time and date functions";
+               $this->addDescription( 'Test various language time and date functions' );
        }
 
        public function execute() {
index a6e0456..eddfa26 100644 (file)
@@ -41,7 +41,7 @@ class Digit2Html extends Maintenance {
 
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Check digit transformation";
+               $this->addDescription( 'Check digit transformation' );
        }
 
        public function execute() {
index a72e25b..5768232 100644 (file)
@@ -33,7 +33,7 @@ require_once __DIR__ . '/../Maintenance.php';
 class DumpMessages extends Maintenance {
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Dump an entire language, using the keys from English";
+               $this->addDescription( 'Dump an entire language, using the keys from English' );
        }
 
        public function execute() {
index 52ed81f..722db06 100644 (file)
@@ -33,7 +33,7 @@ require_once __DIR__ . '/../Maintenance.php';
 class GenerateNormalizerDataAr extends Maintenance {
        public function __construct() {
                parent::__construct();
-               $this->mDescription = 'Generate the normalizer data file for Arabic';
+               $this->addDescription( 'Generate the normalizer data file for Arabic' );
                $this->addOption( 'unicode-data-file', 'The local location of the data file ' .
                        'from http://unicode.org/Public/UNIDATA/UnicodeData.txt', false, true );
        }
index cb6ae69..412e7ef 100644 (file)
@@ -33,7 +33,7 @@ require_once __DIR__ . '/../Maintenance.php';
 class GenerateNormalizerDataMl extends Maintenance {
        public function __construct() {
                parent::__construct();
-               $this->mDescription = 'Generate the normalizer data file for Malayalam';
+               $this->addDescription( 'Generate the normalizer data file for Malayalam' );
        }
 
        public function getDbType() {
index 3520b87..676297e 100644 (file)
@@ -37,8 +37,8 @@ class GenerateUtf8Case extends Maintenance {
 
        public function __construct() {
                parent::__construct();
-               $this->mDescription = 'Generate Utf8Case.ser from the Unicode Character Database ' .
-                       'and supplementary files';
+               $this->addDescription( 'Generate Utf8Case.ser from the Unicode Character Database ' .
+                       'and supplementary files' );
                $this->addOption( 'unicode-data-file', 'The local location of the data file ' .
                        'from http://unicode.org/Public/UNIDATA/UnicodeData.txt', false, true );
        }
index 32cfcd7..7c16602 100644 (file)
@@ -34,8 +34,8 @@ class LangMemUsage extends Maintenance {
 
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Dumb program that tries to get the memory usage\n" .
-                       "for each language file";
+               $this->addDescription( "Dumb program that tries to get the memory usage\n" .
+                       "for each language file" );
        }
 
        public function execute() {
index 4bff891..e8137ba 100644 (file)
@@ -32,7 +32,7 @@ class ListVariants extends Maintenance {
 
        public function __construct() {
                parent::__construct();
-               $this->mDescription = 'Outputs a list of language variants';
+               $this->addDescription( 'Outputs a list of language variants' );
                $this->addOption( 'flat', 'Output variants in a flat list' );
                $this->addOption( 'json', 'Output variants as JSON' );
        }
index c6569a0..ca2f7c5 100644 (file)
@@ -30,7 +30,7 @@ require_once __DIR__ . '/Maintenance.php';
 class MakeTestEdits extends Maintenance {
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Make test edits for a user";
+               $this->addDescription( 'Make test edits for a user' );
                $this->addOption( 'user', 'User name', true, true );
                $this->addOption( 'count', 'Number of edits', true, true );
                $this->addOption( 'namespace', 'Namespace number', false, true );
index a97d2e1..619ada6 100644 (file)
@@ -33,8 +33,8 @@ require_once __DIR__ . '/Maintenance.php';
 class McTest extends Maintenance {
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Makes several 'set', 'incr' and 'get' requests on every"
-                       . " memcached server and shows a report";
+               $this->addDescription( "Makes several 'set', 'incr' and 'get' requests on every"
+                       . " memcached server and shows a report" );
                $this->addOption( 'i', 'Number of iterations', false, true );
                $this->addOption( 'cache', 'Use servers from this $wgObjectCaches store', false, true );
                $this->addArg( 'server[:port]', 'Memcached server to test, with optional port', false );
index b491497..20b333e 100644 (file)
@@ -51,8 +51,9 @@ class MergeMessageFileList extends Maintenance {
                );
                $this->addOption( 'extensions-dir', 'Path where extensions can be found.', false, true );
                $this->addOption( 'output', 'Send output to this file (omit for stdout)', false, true );
-               $this->mDescription = 'Merge $wgExtensionMessagesFiles and $wgMessagesDirs from ' .
-                       ' various extensions to produce a single file listing all message files and dirs.';
+               $this->addDescription( 'Merge $wgExtensionMessagesFiles and $wgMessagesDirs from ' .
+                       ' various extensions to produce a single file listing all message files and dirs.'
+               );
        }
 
        public function execute() {
index 68b97e3..77d88f5 100644 (file)
@@ -33,7 +33,7 @@ require_once __DIR__ . '/Maintenance.php';
 class MigrateFileRepoLayout extends Maintenance {
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Copy files in repo to a different layout.";
+               $this->addDescription( 'Copy files in repo to a different layout.' );
                $this->addOption( 'oldlayout', "Old layout; one of 'name' or 'sha1'", true, true );
                $this->addOption( 'newlayout', "New layout; one of 'name' or 'sha1'", true, true );
                $this->addOption( 'since', "Copy only files from after this timestamp", false, true );
index dc20eee..df6665a 100644 (file)
@@ -31,7 +31,7 @@ require_once __DIR__ . '/Maintenance.php';
 class MigrateUserGroup extends Maintenance {
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Re-assign users from an old group to a new one";
+               $this->addDescription( 'Re-assign users from an old group to a new one' );
                $this->addArg( 'oldgroup', 'Old user group key', true );
                $this->addArg( 'newgroup', 'New user group key', true );
                $this->setBatchSize( 200 );
index c357eeb..16e4d1c 100644 (file)
@@ -40,9 +40,10 @@ class MinifyScript extends Maintenance {
                        "Directory for output. If this is not specified, and neither is --outfile, then the\n" .
                        "output files will be sent to the same directories as the input files.",
                        false, true );
-               $this->mDescription = "Minify a file or set of files.\n\n" .
+               $this->addDescription( "Minify a file or set of files.\n\n" .
                        "If --outfile is not specified, then the output file names will have a .min extension\n" .
-                       "added, e.g. jquery.js -> jquery.min.js.";
+                       "added, e.g. jquery.js -> jquery.min.js."
+               );
        }
 
        public function execute() {
index 43d4d25..8645ab1 100644 (file)
@@ -45,7 +45,7 @@ require_once __DIR__ . '/Maintenance.php';
 class MoveBatch extends Maintenance {
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Moves a batch of pages";
+               $this->addDescription( 'Moves a batch of pages' );
                $this->addOption( 'u', "User to perform move", false, true );
                $this->addOption( 'r', "Reason to move page", false, true );
                $this->addOption( 'i', "Interval to sleep between moves" );
index 00a15e5..35fca8e 100644 (file)
@@ -46,7 +46,7 @@ class MWDocGen extends Maintenance {
         */
        public function __construct() {
                parent::__construct();
-               $this->mDescription = 'Build doxygen documentation';
+               $this->addDescription( 'Build doxygen documentation' );
 
                $this->addOption( 'doxygen',
                        'Path to doxygen',
index 6e5cd38..b59f4a9 100644 (file)
@@ -47,7 +47,7 @@ class NamespaceConflictChecker extends Maintenance {
 
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "";
+               $this->addDescription( 'Find and fix pages affected by namespace addition/removal' );
                $this->addOption( 'fix', 'Attempt to automatically fix errors' );
                $this->addOption( 'merge', "Instead of renaming conflicts, do a history merge with " .
                        "the correct title" );
index 0f2dbf6..8b45e57 100644 (file)
@@ -44,7 +44,7 @@ require_once __DIR__ . '/Maintenance.php';
 class NukeNS extends Maintenance {
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Remove pages with only 1 revision from any namespace";
+               $this->addDescription( 'Remove pages with only 1 revision from any namespace' );
                $this->addOption( 'delete', "Actually delete the page" );
                $this->addOption( 'ns', 'Namespace to delete from, default NS_MEDIAWIKI', false, true );
                $this->addOption( 'all', 'Delete everything regardless of revision count' );
index dc45520..44235d5 100644 (file)
@@ -33,7 +33,7 @@ require_once __DIR__ . '/Maintenance.php';
 class NukePage extends Maintenance {
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Remove a page record from the database";
+               $this->addDescription( 'Remove a page record from the database' );
                $this->addOption( 'delete', "Actually delete the page" );
                $this->addArg( 'title', 'Title to delete' );
        }
index 67e5ded..ba1e879 100644 (file)
@@ -32,7 +32,7 @@ require_once __DIR__ . '/../Maintenance.php';
 class AlterSharedConstraints extends Maintenance {
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Alter foreign key to reference master tables in shared database setup.";
+               $this->addDescription( 'Alter foreign key to reference master tables in shared database setup.' );
        }
 
        public function getDbType() {
index 3c5566f..24ead60 100644 (file)
@@ -39,10 +39,11 @@ require_once __DIR__ . '/Maintenance.php';
 class Orphans extends Maintenance {
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Look for 'orphan' revisions hooked to pages which don't exist\n" .
+               $this->addDescription( "Look for 'orphan' revisions hooked to pages which don't exist\n" .
                        "and 'childless' pages with no revisions\n" .
                        "Then, kill the poor widows and orphans\n" .
-                       "Man this is depressing";
+                       "Man this is depressing"
+               );
                $this->addOption( 'fix', 'Actually fix broken entries' );
        }
 
index f414383..b631005 100644 (file)
@@ -27,7 +27,7 @@ require_once __DIR__ . '/Maintenance.php';
 class PageExists extends Maintenance {
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Report whether a specific page exists";
+               $this->addDescription( 'Report whether a specific page exists' );
                $this->addArg( 'title', 'Page title to check whether it exists' );
        }
 
index d655965..effed56 100644 (file)
@@ -61,7 +61,7 @@ class CLIParser extends Maintenance {
 
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Parse a given wikitext";
+               $this->addDescription( 'Parse a given wikitext' );
                $this->addOption(
                        'title',
                        'Title name for the given wikitext (Default: \'CLIParser\')',
index 1f77bdb..f94046a 100644 (file)
@@ -32,7 +32,7 @@ require_once __DIR__ . '/Maintenance.php';
 class PatchSql extends Maintenance {
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Run an SQL file into the DB, replacing prefix and charset vars";
+               $this->addDescription( 'Run an SQL file into the DB, replacing prefix and charset vars' );
                $this->addArg(
                        'patch-name',
                        'Name of the patch file, either full path or in maintenance/archives'
index 054f792..901cdaa 100644 (file)
@@ -31,7 +31,7 @@ require_once __DIR__ . '/Maintenance.php';
 class PopulateBacklinkNamespace extends LoggedUpdateMaintenance {
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Populate the *_from_namespace fields";
+               $this->addDescription( 'Populate the *_from_namespace fields' );
                $this->addOption( 'lastUpdatedId', "Highest page_id with updated links", false, true );
        }
 
index 481e073..5a8ef90 100644 (file)
@@ -35,7 +35,8 @@ class PopulateCategory extends Maintenance {
 
        public function __construct() {
                parent::__construct();
-               $this->mDescription = <<<TEXT
+               $this->addDescription(
+                       <<<TEXT
 This script will populate the category table, added in MediaWiki 1.13.  It will
 print out progress indicators every 1000 categories it adds to the table.  The
 script is perfectly safe to run on large, live wikis, and running it multiple
@@ -49,8 +50,9 @@ added after the software update and so will be populated anyway.
 
 When the script has finished, it will make a note of this in the database, and
 will not run again without the --force option.
-TEXT;
-# '
+TEXT
+               );
+
                $this->addOption(
                        'begin',
                        'Only do categories whose names are alphabetically after the provided name',
index 4f9c7ae..c158cb4 100644 (file)
@@ -30,7 +30,7 @@ require_once __DIR__ . '/Maintenance.php';
 class PopulateContentModel extends Maintenance {
        public function __construct() {
                parent::__construct();
-               $this->mDescription = 'Populate the various content_* fields';
+               $this->addDescription( 'Populate the various content_* fields' );
                $this->addOption( 'ns', 'Namespace to run in, or "all" for all namespaces', true, true );
                $this->addOption( 'table', 'Table to run in', true, true );
                $this->setBatchSize( 100 );
index 5a67262..24c25b1 100644 (file)
@@ -32,7 +32,7 @@ require_once __DIR__ . '/Maintenance.php';
 class PopulateFilearchiveSha1 extends LoggedUpdateMaintenance {
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Populate the fa_sha1 field from fa_storage_key";
+               $this->addDescription( 'Populate the fa_sha1 field from fa_storage_key' );
        }
 
        protected function getUpdateKey() {
index cc52239..51cc72a 100644 (file)
@@ -31,7 +31,7 @@ require_once __DIR__ . '/Maintenance.php';
 class PopulateImageSha1 extends LoggedUpdateMaintenance {
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Populate the img_sha1 field";
+               $this->addDescription( 'Populate the img_sha1 field' );
                $this->addOption( 'force', "Recalculate sha1 for rows that already have a value" );
                $this->addOption( 'multiversiononly', "Calculate only for files with several versions" );
                $this->addOption( 'method', "Use 'pipe' to pipe to mysql command line,\n" .
index 4c1a72e..41c3bc9 100644 (file)
@@ -40,7 +40,7 @@ class PopulateLogSearch extends LoggedUpdateMaintenance {
 
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Migrate log params to new table and index for searching";
+               $this->addDescription( 'Migrate log params to new table and index for searching' );
                $this->setBatchSize( 100 );
        }
 
index 60329c0..ec3c472 100644 (file)
@@ -35,7 +35,7 @@ require_once __DIR__ . '/Maintenance.php';
 class PopulateLogUsertext extends LoggedUpdateMaintenance {
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Populates the log_user_text field";
+               $this->addDescription( 'Populates the log_user_text field' );
                $this->setBatchSize( 100 );
        }
 
index 9baf28e..beb8cc8 100644 (file)
@@ -34,7 +34,7 @@ require_once __DIR__ . '/Maintenance.php';
 class PopulateParentId extends LoggedUpdateMaintenance {
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Populates rev_parent_id";
+               $this->addDescription( 'Populates rev_parent_id' );
        }
 
        protected function getUpdateKey() {
index 25a51d7..452d213 100644 (file)
@@ -32,8 +32,8 @@ require_once __DIR__ . '/Maintenance.php';
 class PopulateRecentChangesSource extends LoggedUpdateMaintenance {
        public function __construct() {
                parent::__construct();
-               $this->mDescription =
-                       "Populates rc_source field of the recentchanges table with the data in rc_type.";
+               $this->addDescription(
+                       'Populates rc_source field of the recentchanges table with the data in rc_type.' );
                $this->setBatchSize( 100 );
        }
 
index a9fb394..297bed2 100644 (file)
@@ -33,7 +33,7 @@ require_once __DIR__ . '/Maintenance.php';
 class PopulateRevisionLength extends LoggedUpdateMaintenance {
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Populates the rev_len and ar_len fields";
+               $this->addDescription( 'Populates the rev_len and ar_len fields' );
                $this->setBatchSize( 200 );
        }
 
index 43504b1..3aff77e 100644 (file)
@@ -33,7 +33,7 @@ require_once __DIR__ . '/Maintenance.php';
 class PopulateRevisionSha1 extends LoggedUpdateMaintenance {
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Populates the rev_sha1 and ar_sha1 fields";
+               $this->addDescription( 'Populates the rev_sha1 and ar_sha1 fields' );
                $this->setBatchSize( 200 );
        }
 
index 449a7ad..4a3148a 100644 (file)
@@ -31,7 +31,7 @@ require_once __DIR__ . '/Maintenance.php';
 class Protect extends Maintenance {
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Protect or unprotect a page from the command line.";
+               $this->addDescription( 'Protect or unprotect a page from the command line.' );
                $this->addOption( 'unprotect', 'Removes protection' );
                $this->addOption( 'semiprotect', 'Adds semi-protection' );
                $this->addOption( 'cascade', 'Add cascading protection' );
index 455e9c0..8e6978d 100644 (file)
@@ -34,7 +34,7 @@ class PruneFileCache extends Maintenance {
 
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Build file cache for content pages";
+               $this->addDescription( 'Build file cache for content pages' );
                $this->addOption( 'agedays', 'How many days old files must be in order to delete', true, true );
                $this->addOption( 'subdir', 'Prune one $wgFileCacheDirectory subdirectory name', false, true );
        }
index b98e95f..4f10b6e 100644 (file)
@@ -61,7 +61,7 @@ class PurgeChangedFiles extends Maintenance {
 
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Scan the logging table and purge files and thumbnails.";
+               $this->addDescription( 'Scan the logging table and purge files and thumbnails.' );
                $this->addOption( 'starttime', 'Starting timestamp', true, true );
                $this->addOption( 'endtime', 'Ending timestamp', true, true );
                $this->addOption( 'type', 'Comma-separated list of types of changes to send purges for (' .
index 31500c9..cb4f85d 100644 (file)
@@ -36,7 +36,7 @@ class PurgeChangedPages extends Maintenance {
 
        public function __construct() {
                parent::__construct();
-               $this->mDescription = 'Send purge requests for edits in date range to squid/varnish';
+               $this->addDescription( 'Send purge requests for edits in date range to squid/varnish' );
                $this->addOption( 'starttime', 'Starting timestamp', true, true );
                $this->addOption( 'endtime', 'Ending timestamp', true, true );
                $this->addOption( 'htcp-dest', 'HTCP announcement destination (IP:port)', false, true );
index 9963cbf..a733d67 100644 (file)
@@ -31,7 +31,7 @@ require_once __DIR__ . '/Maintenance.php';
 class PurgeList extends Maintenance {
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Send purge requests for listed pages to squid";
+               $this->addDescription( 'Send purge requests for listed pages to squid' );
                $this->addOption( 'purge', 'Whether to update page_touched.', false, false );
                $this->addOption( 'namespace', 'Namespace number', false, true );
                $this->addOption( 'all', 'Purge all pages', false, false );
index 3d81e2d..1b78c7d 100644 (file)
@@ -32,7 +32,7 @@ require_once __DIR__ . '/Maintenance.php';
 class PurgeOldText extends Maintenance {
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Purge old text records from the database";
+               $this->addDescription( 'Purge old text records from the database' );
                $this->addOption( 'purge', 'Performs the deletion' );
        }
 
index e68937a..4d3baaf 100644 (file)
@@ -34,7 +34,7 @@ require_once __DIR__ . '/Maintenance.php';
 class ReassignEdits extends Maintenance {
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Reassign edits from one user to another";
+               $this->addDescription( 'Reassign edits from one user to another' );
                $this->addOption( "force", "Reassign even if the target user doesn't exist" );
                $this->addOption( "norc", "Don't update the recent changes table" );
                $this->addOption( "report", "Print out details of what would be changed, but don't update it" );
index e07bf03..21cd3a1 100644 (file)
@@ -31,7 +31,7 @@ require_once __DIR__ . '/Maintenance.php';
 class RebuildFileCache extends Maintenance {
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Build file cache for content pages";
+               $this->addDescription( 'Build file cache for content pages' );
                $this->addOption( 'start', 'Page_id to start from', false, true );
                $this->addOption( 'end', 'Page_id to end on', false, true );
                $this->addOption( 'overwrite', 'Refresh page cache' );
index 1b0a27d..521ab54 100644 (file)
@@ -51,7 +51,7 @@ class ImageBuilder extends Maintenance {
                // make sure to update old, but compatible img_metadata fields.
                $wgUpdateCompatibleMetadata = true;
 
-               $this->mDescription = 'Script to update image metadata records';
+               $this->addDescription( 'Script to update image metadata records' );
 
                $this->addOption( 'missing', 'Check for files without associated database record' );
                $this->addOption( 'dry-run', 'Only report, don\'t update the database' );
index f89877e..36caa3a 100644 (file)
@@ -39,7 +39,7 @@ require_once __DIR__ . '/Maintenance.php';
 class RebuildLocalisationCache extends Maintenance {
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Rebuild the localisation cache";
+               $this->addDescription( 'Rebuild the localisation cache' );
                $this->addOption( 'force', 'Rebuild all files, even ones not out of date' );
                $this->addOption( 'threads', 'Fork more than one thread', false, true );
                $this->addOption( 'outdir', 'Override the output directory (normally $wgCacheDirectory)',
index 2bc7510..044bafd 100644 (file)
@@ -32,7 +32,7 @@ class RebuildSitesCache extends Maintenance {
        public function __construct() {
                parent::__construct();
 
-               $this->mDescription = "Cache sites as json for file-based lookup.";
+               $this->addDescription( 'Cache sites as json for file-based lookup.' );
                $this->addOption( 'file', 'File to output the json to', false, true );
        }
 
index 4ff873e..d2ee6fc 100644 (file)
@@ -32,7 +32,7 @@ require_once __DIR__ . '/Maintenance.php';
 class RebuildAll extends Maintenance {
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Rebuild links, text index and recent changes";
+               $this->addDescription( 'Rebuild links, text index and recent changes' );
        }
 
        public function getDbType() {
index f223f1a..3b40556 100644 (file)
@@ -31,7 +31,7 @@ require_once __DIR__ . '/Maintenance.php';
 class RebuildMessages extends Maintenance {
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Purge all language messages from the cache";
+               $this->addDescription( 'Purge all language messages from the cache' );
        }
 
        public function execute() {
index 34560fd..d61906c 100644 (file)
@@ -33,7 +33,7 @@ require_once __DIR__ . '/Maintenance.php';
 class RebuildRecentchanges extends Maintenance {
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Rebuild recent changes";
+               $this->addDescription( 'Rebuild recent changes' );
        }
 
        public function execute() {
index e8d59bc..dff734b 100644 (file)
@@ -42,7 +42,7 @@ class RebuildTextIndex extends Maintenance {
 
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Rebuild search index table from scratch";
+               $this->addDescription( 'Rebuild search index table from scratch' );
        }
 
        public function getDbType() {
index 6bc72ec..3f1b167 100644 (file)
@@ -34,7 +34,7 @@ require_once __DIR__ . '/Maintenance.php';
 class RefreshFileHeaders extends Maintenance {
        function __construct() {
                parent::__construct();
-               $this->mDescription = 'Script to update file HTTP headers';
+               $this->addDescription( 'Script to update file HTTP headers' );
                $this->addOption( 'verbose', 'Output information about each file.', false, false, 'v' );
                $this->addOption( 'start', 'Name of file to start with', false, true );
                $this->addOption( 'end', 'Name of file to end with', false, true );
index 4f2341c..01fb15e 100644 (file)
@@ -44,7 +44,7 @@ class RefreshImageMetadata extends Maintenance {
        function __construct() {
                parent::__construct();
 
-               $this->mDescription = 'Script to update image metadata records';
+               $this->addDescription( 'Script to update image metadata records' );
                $this->setBatchSize( 200 );
 
                $this->addOption(
index 1159e53..651255b 100644 (file)
@@ -31,7 +31,7 @@ require_once __DIR__ . '/Maintenance.php';
 class RefreshLinks extends Maintenance {
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Refresh link tables";
+               $this->addDescription( 'Refresh link tables' );
                $this->addOption( 'dfn-only', 'Delete links from nonexistent articles only' );
                $this->addOption( 'new-only', 'Only affect articles with just a single edit' );
                $this->addOption( 'redirects-only', 'Only fix redirects, not all links' );
index 2218a5e..09b1b1c 100644 (file)
@@ -43,7 +43,8 @@ class DumpRenderer extends Maintenance {
 
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Take page text out of an XML dump file and render basic HTML out to files";
+               $this->addDescription(
+                       'Take page text out of an XML dump file and render basic HTML out to files' );
                $this->addOption( 'output-dir', 'The directory to output the HTML files to', true, true );
                $this->addOption( 'prefix', 'Prefix for the rendered files (defaults to wiki)', false, true );
                $this->addOption( 'parser', 'Use an alternative parser class', false, true );
diff --git a/maintenance/resetUserEmail.php b/maintenance/resetUserEmail.php
new file mode 100644 (file)
index 0000000..816e8a4
--- /dev/null
@@ -0,0 +1,66 @@
+<?php
+/**
+ * Reset user email.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup Maintenance
+ */
+
+require_once __DIR__ . '/Maintenance.php';
+
+/**
+ * Maintenance script that resets user email.
+ *
+ * @since 1.27
+ * @ingroup Maintenance
+ */
+class ResetUserEmail extends Maintenance {
+       public function __construct() {
+               $this->addDescription( "Resets a user's email" );
+               $this->addArg( 'user', 'Username or user ID, if starts with #', true );
+               $this->addArg( 'email', 'Email to assign' );
+               parent::__construct();
+       }
+
+       public function execute() {
+               $userName = $this->getArg( 0 );
+               if ( preg_match( '/^#\d+$/', $userName ) ) {
+                       $user = User::newFromId( substr( $userName, 1 ) );
+               } else {
+                       $user = User::newFromName( $userName );
+               }
+               if ( !$user || !$user->getId() || !$user->loadFromId() ) {
+                       $this->error( "Error: user '$userName' does not exist\n", 1 );
+               }
+
+               $email = $this->getArg( 1 );
+               if ( !Sanitizer::validateEmail( $email ) ) {
+                       $this->error( "Error: email '$email' is not valid\n", 1 );
+               }
+
+               // Code from https://wikitech.wikimedia.org/wiki/Password_reset
+               $user->setEmail( $email );
+               $user->setEmailAuthenticationTimestamp( wfTimestampNow() );
+               $user->saveSettings();
+               // Kick whomever is currently controlling the account off
+               $user->setPassword( PasswordFactory::generateRandomPasswordString( 128 ) );
+       }
+}
+
+$maintClass = 'ResetUserEmail';
+require_once RUN_MAINTENANCE_IF_MAIN;
index 9c7aef2..7acf975 100644 (file)
@@ -34,8 +34,9 @@ require_once __DIR__ . '/Maintenance.php';
 class ResetUserTokens extends Maintenance {
        public function __construct() {
                parent::__construct();
-               $this->mDescription =
-                       "Reset the user_token of all users on the wiki. Note that this may log some of them out.";
+               $this->addDescription(
+                       'Reset the user_token of all users on the wiki. Note that this may log some of them out.'
+               );
                $this->addOption( 'nowarn', "Hides the 5 seconds warning", false, false );
                $this->addOption(
                        'nulls',
index 7134453..a2ddb93 100644 (file)
@@ -33,8 +33,8 @@ require_once __DIR__ . '/Maintenance.php';
 class RollbackEdits extends Maintenance {
        public function __construct() {
                parent::__construct();
-               $this->mDescription =
-                       "Rollback all edits by a given user or IP provided they're the most recent edit";
+               $this->addDescription(
+                       "Rollback all edits by a given user or IP provided they're the most recent edit" );
                $this->addOption(
                        'titles',
                        'A list of titles, none means all titles where the given user is the most recent',
index 3fd9e02..2feae02 100644 (file)
@@ -33,9 +33,9 @@ require_once __DIR__ . '/Maintenance.php';
 class BatchedQueryRunner extends Maintenance {
        public function __construct() {
                parent::__construct();
-               $this->mDescription =
+               $this->addDescription(
                        "Run a query repeatedly until it affects 0 rows, and wait for slaves in between.\n" .
-                               "NOTE: You need to set a LIMIT clause yourself.";
+                               "NOTE: You need to set a LIMIT clause yourself." );
        }
 
        public function execute() {
index 3c5d28b..86cade2 100644 (file)
@@ -33,7 +33,7 @@ use MediaWiki\Logger\LoggerFactory;
 class RunJobs extends Maintenance {
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Run pending jobs";
+               $this->addDescription( 'Run pending jobs' );
                $this->addOption( 'maxjobs', 'Maximum number of jobs to run', false, true );
                $this->addOption( 'maxtime', 'Maximum amount of wall-clock time', false, true );
                $this->addOption( 'type', 'Type of job to run', false, true );
index 25a096c..992c238 100644 (file)
@@ -43,7 +43,7 @@ class ShowJobs extends Maintenance {
 
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Show number of jobs waiting in master database";
+               $this->addDescription( 'Show number of jobs waiting in master database' );
                $this->addOption( 'group', 'Show number of jobs per job type' );
                $this->addOption( 'list', 'Show a list of all jobs instead of counts' );
                $this->addOption( 'type', 'Only show/count jobs of a given type', false, true );
index 56cc573..098aba5 100644 (file)
@@ -39,7 +39,7 @@ require_once __DIR__ . '/Maintenance.php';
 class ShowSiteStats extends Maintenance {
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Show the cached statistics";
+               $this->addDescription( 'Show the cached statistics' );
        }
 
        public function execute() {
index a93e51f..f089972 100644 (file)
@@ -32,8 +32,8 @@ require_once __DIR__ . '/Maintenance.php';
 class MwSql extends Maintenance {
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Send SQL queries to a MediaWiki database. " .
-                               "Takes a file name containing SQL as argument or runs interactively.";
+               $this->addDescription( 'Send SQL queries to a MediaWiki database. ' .
+                       'Takes a file name containing SQL as argument or runs interactively.' );
                $this->addOption( 'query', 'Run a single query instead of running interactively', false, true );
                $this->addOption( 'cluster', 'Use an external cluster by name', false, true );
                $this->addOption( 'wikidb', 'The database wiki ID to use if not the current one', false, true );
index 96a8a38..5cc35ed 100644 (file)
@@ -31,7 +31,7 @@ require_once __DIR__ . '/Maintenance.php';
 class SqliteMaintenance extends Maintenance {
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Performs some operations specific to SQLite database backend";
+               $this->addDescription( 'Performs some operations specific to SQLite database backend' );
                $this->addOption(
                        'vacuum',
                        'Clean up database by removing deleted pages. Decreases database file size'
index b27b111..dd3ba04 100644 (file)
@@ -63,7 +63,7 @@ class CompressOld extends Maintenance {
 
        public function __construct() {
                parent::__construct();
-               $this->mDescription = 'Compress the text of a wiki';
+               $this->addDescription( 'Compress the text of a wiki' );
                $this->addOption( 'type', 'Set compression type to either: gzip|concat', false, true, 't' );
                $this->addOption(
                        'chunksize',
index e926f56..d353b88 100644 (file)
@@ -36,7 +36,7 @@ class FixBug20757 extends Maintenance {
 
        function __construct() {
                parent::__construct();
-               $this->mDescription = 'Script to fix bug 20757 assuming that blob_tracking is intact';
+               $this->addDescription( 'Script to fix bug 20757 assuming that blob_tracking is intact' );
                $this->addOption( 'dry-run', 'Report only' );
                $this->addOption( 'start', 'old_id to start at', false, true );
        }
index b1bf95b..21f50f5 100644 (file)
@@ -32,8 +32,8 @@ require_once __DIR__ . '/../Maintenance.php';
 class OrphanStats extends Maintenance {
        public function __construct() {
                parent::__construct();
-               $this->mDescription =
-                       "Show some statistics on the blob_orphans table, created with trackBlobs.php";
+               $this->addDescription(
+                       "Show some statistics on the blob_orphans table, created with trackBlobs.php" );
        }
 
        protected function &getDB( $cluster, $groups = array(), $wiki = false ) {
index 63d5e9f..c0663a7 100644 (file)
@@ -32,7 +32,7 @@ require_once __DIR__ . '/Maintenance.php';
 class SyncFileBackend extends Maintenance {
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Sync one file backend with another using the journal";
+               $this->addDescription( 'Sync one file backend with another using the journal' );
                $this->addOption( 'src', 'Name of backend to sync from', true, true );
                $this->addOption( 'dst', 'Name of destination backend to sync', false, true );
                $this->addOption( 'start', 'Starting journal ID', false, true );
index 71b4de1..861f5ed 100644 (file)
@@ -26,7 +26,7 @@ require_once __DIR__ . '/Maintenance.php';
 class Undelete extends Maintenance {
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Undelete a page";
+               $this->addDescription( 'Undelete a page' );
                $this->addOption( 'user', 'The user to perform the undeletion', false, true, 'u' );
                $this->addOption( 'reason', 'The reason to undelete', false, true, 'r' );
                $this->addArg( 'pagename', 'Page to undelete' );
index eeaf9c8..06e947c 100755 (executable)
@@ -36,7 +36,7 @@ require_once __DIR__ . '/Maintenance.php';
 class UpdateMediaWiki extends Maintenance {
        function __construct() {
                parent::__construct();
-               $this->mDescription = "MediaWiki database updater";
+               $this->addDescription( 'MediaWiki database updater' );
                $this->addOption( 'skip-compat-checks', 'Skips compatibility checks, mostly for developers' );
                $this->addOption( 'quick', 'Skip 5 second countdown before starting' );
                $this->addOption( 'doshared', 'Also update shared tables' );
index 9537a79..baba6c8 100644 (file)
@@ -35,7 +35,7 @@ class UpdateArticleCount extends Maintenance {
 
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Count of the number of articles and update the site statistics table";
+               $this->addDescription( 'Count of the number of articles and update the site statistics table' );
                $this->addOption( 'update', 'Update the site_stats table with the new count' );
                $this->addOption( 'use-master', 'Count using the master database' );
        }
index bd75b3b..37c9948 100644 (file)
@@ -42,12 +42,13 @@ class UpdateCollation extends Maintenance {
                parent::__construct();
 
                global $wgCategoryCollation;
-               $this->mDescription = <<<TEXT
+               $this->addDescription( <<<TEXT
 This script will find all rows in the categorylinks table whose collation is
 out-of-date (cl_collation != '$wgCategoryCollation') and repopulate cl_sortkey
 using the page title and cl_sortkey_prefix.  If all collations are
 up-to-date, it will do nothing.
-TEXT;
+TEXT
+               );
 
                $this->addOption( 'force', 'Run on all rows, even if the collation is ' .
                        'supposed to be up-to-date.' );
index 5c21b40..f5bb881 100644 (file)
@@ -34,7 +34,7 @@ class UpdateDoubleWidthSearch extends Maintenance {
 
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Script to normalize double-byte latin UTF-8 characters";
+               $this->addDescription( 'Script to normalize double-byte latin UTF-8 characters' );
                $this->addOption( 'q', 'quiet', false, true );
                $this->addOption(
                        'l',
index ebfffe4..98d9389 100644 (file)
@@ -35,7 +35,7 @@ require_once __DIR__ . '/Maintenance.php';
 class UpdateRestrictions extends Maintenance {
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Updates page_restrictions table from old page_restriction column";
+               $this->addDescription( 'Updates page_restrictions table from old page_restriction column' );
                $this->setBatchSize( 100 );
        }
 
index 18edecc..b2f2577 100644 (file)
@@ -39,7 +39,7 @@ class UpdateSearchIndex extends Maintenance {
 
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Script for periodic off-peak updating of the search index";
+               $this->setDescription( 'Script for periodic off-peak updating of the search index' );
                $this->addOption( 's', 'starting timestamp', false, true );
                $this->addOption( 'e', 'Ending timestamp', false, true );
                $this->addOption(
index e0c10f8..2534ca6 100644 (file)
@@ -32,7 +32,7 @@ require_once __DIR__ . '/Maintenance.php';
 class WrapOldPasswords extends Maintenance {
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Wrap all passwords of a certain type in a new layered type";
+               $this->addDescription( 'Wrap all passwords of a certain type in a new layered type' );
                $this->addOption( 'type',
                        'Password type to wrap passwords in (must inherit LayeredParameterizedPassword)', true, true );
                $this->addOption( 'verbose', 'Enables verbose output', false, false, 'v' );
index b04e01c..b8349d0 100644 (file)
                /**
                 * Get a message object.
                 *
-                * Shorcut for `new mw.Message( mw.messages, key, parameters )`.
+                * Shortcut for `new mw.Message( mw.messages, key, parameters )`.
                 *
                 * @see mw.Message
                 * @param {string} key Key of message to get
                         */
 
                        /**
-                        * Write a message the console's warning channel.
+                        * Write a message to the console's warning channel.
                         * Actions not supported by the browser console are silently ignored.
                         *
                         * @param {...string} msg Messages to output to console
                                $.noop;
 
                        /**
-                        * Write a message the console's error channel.
+                        * Write a message to the console's error channel.
                         *
                         * Most browsers provide a stacktrace by default if the argument
                         * is a caught Error object.
                        /**
                         * A module has entered state 'ready', 'error', or 'missing'. Automatically update
                         * pending jobs and modules that depend upon this module. If the given module failed,
-                        * propagate the 'error' state up the dependency tree. Otherwise, go ahead an execute
+                        * propagate the 'error' state up the dependency tree. Otherwise, go ahead and execute
                         * all jobs/modules now having their dependencies satisfied.
                         *
                         * Jobs that depend on a failed module, will have their error callback ran (if any).
                                                                script( $, $ );
                                                                markModuleReady();
                                                        } else if ( typeof script === 'string' ) {
-                                                               // Site and user modules are legacy scripts that run in the global scope.
+                                                               // Site and user modules are legacy scripts that run in the global scope.
                                                                // This is transported as a string instead of a function to avoid needing
                                                                // to use string manipulation to undo the function wrapper.
                                                                if ( module === 'user' ) {
                        }
 
                        /**
-                        * Adds a dependencies to the queue with optional callbacks to be run
+                        * Adds all dependencies to the queue with optional callbacks to be run
                         * when the dependencies are ready or fail
                         *
                         * @private
                                 * When #load or #using requests one or more modules, the server
                                 * response contain calls to this function.
                                 *
-                                * All arguments are required.
-                                *
                                 * @param {string} module Name of module
-                                * @param {Function|Array} script Function with module code or Array of URLs to
+                                * @param {Function|Array} [script] Function with module code or Array of URLs to
                                 *  be used as the src attribute of a new `<script>` tag.
                                 * @param {Object} [style] Should follow one of the following patterns:
                                 *
        /**
         * Log a message to window.console, if possible.
         *
-        * Useful to force logging of some  errors that are otherwise hard to detect (i.e., this logs
+        * Useful to force logging of some errors that are otherwise hard to detect (i.e., this logs
         * also in production mode). Gets console references in each invocation instead of caching the
         * reference, so that debugging tools loaded later are supported (e.g. Firebug Lite in IE).
         *
                        msg += ( e ? ':' : '.' );
                        console.log( msg );
 
-                       // If we have an exception object, log it to the error channel to trigger a
-                       // proper stacktraces in browsers that support it. No fallback as we have no browsers
-                       // that don't support error(), but do support log().
+                       // If we have an exception object, log it to the error channel to trigger
+                       // proper stacktraces in browsers that support it. No fallback as we have
+                       // no browsers that don't support error(), but do support log().
                        if ( e && console.error ) {
                                console.error( String( e ), e );
                        }
index ac745f2..90ee1bb 100644 (file)
@@ -272,6 +272,25 @@ class EditPageTest extends MediaWikiLangTestCase {
        public function testCreatePage(
                $desc, $pageTitle, $user, $editText, $expectedCode, $expectedText, $ignoreBlank = false
        ) {
+               $checkId = null;
+
+               $this->setMwGlobals( 'wgHooks', array(
+                       'PageContentInsertComplete' => array( function (
+                               WikiPage &$page, User &$user, Content $content,
+                               $summary, $minor, $u1, $u2, &$flags, Revision $revision
+                       ) {
+                               // types/refs checked
+                       } ),
+                       'PageContentSaveComplete' => array( function (
+                               WikiPage &$page, User &$user, Content $content,
+                               $summary, $minor, $u1, $u2, &$flags, Revision $revision,
+                               Status &$status, $baseRevId
+                       ) use ( &$checkId ) {
+                               $checkId = $status->value['revision']->getId();
+                               // types/refs checked
+                       } ),
+               ) );
+
                $edit = array( 'wpTextbox1' => $editText );
                if ( $ignoreBlank ) {
                        $edit['wpIgnoreBlankArticle'] = 1;
@@ -280,7 +299,67 @@ class EditPageTest extends MediaWikiLangTestCase {
                $page = $this->assertEdit( $pageTitle, null, $user, $edit, $expectedCode, $expectedText, $desc );
 
                if ( $expectedCode != EditPage::AS_BLANK_ARTICLE ) {
+                       $latest = $page->getLatest();
+                       $page->doDeleteArticleReal( $pageTitle );
+
+                       $this->assertGreaterThan( 0, $latest, "Page revision ID updated in object" );
+                       $this->assertEquals( $latest, $checkId, "Revision in Status for hook" );
+               }
+       }
+
+       /**
+        * @dataProvider provideCreatePages
+        * @covers EditPage
+        */
+       public function testCreatePageTrx(
+               $desc, $pageTitle, $user, $editText, $expectedCode, $expectedText, $ignoreBlank = false
+       ) {
+               $checkIds = array();
+               $this->setMwGlobals( 'wgHooks', array(
+                       'PageContentInsertComplete' => array( function (
+                               WikiPage &$page, User &$user, Content $content,
+                               $summary, $minor, $u1, $u2, &$flags, Revision $revision
+                       ) {
+                               // types/refs checked
+                       } ),
+                       'PageContentSaveComplete' => array( function (
+                               WikiPage &$page, User &$user, Content $content,
+                               $summary, $minor, $u1, $u2, &$flags, Revision $revision,
+                               Status &$status, $baseRevId
+                       ) use ( &$checkIds ) {
+                               $checkIds[] = $status->value['revision']->getId();
+                               // types/refs checked
+                       } ),
+               ) );
+
+               wfGetDB( DB_MASTER )->begin( __METHOD__ );
+
+               $edit = array( 'wpTextbox1' => $editText );
+               if ( $ignoreBlank ) {
+                       $edit['wpIgnoreBlankArticle'] = 1;
+               }
+
+               $page = $this->assertEdit(
+                       $pageTitle, null, $user, $edit, $expectedCode, $expectedText, $desc );
+
+               $pageTitle2 = (string)$pageTitle . '/x';
+               $page2 = $this->assertEdit(
+                       $pageTitle2, null, $user, $edit, $expectedCode, $expectedText, $desc );
+
+               wfGetDB( DB_MASTER )->commit( __METHOD__ );
+
+               if ( $expectedCode != EditPage::AS_BLANK_ARTICLE ) {
+                       $latest = $page->getLatest();
                        $page->doDeleteArticleReal( $pageTitle );
+
+                       $this->assertGreaterThan( 0, $latest, "Page #1 revision ID updated in object" );
+                       $this->assertEquals( $latest, $checkIds[0], "Revision #1 in Status for hook" );
+
+                       $latest2 = $page2->getLatest();
+                       $page2->doDeleteArticleReal( $pageTitle2 );
+
+                       $this->assertGreaterThan( 0, $latest2, "Page #2 revision ID updated in object" );
+                       $this->assertEquals( $latest2, $checkIds[1], "Revision #2 in Status for hook" );
                }
        }
 
index d3dc512..ca1ec50 100644 (file)
@@ -317,33 +317,6 @@ class SanitizerTest extends MediaWikiTestCase {
                );
        }
 
-       /**
-        * Test for support or lack of support for specific attributes in the attribute whitelist.
-        */
-       public static function provideAttributeSupport() {
-               /** array( <attributes>, <expected>, <message> ) */
-               return array(
-                       array(
-                               'div',
-                               ' role="presentation"',
-                               ' role="presentation"',
-                               'Support for WAI-ARIA\'s role="presentation".'
-                       ),
-                       array( 'div', ' role="main"', '', "Other WAI-ARIA roles are currently not supported." ),
-               );
-       }
-
-       /**
-        * @dataProvider provideAttributeSupport
-        * @covers Sanitizer::fixTagAttributes
-        */
-       public function testAttributeSupport( $tag, $attributes, $expected, $message ) {
-               $this->assertEquals( $expected,
-                       Sanitizer::fixTagAttributes( $attributes, $tag ),
-                       $message
-               );
-       }
-
        /**
         * @dataProvider provideEscapeHtmlAllowEntities
         * @covers Sanitizer::escapeHtmlAllowEntities
@@ -363,4 +336,28 @@ class SanitizerTest extends MediaWikiTestCase {
                        array( '&lt;script&gt;foo&lt;/script&gt;', '<script>foo</script>' ),
                );
        }
+
+       /**
+        * Test escapeIdReferenceList for consistency with escapeId
+        *
+        * @dataProvider provideEscapeIdReferenceList
+        * @covers Sanitizer::escapeIdReferenceList
+        */
+       public function testEscapeIdReferenceList( $referenceList, $id1, $id2 ) {
+               $this->assertEquals(
+                       Sanitizer::escapeIdReferenceList( $referenceList, 'noninitial' ),
+                       Sanitizer::escapeId( $id1, 'noninitial' )
+                               . ' '
+                               . Sanitizer::escapeId( $id2, 'noninitial' )
+               );
+       }
+
+       public static function provideEscapeIdReferenceList() {
+               /** array( <reference list>, <individual id 1>, <individual id 2> ) */
+               return array(
+                       array( 'foo bar', 'foo', 'bar' ),
+                       array( '#1 #2', '#1', '#2' ),
+                       array( '+1 +2', '+1', '+2' ),
+               );
+       }
 }
index 3945102..35905c5 100644 (file)
@@ -10,7 +10,6 @@
 class ApiCreateAccountTest extends ApiTestCase {
        protected function setUp() {
                parent::setUp();
-               LoginForm::setCreateaccountToken();
                $this->setMwGlobals( array( 'wgEnableEmail' => true ) );
        }
 
@@ -114,7 +113,7 @@ class ApiCreateAccountTest extends ApiTestCase {
        public function testNoName() {
                $this->doApiRequest( array(
                        'action' => 'createaccount',
-                       'token' => LoginForm::getCreateaccountToken(),
+                       'token' => LoginForm::getCreateaccountToken()->toString(),
                        'password' => 'password',
                ) );
        }
@@ -127,7 +126,7 @@ class ApiCreateAccountTest extends ApiTestCase {
                $this->doApiRequest( array(
                        'action' => 'createaccount',
                        'name' => 'testName',
-                       'token' => LoginForm::getCreateaccountToken(),
+                       'token' => LoginForm::getCreateaccountToken()->toString(),
                ) );
        }
 
@@ -139,7 +138,7 @@ class ApiCreateAccountTest extends ApiTestCase {
                $this->doApiRequest( array(
                        'action' => 'createaccount',
                        'name' => 'Apitestsysop',
-                       'token' => LoginForm::getCreateaccountToken(),
+                       'token' => LoginForm::getCreateaccountToken()->toString(),
                        'password' => 'password',
                        'email' => 'test@domain.test',
                ) );
@@ -153,7 +152,7 @@ class ApiCreateAccountTest extends ApiTestCase {
                $this->doApiRequest( array(
                        'action' => 'createaccount',
                        'name' => 'Test User',
-                       'token' => LoginForm::getCreateaccountToken(),
+                       'token' => LoginForm::getCreateaccountToken()->toString(),
                        'password' => 'password',
                        'email' => 'invalid',
                ) );
index 4085925..894feb7 100644 (file)
@@ -14,11 +14,11 @@ class ApiLoginTest extends ApiTestCase {
         */
        public function testApiLoginNoName() {
                $session = array(
-                       'wsLoginToken' => 'foobar'
+                       'wsTokenSecrets' => array( 'login' => 'foobar' ),
                );
                $data = $this->doApiRequest( array( 'action' => 'login',
                        'lgname' => '', 'lgpassword' => self::$users['sysop']->password,
-                       'lgtoken' => 'foobar',
+                       'lgtoken' => (string)( new MediaWiki\Session\Token( 'foobar', '' ) )
                ), $session );
                $this->assertEquals( 'NoName', $data[0]['login']['result'] );
        }
index 25ffcb7..52c9fec 100644 (file)
@@ -148,12 +148,12 @@ abstract class ApiTestCase extends MediaWikiLangTestCase {
                if ( isset( $session['wsToken'] ) && $session['wsToken'] ) {
                        // @todo Why does this directly mess with the session? Fix that.
                        // add edit token to fake session
-                       $session['wsEditToken'] = $session['wsToken'];
+                       $session['wsTokenSecrets']['default'] = $session['wsToken'];
                        // add token to request parameters
                        $timestamp = wfTimestamp();
                        $params['token'] = hash_hmac( 'md5', $timestamp, $session['wsToken'] ) .
                                dechex( $timestamp ) .
-                               User::EDIT_TOKEN_SUFFIX;
+                               MediaWiki\Session\Token::SUFFIX;
 
                        return $this->doApiRequest( $params, $session, false, $user );
                } else {
index 25969e6..e0487c2 100644 (file)
@@ -50,6 +50,8 @@ class RequestContextTest extends MediaWikiTestCase {
                $oInfo = $context->exportSession();
                $this->assertEquals( '127.0.0.1', $oInfo['ip'], "Correct initial IP address." );
                $this->assertEquals( 0, $oInfo['userId'], "Correct initial user ID." );
+               $this->assertFalse( MediaWiki\Session\SessionManager::getGlobalSession()->isPersistent(),
+                       'Global session isn\'t persistent to start' );
 
                $user = User::newFromName( 'UnitTestContextUser' );
                $user->addToDatabase();
@@ -109,5 +111,7 @@ class RequestContextTest extends MediaWikiTestCase {
                $this->assertEquals( $oInfo['headers'], $info['headers'], "Correct restored headers." );
                $this->assertEquals( $oInfo['sessionId'], $info['sessionId'], "Correct restored session ID." );
                $this->assertEquals( $oInfo['userId'], $info['userId'], "Correct restored user ID." );
+               $this->assertFalse( MediaWiki\Session\SessionManager::getGlobalSession()->isPersistent(),
+                       'Global session isn\'t persistent after restoring the context' );
        }
 }
index e4415ec..d355e17 100644 (file)
@@ -34,7 +34,7 @@ class BitmapScalingTest extends MediaWikiTestCase {
                                array(
                                        'width' => 512, 'height' => 384,
                                        'physicalWidth' => 512, 'physicalHeight' => 384,
-                                       'page' => 1,
+                                       'page' => 1, 'interlace' => false,
                                ),
                                array( 'width' => 512 ),
                                'Resizing with width set',
@@ -44,7 +44,7 @@ class BitmapScalingTest extends MediaWikiTestCase {
                                array(
                                        'width' => 512, 'height' => 384,
                                        'physicalWidth' => 512, 'physicalHeight' => 384,
-                                       'page' => 1,
+                                       'page' => 1, 'interlace' => false,
                                ),
                                array( 'width' => 512, 'height' => 768 ),
                                'Resizing with height set too high',
@@ -54,7 +54,7 @@ class BitmapScalingTest extends MediaWikiTestCase {
                                array(
                                        'width' => 512, 'height' => 384,
                                        'physicalWidth' => 512, 'physicalHeight' => 384,
-                                       'page' => 1,
+                                       'page' => 1, 'interlace' => false,
                                ),
                                array( 'width' => 1024, 'height' => 384 ),
                                'Resizing with height set',
@@ -66,7 +66,7 @@ class BitmapScalingTest extends MediaWikiTestCase {
                                array(
                                        'width' => 5, 'height' => 1,
                                        'physicalWidth' => 5, 'physicalHeight' => 1,
-                                       'page' => 1,
+                                       'page' => 1, 'interlace' => false,
                                ),
                                array( 'width' => 5 ),
                                'Very wide image',
@@ -77,7 +77,7 @@ class BitmapScalingTest extends MediaWikiTestCase {
                                array(
                                        'width' => 1, 'height' => 10,
                                        'physicalWidth' => 1, 'physicalHeight' => 10,
-                                       'page' => 1,
+                                       'page' => 1, 'interlace' => false,
                                ),
                                array( 'width' => 1 ),
                                'Very high image',
@@ -87,7 +87,7 @@ class BitmapScalingTest extends MediaWikiTestCase {
                                array(
                                        'width' => 1, 'height' => 5,
                                        'physicalWidth' => 1, 'physicalHeight' => 10,
-                                       'page' => 1,
+                                       'page' => 1, 'interlace' => false,
                                ),
                                array( 'width' => 10, 'height' => 5 ),
                                'Very high image with height set',
@@ -98,11 +98,22 @@ class BitmapScalingTest extends MediaWikiTestCase {
                                array(
                                        'width' => 5000, 'height' => 5000,
                                        'physicalWidth' => 4000, 'physicalHeight' => 4000,
-                                       'page' => 1,
+                                       'page' => 1, 'interlace' => false,
                                ),
                                array( 'width' => 5000 ),
                                'Bigger than max image size but doesn\'t need scaling',
                        ),
+                       /* Max interlace image area */
+                       array(
+                               array( 4000, 4000 ),
+                               array(
+                                       'width' => 5000, 'height' => 5000,
+                                       'physicalWidth' => 4000, 'physicalHeight' => 4000,
+                                       'page' => 1, 'interlace' => false,
+                               ),
+                               array( 'width' => 5000, 'interlace' => true ),
+                               'Interlace bigger than max interlace area',
+                       ),
                );
        }
 
index 702f556..e5df458 100644 (file)
@@ -184,7 +184,9 @@ class CookieSessionProviderTest extends MediaWikiTestCase {
                $this->assertNotNull( $info );
                $this->assertSame( $params['priority'], $info->getPriority() );
                $this->assertSame( $sessionId, $info->getId() );
-               $this->assertNull( $info->getUserInfo() );
+               $this->assertNotNull( $info->getUserInfo() );
+               $this->assertSame( 0, $info->getUserInfo()->getId() );
+               $this->assertNull( $info->getUserInfo()->getName() );
                $this->assertFalse( $info->forceHTTPS() );
 
                // User, no session key
@@ -363,6 +365,7 @@ class CookieSessionProviderTest extends MediaWikiTestCase {
                                'idIsSafe' => true,
                        ) ),
                        $store,
+                       $store,
                        new \Psr\Log\NullLogger(),
                        10
                );
@@ -449,6 +452,7 @@ class CookieSessionProviderTest extends MediaWikiTestCase {
                                'idIsSafe' => true,
                        ) ),
                        new \EmptyBagOStuff(),
+                       new \EmptyBagOStuff(),
                        new \Psr\Log\NullLogger(),
                        10
                );
@@ -553,6 +557,7 @@ class CookieSessionProviderTest extends MediaWikiTestCase {
                                'idIsSafe' => true,
                        ) ),
                        $store,
+                       $store,
                        new \Psr\Log\NullLogger(),
                        10
                );
index e06dfd5..46f23f3 100644 (file)
@@ -205,6 +205,7 @@ class ImmutableSessionProviderWithCookieTest extends MediaWikiTestCase {
                                'idIsSafe' => true,
                        ) ),
                        new \EmptyBagOStuff(),
+                       new \EmptyBagOStuff(),
                        new \Psr\Log\NullLogger(),
                        10
                );
index 125e1b6..1c54a20 100644 (file)
@@ -172,14 +172,6 @@ class PHPSessionHandlerTest extends MediaWikiTestCase {
                        $this->assertSame( $expect, $_SESSION );
                }
 
-               // Test expiry
-               session_write_close();
-               ini_set( 'session.gc_divisor', 1 );
-               ini_set( 'session.gc_probability', 1 );
-               sleep( 3 );
-               session_start();
-               $this->assertSame( array(), $_SESSION );
-
                // Re-fill the session, then test that session_destroy() works.
                $_SESSION['AuthenticationSessionTest'] = $rand;
                session_write_close();
index d06706b..85fa9bd 100644 (file)
@@ -59,7 +59,7 @@ class SessionBackendTest extends MediaWikiTestCase {
                ) );
                $id = new SessionId( $info->getId() );
 
-               $backend = new SessionBackend( $id, $info, $this->store, $logger, 10 );
+               $backend = new SessionBackend( $id, $info, $this->store, $this->store, $logger, 10 );
                $priv = \TestingAccessWrapper::newFromObject( $backend );
                $priv->persist = false;
                $priv->requests = array( 100 => new \FauxRequest() );
@@ -87,7 +87,7 @@ class SessionBackendTest extends MediaWikiTestCase {
                $id = new SessionId( $info->getId() );
                $logger = new \Psr\Log\NullLogger();
                try {
-                       new SessionBackend( $id, $info, $this->store, $logger, 10 );
+                       new SessionBackend( $id, $info, $this->store, $this->store, $logger, 10 );
                        $this->fail( 'Expected exception not thrown' );
                } catch ( \InvalidArgumentException $ex ) {
                        $this->assertSame(
@@ -103,7 +103,7 @@ class SessionBackendTest extends MediaWikiTestCase {
                ) );
                $id = new SessionId( $info->getId() );
                try {
-                       new SessionBackend( $id, $info, $this->store, $logger, 10 );
+                       new SessionBackend( $id, $info, $this->store, $this->store, $logger, 10 );
                        $this->fail( 'Expected exception not thrown' );
                } catch ( \InvalidArgumentException $ex ) {
                        $this->assertSame( 'Cannot create session without a provider', $ex->getMessage() );
@@ -118,7 +118,7 @@ class SessionBackendTest extends MediaWikiTestCase {
                ) );
                $id = new SessionId( '!' . $info->getId() );
                try {
-                       new SessionBackend( $id, $info, $this->store, $logger, 10 );
+                       new SessionBackend( $id, $info, $this->store, $this->store, $logger, 10 );
                        $this->fail( 'Expected exception not thrown' );
                } catch ( \InvalidArgumentException $ex ) {
                        $this->assertSame(
@@ -135,7 +135,7 @@ class SessionBackendTest extends MediaWikiTestCase {
                        'idIsSafe' => true,
                ) );
                $id = new SessionId( $info->getId() );
-               $backend = new SessionBackend( $id, $info, $this->store, $logger, 10 );
+               $backend = new SessionBackend( $id, $info, $this->store, $this->store, $logger, 10 );
                $this->assertSame( self::SESSIONID, $backend->getId() );
                $this->assertSame( $id, $backend->getSessionId() );
                $this->assertSame( $this->provider, $backend->getProvider() );
@@ -157,7 +157,7 @@ class SessionBackendTest extends MediaWikiTestCase {
                        'idIsSafe' => true,
                ) );
                $id = new SessionId( $info->getId() );
-               $backend = new SessionBackend( $id, $info, $this->store, $logger, 10 );
+               $backend = new SessionBackend( $id, $info, $this->store, $this->store, $logger, 10 );
                $this->assertSame( self::SESSIONID, $backend->getId() );
                $this->assertSame( $id, $backend->getSessionId() );
                $this->assertSame( $this->provider, $backend->getProvider() );
index 083223e..4fde341 100644 (file)
@@ -103,7 +103,7 @@ class SessionManagerTest extends MediaWikiTestCase {
                $manager = \TestingAccessWrapper::newFromObject( $this->getManager() );
                $this->assertSame( $this->config, $manager->config );
                $this->assertSame( $this->logger, $manager->logger );
-               $this->assertSame( $this->store, $manager->store );
+               $this->assertSame( $this->store, $manager->permStore );
 
                $manager = \TestingAccessWrapper::newFromObject( new SessionManager() );
                $this->assertSame( \RequestContext::getMain()->getConfig(), $manager->config );
@@ -111,7 +111,7 @@ class SessionManagerTest extends MediaWikiTestCase {
                $manager = \TestingAccessWrapper::newFromObject( new SessionManager( array(
                        'config' => $this->config,
                ) ) );
-               $this->assertSame( \ObjectCache::$instances['testSessionStore'], $manager->store );
+               $this->assertSame( \ObjectCache::$instances['testSessionStore'], $manager->permStore );
 
                foreach ( array(
                        'config' => '$options[\'config\'] must be an instance of Config',
@@ -301,6 +301,9 @@ class SessionManagerTest extends MediaWikiTestCase {
        public function testGetSessionById() {
                $manager = $this->getManager();
 
+               // Disable the in-process cache so our $this->store->setSession() takes effect.
+               \TestingAccessWrapper::newFromObject( $manager )->tempStore = new \EmptyBagOStuff;
+
                try {
                        $manager->getSessionById( 'bad' );
                        $this->fail( 'Expected exception not thrown' );
@@ -1083,6 +1086,9 @@ class SessionManagerTest extends MediaWikiTestCase {
                $manager->setLogger( $logger );
                $request = new \FauxRequest();
 
+               // Disable the in-process cache so our $this->store->setSession() takes effect.
+               \TestingAccessWrapper::newFromObject( $manager )->tempStore = new \EmptyBagOStuff;
+
                // TestingAccessWrapper can't handle methods with reference arguments, sigh.
                $rClass = new \ReflectionClass( $manager );
                $rMethod = $rClass->getMethod( 'loadSessionInfoFromStore' );
@@ -1604,6 +1610,38 @@ class SessionManagerTest extends MediaWikiTestCase {
                $this->assertTrue( $info->forceHTTPS() );
                $this->assertSame( array(), $logger->getBuffer() );
 
+               // "Persist" flag from session
+               $this->store->setSessionMeta( $id, $metadata );
+               $info = new SessionInfo( SessionInfo::MIN_PRIORITY, array(
+                       'provider' => $provider,
+                       'id' => $id,
+                       'userInfo' => $userInfo
+               ) );
+               $this->assertTrue( $loadSessionInfoFromStore( $info ) );
+               $this->assertFalse( $info->wasPersisted() );
+               $this->assertSame( array(), $logger->getBuffer() );
+
+               $this->store->setSessionMeta( $id, array( 'persisted' => true ) + $metadata );
+               $info = new SessionInfo( SessionInfo::MIN_PRIORITY, array(
+                       'provider' => $provider,
+                       'id' => $id,
+                       'userInfo' => $userInfo
+               ) );
+               $this->assertTrue( $loadSessionInfoFromStore( $info ) );
+               $this->assertTrue( $info->wasPersisted() );
+               $this->assertSame( array(), $logger->getBuffer() );
+
+               $this->store->setSessionMeta( $id, array( 'persisted' => false ) + $metadata );
+               $info = new SessionInfo( SessionInfo::MIN_PRIORITY, array(
+                       'provider' => $provider,
+                       'id' => $id,
+                       'userInfo' => $userInfo,
+                       'persisted' => true
+               ) );
+               $this->assertTrue( $loadSessionInfoFromStore( $info ) );
+               $this->assertTrue( $info->wasPersisted() );
+               $this->assertSame( array(), $logger->getBuffer() );
+
                // Provider refreshSessionInfo() returning false
                $info = new SessionInfo( SessionInfo::MIN_PRIORITY, array(
                        'provider' => $provider3,
index efc92f7..858996d 100644 (file)
@@ -199,4 +199,51 @@ class SessionTest extends MediaWikiTestCase {
                $this->assertTrue( $backend->dirty );
        }
 
+       public function testTokens() {
+               $rc = new \ReflectionClass( 'MediaWiki\\Session\\Session' );
+               if ( !method_exists( $rc, 'newInstanceWithoutConstructor' ) ) {
+                       $this->markTestSkipped(
+                               'ReflectionClass::newInstanceWithoutConstructor isn\'t available'
+                       );
+               }
+
+               // Instead of actually constructing the Session, we use reflection to
+               // bypass the constructor and plug a mock SessionBackend into the
+               // private fields to avoid having to actually create a SessionBackend.
+               $backend = new DummySessionBackend;
+               $session = $rc->newInstanceWithoutConstructor();
+               $priv = \TestingAccessWrapper::newFromObject( $session );
+               $priv->backend = $backend;
+               $priv->index = 42;
+
+               $token = \TestingAccessWrapper::newFromObject( $session->getToken() );
+               $this->assertArrayHasKey( 'wsTokenSecrets', $backend->data );
+               $this->assertArrayHasKey( 'default', $backend->data['wsTokenSecrets'] );
+               $secret = $backend->data['wsTokenSecrets']['default'];
+               $this->assertSame( $secret, $token->secret );
+               $this->assertSame( '', $token->salt );
+               $this->assertTrue( $token->wasNew() );
+
+               $token = \TestingAccessWrapper::newFromObject( $session->getToken( 'foo' ) );
+               $this->assertSame( $secret, $token->secret );
+               $this->assertSame( 'foo', $token->salt );
+               $this->assertFalse( $token->wasNew() );
+
+               $backend->data['wsTokenSecrets']['secret'] = 'sekret';
+               $token = \TestingAccessWrapper::newFromObject(
+                       $session->getToken( array( 'bar', 'baz' ), 'secret' )
+               );
+               $this->assertSame( 'sekret', $token->secret );
+               $this->assertSame( 'bar|baz', $token->salt );
+               $this->assertFalse( $token->wasNew() );
+
+               $session->resetToken( 'secret' );
+               $this->assertArrayHasKey( 'wsTokenSecrets', $backend->data );
+               $this->assertArrayHasKey( 'default', $backend->data['wsTokenSecrets'] );
+               $this->assertArrayNotHasKey( 'secret', $backend->data['wsTokenSecrets'] );
+
+               $session->resetAllTokens();
+               $this->assertArrayNotHasKey( 'wsTokenSecrets', $backend->data );
+
+       }
 }
diff --git a/tests/phpunit/includes/session/TokenTest.php b/tests/phpunit/includes/session/TokenTest.php
new file mode 100644 (file)
index 0000000..113f409
--- /dev/null
@@ -0,0 +1,66 @@
+<?php
+
+namespace MediaWiki\Session;
+
+use MediaWikiTestCase;
+
+/**
+ * @group Session
+ * @covers MediaWiki\Session\Token
+ */
+class TokenTest extends MediaWikiTestCase {
+
+       public function testBasics() {
+               $token = $this->getMockBuilder( 'MediaWiki\\Session\\Token' )
+                       ->setMethods( array( 'toStringAtTimestamp' ) )
+                       ->setConstructorArgs( array( 'sekret', 'salty', true ) )
+                       ->getMock();
+               $token->expects( $this->any() )->method( 'toStringAtTimestamp' )
+                       ->will( $this->returnValue( 'faketoken+\\' ) );
+
+               $this->assertSame( 'faketoken+\\', $token->toString() );
+               $this->assertSame( 'faketoken+\\', (string)$token );
+               $this->assertTrue( $token->wasNew() );
+
+               $token = new Token( 'sekret', 'salty', false );
+               $this->assertFalse( $token->wasNew() );
+       }
+
+       public function testToStringAtTimestamp() {
+               $token = \TestingAccessWrapper::newFromObject( new Token( 'sekret', 'salty', false ) );
+
+               $this->assertSame(
+                       'd9ade0c7d4349e9df9094e61c33a5a0d5644fde2+\\',
+                       $token->toStringAtTimestamp( 1447362018 )
+               );
+               $this->assertSame(
+                       'ee2f7a2488dea9176c224cfb400d43be5644fdea+\\',
+                       $token->toStringAtTimestamp( 1447362026 )
+               );
+       }
+
+       public function testGetTimestamp() {
+               $this->assertSame(
+                       1447362018, Token::getTimestamp( 'd9ade0c7d4349e9df9094e61c33a5a0d5644fde2+\\' )
+               );
+               $this->assertSame(
+                       1447362026, Token::getTimestamp( 'ee2f7a2488dea9176c224cfb400d43be5644fdea+\\' )
+               );
+               $this->assertNull( Token::getTimestamp( 'ee2f7a2488dea9176c224cfb400d43be5644fdea-\\' ) );
+               $this->assertNull( Token::getTimestamp( 'ee2f7a2488dea9176c224cfb400d43be+\\' ) );
+
+               $this->assertNull( Token::getTimestamp( 'ee2f7a2488dea9x76c224cfb400d43be5644fdea+\\' ) );
+       }
+
+       public function testMatch() {
+               $token = \TestingAccessWrapper::newFromObject( new Token( 'sekret', 'salty', false ) );
+
+               $test = $token->toStringAtTimestamp( time() - 10 );
+               $this->assertTrue( $token->match( $test ) );
+               $this->assertTrue( $token->match( $test, 12 ) );
+               $this->assertFalse( $token->match( $test, 8 ) );
+
+               $this->assertFalse( $token->match( 'ee2f7a2488dea9176c224cfb400d43be5644fdea-\\' ) );
+       }
+
+}
index 121bb72..c38edd6 100644 (file)
@@ -19,7 +19,7 @@ class UserInfoTest extends MediaWikiTestCase {
                $this->assertTrue( $userinfo->isVerified() );
                $this->assertSame( 0, $userinfo->getId() );
                $this->assertSame( null, $userinfo->getName() );
-               $this->assertSame( null, $userinfo->getToken() );
+               $this->assertSame( '', $userinfo->getToken() );
                $this->assertNotNull( $userinfo->getUser() );
                $this->assertSame( $userinfo, $userinfo->verified() );
                $this->assertSame( '<anon>', (string)$userinfo );
@@ -102,7 +102,7 @@ class UserInfoTest extends MediaWikiTestCase {
                $this->assertFalse( $userinfo->isVerified() );
                $this->assertSame( $user->getId(), $userinfo->getId() );
                $this->assertSame( $user->getName(), $userinfo->getName() );
-               $this->assertSame( null, $userinfo->getToken() );
+               $this->assertSame( '', $userinfo->getToken() );
                $this->assertInstanceOf( 'User', $userinfo->getUser() );
                $userinfo2 = $userinfo->verified();
                $this->assertNotSame( $userinfo2, $userinfo );
@@ -112,7 +112,7 @@ class UserInfoTest extends MediaWikiTestCase {
                $this->assertTrue( $userinfo2->isVerified() );
                $this->assertSame( $user->getId(), $userinfo2->getId() );
                $this->assertSame( $user->getName(), $userinfo2->getName() );
-               $this->assertSame( null, $userinfo2->getToken() );
+               $this->assertSame( '', $userinfo2->getToken() );
                $this->assertInstanceOf( 'User', $userinfo2->getUser() );
                $this->assertSame( $userinfo2, $userinfo2->verified() );
                $this->assertSame( "<+:{$user->getId()}:{$user->getName()}>", (string)$userinfo2 );
@@ -157,7 +157,7 @@ class UserInfoTest extends MediaWikiTestCase {
                $this->assertFalse( $userinfo->isVerified() );
                $this->assertSame( $user->getId(), $userinfo->getId() );
                $this->assertSame( $user->getName(), $userinfo->getName() );
-               $this->assertSame( null, $userinfo->getToken() );
+               $this->assertSame( '', $userinfo->getToken() );
                $this->assertSame( $user, $userinfo->getUser() );
                $userinfo2 = $userinfo->verified();
                $this->assertNotSame( $userinfo2, $userinfo );
@@ -167,7 +167,7 @@ class UserInfoTest extends MediaWikiTestCase {
                $this->assertTrue( $userinfo2->isVerified() );
                $this->assertSame( $user->getId(), $userinfo2->getId() );
                $this->assertSame( $user->getName(), $userinfo2->getName() );
-               $this->assertSame( null, $userinfo2->getToken() );
+               $this->assertSame( '', $userinfo2->getToken() );
                $this->assertSame( $user, $userinfo2->getUser() );
                $this->assertSame( $userinfo2, $userinfo2->verified() );
                $this->assertSame( "<+:{$user->getId()}:{$user->getName()}>", (string)$userinfo2 );
index ed3f2cd..fe5530b 100644 (file)
                } );
        } );
 
+       QUnit.test( 'mw.loader.implement( empty )', 1, function ( assert ) {
+               mw.loader.implement( 'test.empty' );
+               assert.strictEqual( mw.loader.getState( 'test.empty' ), 'ready' );
+       } );
+
        QUnit.test( 'mw.loader with broken indirect dependency', 4, function ( assert ) {
                // don't emit an error event
                this.sandbox.stub( mw, 'track' );