Merge "Add ParserOutputStashForEdit hook for extension cache warming"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Thu, 28 Jan 2016 23:13:06 +0000 (23:13 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Thu, 28 Jan 2016 23:13:06 +0000 (23:13 +0000)
117 files changed:
RELEASE-NOTES-1.27
autoload.php
docs/hooks.txt
images/.htaccess
includes/DefaultSettings.php
includes/EditPage.php
includes/Linker.php
includes/Sanitizer.php
includes/Setup.php
includes/actions/HistoryAction.php
includes/api/ApiBase.php
includes/api/ApiCheckToken.php
includes/api/ApiCreateAccount.php
includes/api/ApiLogin.php
includes/api/ApiQueryInfo.php
includes/api/ApiQueryTokens.php
includes/api/ApiTokens.php
includes/api/i18n/de.json
includes/api/i18n/en.json
includes/api/i18n/fr.json
includes/api/i18n/he.json
includes/api/i18n/it.json
includes/api/i18n/nl.json
includes/api/i18n/qqq.json
includes/api/i18n/zh-hans.json
includes/changes/CategoryMembershipChange.php
includes/context/RequestContext.php
includes/db/IDatabase.php
includes/installer/DatabaseUpdater.php
includes/installer/MysqlUpdater.php
includes/installer/i18n/el.json
includes/installer/i18n/ja.json
includes/installer/i18n/nl.json
includes/installer/i18n/zh-hans.json
includes/jobqueue/JobRunner.php
includes/jobqueue/jobs/CategoryMembershipChangeJob.php
includes/jobqueue/jobs/HTMLCacheUpdateJob.php
includes/jobqueue/jobs/RecentChangesUpdateJob.php
includes/logging/TagLogFormatter.php
includes/media/Bitmap.php
includes/media/TransformationalImageHandler.php
includes/objectcache/SqlBagOStuff.php
includes/page/WikiPage.php
includes/resourceloader/ResourceLoader.php
includes/resourceloader/ResourceLoaderModule.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/SpecialUserlogin.php
includes/user/LoggedOutEditToken.php [new file with mode: 0644]
includes/user/User.php
includes/utils/BatchRowWriter.php
languages/i18n/azb.json
languages/i18n/be-tarask.json
languages/i18n/bn.json
languages/i18n/bs.json
languages/i18n/da.json
languages/i18n/el.json
languages/i18n/eo.json
languages/i18n/fi.json
languages/i18n/fur.json
languages/i18n/gl.json
languages/i18n/gu.json
languages/i18n/hi.json
languages/i18n/hr.json
languages/i18n/it.json
languages/i18n/jam.json
languages/i18n/ka.json
languages/i18n/ko.json
languages/i18n/lt.json
languages/i18n/lzh.json
languages/i18n/mn.json
languages/i18n/nl.json
languages/i18n/nn.json
languages/i18n/pl.json
languages/i18n/pt.json
languages/i18n/ro.json
languages/i18n/sv.json
languages/i18n/ur.json
languages/i18n/vo.json
languages/i18n/wuu.json
languages/i18n/zh-hans.json
resources/src/mediawiki.widgets/mw.widgets.DateInputWidget.js
resources/src/mediawiki/page/patrol.ajax.js
resources/src/startup.js
tests/phpunit/includes/EditPageTest.php
tests/phpunit/includes/OutputPageTest.php
tests/phpunit/includes/SanitizerTest.php
tests/phpunit/includes/StatusTest.php
tests/phpunit/includes/TitleArrayFromResultTest.php
tests/phpunit/includes/api/ApiCreateAccountTest.php
tests/phpunit/includes/api/ApiLoginTest.php
tests/phpunit/includes/api/ApiTestCase.php
tests/phpunit/includes/changes/CategoryMembershipChangeTest.php
tests/phpunit/includes/content/JsonContentTest.php
tests/phpunit/includes/context/RequestContextTest.php
tests/phpunit/includes/diff/ArrayDiffFormatterTest.php
tests/phpunit/includes/diff/DiffOpTest.php
tests/phpunit/includes/diff/DiffTest.php
tests/phpunit/includes/exception/BadTitleErrorTest.php
tests/phpunit/includes/exception/ErrorPageErrorTest.php
tests/phpunit/includes/exception/ReadOnlyErrorTest.php
tests/phpunit/includes/exception/ThrottledErrorTest.php
tests/phpunit/includes/exception/UserNotLoggedInTest.php
tests/phpunit/includes/jobqueue/JobTest.php
tests/phpunit/includes/media/BitmapScalingTest.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/phpunit/includes/specials/SpecialBlankPageTest.php
tests/phpunit/includes/specials/SpecialPageTestBase.php
tests/phpunit/includes/user/UserArrayFromResultTest.php
tests/phpunit/tests/MediaWikiTestCaseTest.php

index 50d40a6..d9b6dd5 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,6 +90,10 @@ 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.
 
 === New features in 1.27 ===
 * $wgDataCenterId and $wgDataCenterRoles where added, which will serve as
@@ -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 ===
 
index 26b6598..6de1d79 100644 (file)
@@ -72,7 +72,6 @@ $wgAutoloadLocalClasses = array(
        'ApiQueryAllMessages' => __DIR__ . '/includes/api/ApiQueryAllMessages.php',
        'ApiQueryAllPages' => __DIR__ . '/includes/api/ApiQueryAllPages.php',
        'ApiQueryAllRevisions' => __DIR__ . '/includes/api/ApiQueryAllRevisions.php',
-       'ApiQueryMyStashedFiles' => __DIR__ . '/includes/api/ApiQueryMyStashedFiles.php',
        'ApiQueryAllUsers' => __DIR__ . '/includes/api/ApiQueryAllUsers.php',
        'ApiQueryBacklinks' => __DIR__ . '/includes/api/ApiQueryBacklinks.php',
        'ApiQueryBacklinksprop' => __DIR__ . '/includes/api/ApiQueryBacklinksprop.php',
@@ -101,6 +100,7 @@ $wgAutoloadLocalClasses = array(
        'ApiQueryLangLinks' => __DIR__ . '/includes/api/ApiQueryLangLinks.php',
        'ApiQueryLinks' => __DIR__ . '/includes/api/ApiQueryLinks.php',
        'ApiQueryLogEvents' => __DIR__ . '/includes/api/ApiQueryLogEvents.php',
+       'ApiQueryMyStashedFiles' => __DIR__ . '/includes/api/ApiQueryMyStashedFiles.php',
        'ApiQueryPagePropNames' => __DIR__ . '/includes/api/ApiQueryPagePropNames.php',
        'ApiQueryPageProps' => __DIR__ . '/includes/api/ApiQueryPageProps.php',
        'ApiQueryPagesWithProp' => __DIR__ . '/includes/api/ApiQueryPagesWithProp.php',
@@ -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',
index a252438..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,
index 8c46bbb..3f3d41e 100644 (file)
@@ -1,6 +1,7 @@
 # Protect against bug 28235
 <IfModule rewrite_module>
        RewriteEngine On
+       RewriteOptions inherit
        RewriteCond %{QUERY_STRING} \.[^\\/:*?\x22<>|%]+(#|\?|$) [nocase]
        RewriteRule . - [forbidden]
        # Fix for bug T64289
index a22a29d..4d0b50e 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
  */
@@ -3688,7 +3694,15 @@ $wgResourceLoaderValidateStaticJS = false;
  * @endcode
  * @since 1.22
  */
-$wgResourceLoaderLESSVars = array();
+$wgResourceLoaderLESSVars = array(
+       /**
+        * Minimum available screen width at which a device can be considered a tablet/desktop
+        * The number is currently based on the device width of a Samsung Galaxy S5 mini and is low
+        * enough to cover iPad (768px). Number is prone to change with new information.
+        * @since 1.27
+        */
+       'deviceWidthTablet' => '720px',
+);
 
 /**
  * Default import paths for LESS modules. LESS files referenced in @import
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 3ba472b..4b9b963 100644 (file)
@@ -2013,7 +2013,7 @@ class Linker {
         * directly paste it in as the link (escaping needs to be done manually).
         * Finally, if $more is a Message, call toString().
         *
-        * @param array $templates Array of templates from Article::getUsedTemplate or similar
+        * @param Title[] $templates Array of templates
         * @param bool $preview Whether this is for a preview
         * @param bool $section Whether this is for a section edit
         * @param Title|Message|string|null $more An escaped link for "More..." of the templates
index d41e559..e2564cd 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.
@@ -1546,6 +1579,11 @@ class Sanitizer {
                        'title',
 
                        # WAI-ARIA
+                       'aria-describedby',
+                       'aria-flowto',
+                       'aria-label',
+                       'aria-labelledby',
+                       'aria-owns',
                        'role',
                );
 
index 9bf05e0..9d434de 100644 (file)
@@ -505,6 +505,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 ca47fce..43260d0 100644 (file)
@@ -132,6 +132,8 @@ class HistoryAction extends FormlessAction {
                        return;
                }
 
+               $this->addHelpLink( '//meta.wikimedia.org/wiki/Special:MyLanguage/Help:Page_history', true );
+
                // Fail nicely if article doesn't exist.
                if ( !$this->page->exists() ) {
                        $out->addWikiMsg( 'nohistory' );
index 13d13a6..425a337 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;
                }
 
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 6f1e2e5..286c18e 100644 (file)
@@ -33,7 +33,8 @@ class ApiQueryInfo extends ApiQueryBase {
 
        private $fld_protection = false, $fld_talkid = false,
                $fld_subjectid = false, $fld_url = false,
-               $fld_readable = false, $fld_watched = false, $fld_watchers = false,
+               $fld_readable = false, $fld_watched = false,
+               $fld_watchers = false, $fld_visitingwatchers = false,
                $fld_notificationtimestamp = false,
                $fld_preload = false, $fld_displaytitle = false;
 
@@ -42,8 +43,8 @@ class ApiQueryInfo extends ApiQueryBase {
        private $pageRestrictions, $pageIsRedir, $pageIsNew, $pageTouched,
                $pageLatest, $pageLength;
 
-       private $protections, $restrictionTypes, $watched, $watchers, $notificationtimestamps,
-               $talkids, $subjectids, $displaytitles;
+       private $protections, $restrictionTypes, $watched, $watchers, $visitingwatchers,
+               $notificationtimestamps, $talkids, $subjectids, $displaytitles;
        private $showZeroWatchers = false;
 
        private $tokenFunctions;
@@ -292,6 +293,7 @@ class ApiQueryInfo extends ApiQueryBase {
                        $this->fld_protection = isset( $prop['protection'] );
                        $this->fld_watched = isset( $prop['watched'] );
                        $this->fld_watchers = isset( $prop['watchers'] );
+                       $this->fld_visitingwatchers = isset( $prop['visitingwatchers'] );
                        $this->fld_notificationtimestamp = isset( $prop['notificationtimestamp'] );
                        $this->fld_talkid = isset( $prop['talkid'] );
                        $this->fld_subjectid = isset( $prop['subjectid'] );
@@ -348,6 +350,10 @@ class ApiQueryInfo extends ApiQueryBase {
                        $this->getWatcherInfo();
                }
 
+               if ( $this->fld_visitingwatchers ) {
+                       $this->getVisitingWatcherInfo();
+               }
+
                // Run the talkid/subjectid query if requested
                if ( $this->fld_talkid || $this->fld_subjectid ) {
                        $this->getTSIDs();
@@ -447,6 +453,14 @@ class ApiQueryInfo extends ApiQueryBase {
                        }
                }
 
+               if ( $this->fld_visitingwatchers ) {
+                       if ( isset( $this->visitingwatchers[$ns][$dbkey] ) ) {
+                               $pageInfo['visitingwatchers'] = $this->visitingwatchers[$ns][$dbkey];
+                       } elseif ( $this->showZeroWatchers ) {
+                               $pageInfo['visitingwatchers'] = 0;
+                       }
+               }
+
                if ( $this->fld_notificationtimestamp ) {
                        $pageInfo['notificationtimestamp'] = '';
                        if ( isset( $this->notificationtimestamps[$ns][$dbkey] ) ) {
@@ -802,6 +816,98 @@ class ApiQueryInfo extends ApiQueryBase {
                }
        }
 
+       /**
+        * Get the count of watchers who have visited recent edits and put it in
+        * $this->visitingwatchers
+        *
+        * Based on InfoAction::pageCounts
+        */
+       private function getVisitingWatcherInfo() {
+               $config = $this->getConfig();
+               $user = $this->getUser();
+               $db = $this->getDB();
+
+               $canUnwatchedpages = $user->isAllowed( 'unwatchedpages' );
+               $unwatchedPageThreshold = $this->getConfig()->get( 'UnwatchedPageThreshold' );
+               if ( !$canUnwatchedpages && !is_int( $unwatchedPageThreshold ) ) {
+                       return;
+               }
+
+               $this->showZeroWatchers = $canUnwatchedpages;
+
+               // Assemble a WHERE condition to find:
+               // * if the page exists, number of users watching who have
+               //   visited the page recently
+               // * if the page doesn't exist, number of users that have
+               //   the page on their watchlist
+               $whereStrings = array();
+
+               // For pages that exist
+               if ( $this->titles ) {
+                       $lb = new LinkBatch( $this->titles );
+
+                       // Fetch last edit timestamps for pages
+                       $this->resetQueryParams();
+                       $this->addTables( array( 'page', 'revision' ) );
+                       $this->addFields( array( 'page_namespace', 'page_title', 'rev_timestamp' ) );
+                       $this->addWhere( array(
+                               'page_latest = rev_id',
+                               $lb->constructSet( 'page', $db ),
+                       ) );
+                       $this->addOption( 'GROUP BY', array( 'page_namespace', 'page_title' ) );
+                       $timestampRes = $this->select( __METHOD__ );
+
+                       // Assemble SQL WHERE condition to find number of page watchers who also
+                       // visited a "recent" edit (last visited about 26 weeks before latest edit)
+                       $age = $config->get( 'WatchersMaxAge' );
+                       $timestamps = array();
+                       foreach ( $timestampRes as $row ) {
+                               $revTimestamp = wfTimestamp( TS_UNIX, (int)$row->rev_timestamp );
+                               $threshold = $db->timestamp( $revTimestamp - $age );
+                               $timestamps[$row->page_namespace][$row->page_title] = $threshold;
+                       }
+
+                       foreach ( $timestamps as $ns_key => $namespace ) {
+                               $pageStrings = array();
+                               foreach ( $namespace as $pg_key => $threshold ) {
+                                       $pageStrings[] = "wl_title = '$pg_key' AND" .
+                                               ' (wl_notificationtimestamp >= ' .
+                                               $db->addQuotes( $threshold ) .
+                                               ' OR wl_notificationtimestamp IS NULL)';
+                               }
+                               $whereStrings[] = "wl_namespace = '$ns_key' AND (" .
+                                       $db->makeList( $pageStrings, LIST_OR ) . ')';
+                       }
+               }
+
+               // For nonexistant pages
+               if ( $this->missing ) {
+                       $lb = new LinkBatch( $this->missing );
+                       $whereStrings[] = $lb->constructSet( 'wl', $db );
+               }
+
+               // Make the actual string and do the query
+               $whereString = $db->makeList( $whereStrings, LIST_OR );
+
+               $this->resetQueryParams();
+               $this->addTables( array( 'watchlist' ) );
+               $this->addFields( array(
+                       'wl_namespace',
+                       'wl_title',
+                       'count' => 'COUNT(*)'
+               ) );
+               $this->addWhere( array( $whereString ) );
+               $this->addOption( 'GROUP BY', array( 'wl_namespace', 'wl_title' ) );
+               if ( !$canUnwatchedpages ) {
+                       $this->addOption( 'HAVING', "COUNT(*) >= $unwatchedPageThreshold" );
+               }
+
+               $res = $this->select( __METHOD__ );
+               foreach ( $res as $row ) {
+                       $this->visitingwatchers[$row->wl_namespace][$row->wl_title] = (int)$row->count;
+               }
+       }
+
        public function getCacheMode( $params ) {
                // Other props depend on something about the current user
                $publicProps = array(
@@ -837,6 +943,7 @@ class ApiQueryInfo extends ApiQueryBase {
                                        'talkid',
                                        'watched', # private
                                        'watchers', # private
+                                       'visitingwatchers', # private
                                        'notificationtimestamp', # private
                                        'subjectid',
                                        'url',
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 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 55baa47..1af53fa 100644 (file)
        "apihelp-query+info-paramvalue-prop-talkid": "The page ID of the talk page for each non-talk page.",
        "apihelp-query+info-paramvalue-prop-watched": "List the watched status of each page.",
        "apihelp-query+info-paramvalue-prop-watchers": "The number of watchers, if allowed.",
+       "apihelp-query+info-paramvalue-prop-visitingwatchers": "The number of watchers of each page who have visited recent edits to that page, if allowed.",
        "apihelp-query+info-paramvalue-prop-notificationtimestamp": "The watchlist notification timestamp of each page.",
        "apihelp-query+info-paramvalue-prop-subjectid": "The page ID of the parent page for each talk page.",
        "apihelp-query+info-paramvalue-prop-url": "Gives a full URL, an edit URL, and the canonical URL for each page.",
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 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 6705658..4d4614c 100644 (file)
        "apihelp-query+info-paramvalue-prop-talkid": "{{doc-apihelp-paramvalue|query+info|prop|talkid}}",
        "apihelp-query+info-paramvalue-prop-watched": "{{doc-apihelp-paramvalue|query+info|prop|watched}}",
        "apihelp-query+info-paramvalue-prop-watchers": "{{doc-apihelp-paramvalue|query+info|prop|watchers}}",
+       "apihelp-query+info-paramvalue-prop-visitingwatchers": "{{doc-apihelp-paramvalue|query+info|prop|visitingwatchers}}",
        "apihelp-query+info-paramvalue-prop-notificationtimestamp": "{{doc-apihelp-paramvalue|query+info|prop|notificationtimestamp}}",
        "apihelp-query+info-paramvalue-prop-subjectid": "{{doc-apihelp-paramvalue|query+info|prop|subjectid}}",
        "apihelp-query+info-paramvalue-prop-url": "{{doc-apihelp-paramvalue|query+info|prop|url}}",
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 af6f9d9..ab88834 100644 (file)
@@ -19,7 +19,7 @@
  *
  * @file
  * @author Kai Nissen
- * @author Adam Shorland
+ * @author Addshore
  * @since 1.27
  */
 
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 c72218a..cecb643 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
         */
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 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 c9e20a9..98c87a5 100644 (file)
@@ -169,7 +169,7 @@ class CategoryMembershipChangeJob extends Job {
                        $catMembChange->triggerCategoryAddedNotification( $categoryTitle );
                        if ( $insertCount++ && ( $insertCount % $batchSize ) == 0 ) {
                                $dbw->commit( __METHOD__, 'flush' );
-                               wfWaitForSlaves();
+                               wfGetLBFactory()->waitForReplication();
                        }
                }
 
@@ -178,7 +178,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 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 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 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 74ee6ab..d7b51b8 100644 (file)
@@ -1365,7 +1365,7 @@ MESSAGE;
         * @return string
         */
        public static function makeLoaderConditionalScript( $script ) {
-               return "window.RLQ = window.RLQ || []; window.RLQ.push( function () {\n" .
+               return "(window.RLQ = window.RLQ || []).push(function () {\n" .
                        trim( $script ) . "\n} );";
        }
 
@@ -1382,7 +1382,7 @@ MESSAGE;
                $js = self::makeLoaderConditionalScript( $script );
                return new WrappedString(
                        Html::inlineScript( $js ),
-                       "<script>window.RLQ = window.RLQ || []; window.RLQ.push( function () {\n",
+                       "<script>(window.RLQ = window.RLQ || []).push(function () {\n",
                        "\n} );</script>"
                );
        }
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 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..f86daaa 100644 (file)
@@ -262,6 +262,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 +544,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 +596,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 ) );
index ecc4e54..06a765c 100644 (file)
@@ -520,7 +520,7 @@ final class SessionManager implements SessionManagerInterface {
 
                // Reset the user's token to kill existing sessions
                $user = User::newFromName( $username );
-               if ( $user && $user->getToken() ) {
+               if ( $user && $user->getToken( false ) ) {
                        $user->setToken( true );
                        $user->saveSettings();
                }
@@ -801,6 +801,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;
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 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' );
        }
 
        /**
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..7c29242 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 );
@@ -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 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..354e39f 100644 (file)
        "botpasswords-label-grants": "Прыдатныя дазволы:",
        "botpasswords-label-restrictions": "Абмежаваньні на выкарыстаньне:",
        "botpasswords-label-grants-column": "Дазволена",
+       "botpasswords-bad-appid": "Назва робата «$1» зьяўляецца няслушнай.",
+       "botpasswords-insert-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 уключэньні",
        "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": "Ужываць мову па змоўчаньні",
index 2df341f..1a1c0c4 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": "আদি টেক্সট",
        "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-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": "এই পাতার ক্যাশে পরিষ্কার করতে চান?",
        "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 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 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 9abcabe..3ff65a5 100644 (file)
        "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-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 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..334869f 100644 (file)
@@ -16,6 +16,7 @@
        "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 +27,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.",
        "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.",
        "loginerror": "Erôr te jentrade",
        "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 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..5413ae7 100644 (file)
        "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-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 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..c077a82 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": "კარგი",
        "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 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..7a1ca4e 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-uselivepreview": "Livevoorvertoning gebruiken",
+       "tog-fancysig": "Handtekening als wikitekst behandelen (zonder automatische koppeling)",
+       "tog-uselivepreview": "Live voorvertoning gebruiken",
        "tog-forceeditsummary": "Een melding geven bij een lege bewerkingssamenvatting",
        "tog-watchlisthideown": "Eigen bewerkingen op mijn volglijst verbergen",
        "tog-watchlisthidebots": "Botbewerkingen op mijn volglijst verbergen",
        "databaseerror-query": "Zoekopdracht: $1",
        "databaseerror-function": "Functie: $1",
        "databaseerror-error": "Fout: $1",
+       "transaction-duration-limit-exceeded": "Deze transactie ($1) werd afgebroken omdat de {{PLURAL:$2|seconde|seconden}} limiet werd 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 'Promise-Non-Write-API-Action' HTTP header 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\"",
        "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 inloggegevens 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 in te loggen 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-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",
        "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",
        "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 lognummer",
        "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 log-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": "ID opslaan",
        "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 heeft $3 door middel van een bestandsupload {{GENDER:$2|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 heeft $3 uit $5 {{GENDER:$2|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",
        "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)",
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..6fdb43a 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.",
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 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 17cfff1..f2c6262 100644 (file)
        "rcshowhidemine": "ذاتی ترامیم $1",
        "rcshowhidemine-show": "دکھاؤ",
        "rcshowhidemine-hide": "چھپائیں",
+       "rcshowhidecategorization": "صفحاتی زمرہ بندی $1",
        "rcshowhidecategorization-show": "دکھائیں",
        "rcshowhidecategorization-hide": "چھپائیں",
        "rclinks": "آخری $2 روز میں ہونے والی $1 تبدیلیوں کا مشاہدہ کریں<br />$3",
        "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..f738420 100644 (file)
        "nstab-image": "文件",
        "nstab-mediawiki": "信息",
        "nstab-template": "模板",
-       "nstab-help": "幫å¿\99é \81",
+       "nstab-help": "帮å¿\99页",
        "nstab-category": "分类",
        "mainpage-nstab": "封面",
        "nosuchaction": "嘸能操作",
        "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": "囥脱",
        "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地址要勿用户名:",
        "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..e4f9dab 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的用户贡献",
index 1ffcc66..3e03502 100644 (file)
@@ -72,7 +72,9 @@
         *     while the widget is inactive. Should be as unambiguous as possible (for example, prefer to
         *     spell out the month, rather than rely on the order), even if that makes it longer. When not
         *     given, the default is language-specific.
-        * @cfg {string} [placeholder] User-visible date format string displayed in the textual input
+        * @cfg {string} [placeholderLabel=No date selected] Placeholder text shown when the widget is not
+        *     selected. Default text taken from message `mw-widgets-dateinput-no-date`.
+        * @cfg {string} [placeholderDateFormat] User-visible date format string displayed in the textual input
         *     field when it's empty. Should be the same as `inputFormat`, but translated to the user's
         *     language. When not given, defaults to a translated version of 'YYYY-MM-DD' or 'YYYY-MM',
         *     depending on `precision`.
         */
        mw.widgets.DateInputWidget = function MWWDateInputWidget( config ) {
                // Config initialization
-               config = $.extend( { precision: 'day', required: false }, config );
+               config = $.extend( {
+                       precision: 'day',
+                       required: false,
+                       placeholderLabel: mw.msg( 'mw-widgets-dateinput-no-date' )
+               }, config );
                if ( config.required ) {
                        if ( config.indicator === undefined ) {
                                config.indicator = 'required';
                        }
                }
 
-               var placeholder, mustBeAfter, mustBeBefore;
-               if ( config.placeholder ) {
-                       placeholder = config.placeholder;
+               var placeholderDateFormat, mustBeAfter, mustBeBefore;
+               if ( config.placeholderDateFormat ) {
+                       placeholderDateFormat = config.placeholderDateFormat;
                } else if ( config.inputFormat ) {
                        // We have no way to display a translated placeholder for custom formats
-                       placeholder = '';
+                       placeholderDateFormat = '';
                } else {
                        // Messages: mw-widgets-dateinput-placeholder-day, mw-widgets-dateinput-placeholder-month
-                       placeholder = mw.msg( 'mw-widgets-dateinput-placeholder-' + config.precision );
+                       placeholderDateFormat = mw.msg( 'mw-widgets-dateinput-placeholder-' + config.precision );
                }
 
                // Properties (must be set before parent constructor, which calls #setValue)
                this.label = new OO.ui.LabelWidget();
                this.textInput = new OO.ui.TextInputWidget( {
                        required: config.required,
-                       placeholder: placeholder,
+                       placeholder: placeholderDateFormat,
                        validate: this.validateDate.bind( this )
                } );
                this.calendar = new mw.widgets.CalendarWidget( {
                this.inputFormat = config.inputFormat;
                this.displayFormat = config.displayFormat;
                this.required = config.required;
+               this.placeholderLabel = config.placeholderLabel;
 
                // Validate and set min and max dates as properties
                mustBeAfter = moment( config.mustBeAfter, 'YYYY-MM-DD' );
                if ( this.getValue() === '' ) {
                        this.textInput.setValue( '' );
                        this.calendar.setDate( null );
-                       this.label.setLabel( mw.msg( 'mw-widgets-dateinput-no-date' ) );
+                       this.label.setLabel( this.placeholderLabel );
                        this.$element.addClass( 'mw-widget-dateInputWidget-empty' );
                } else {
                        if ( !this.inTextInput ) {
index f9b0d35..a63202f 100644 (file)
@@ -31,6 +31,7 @@
                        apiRequest = new mw.Api();
 
                        apiRequest.postWithToken( 'patrol', {
+                               formatversion: 2,
                                action: 'patrol',
                                rcid: rcid
                        } )
index 0f51a35..0c2d6d6 100644 (file)
@@ -87,7 +87,7 @@ function isCompatible( ua ) {
 
                // Must be after mw.config.set because these callbacks may use mw.loader which
                // needs to have values 'skin', 'debug' etc. from mw.config.
-               window.RLQ = window.RLQ || [];
+               var RLQ = window.RLQ || [];
                while ( RLQ.length ) {
                        RLQ.shift()();
                }
index 51f0083..f113b1f 100644 (file)
@@ -86,7 +86,7 @@ class EditPageTest extends MediaWikiLangTestCase {
         * @param string $msg
         */
        protected function assertEditedTextEquals( $expected, $actual, $msg = '' ) {
-               return $this->assertEquals( rtrim( $expected ), rtrim( $actual ), $msg );
+               $this->assertEquals( rtrim( $expected ), rtrim( $actual ), $msg );
        }
 
        /**
@@ -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 f5ef016..cfc416b 100644 (file)
@@ -142,7 +142,7 @@ class OutputPageTest extends MediaWikiTestCase {
                        // Load module script only
                        array(
                                array( 'test.foo', ResourceLoaderModule::TYPE_SCRIPTS ),
-                               "<script>window.RLQ = window.RLQ || []; window.RLQ.push( function () {\n"
+                               "<script>(window.RLQ = window.RLQ || []).push(function () {\n"
                                        . 'mw.loader.load("http://127.0.0.1:8080/w/load.php?debug=false\u0026lang=en\u0026modules=test.foo\u0026only=scripts\u0026skin=fallback");'
                                        . "\n} );</script>"
                        ),
@@ -161,14 +161,14 @@ class OutputPageTest extends MediaWikiTestCase {
                        // Load private module (only=scripts)
                        array(
                                array( 'test.quux', ResourceLoaderModule::TYPE_SCRIPTS ),
-                               "<script>window.RLQ = window.RLQ || []; window.RLQ.push( function () {\n"
+                               "<script>(window.RLQ = window.RLQ || []).push(function () {\n"
                                        . "mw.test.baz({token:123});mw.loader.state({\"test.quux\":\"ready\"});\n"
                                        . "} );</script>"
                        ),
                        // Load private module (combined)
                        array(
                                array( 'test.quux', ResourceLoaderModule::TYPE_COMBINED ),
-                               "<script>window.RLQ = window.RLQ || []; window.RLQ.push( function () {\n"
+                               "<script>(window.RLQ = window.RLQ || []).push(function () {\n"
                                        . "mw.loader.implement(\"test.quux\",function($,jQuery){"
                                        . "mw.test.baz({token:123});},{\"css\":[\".mw-icon{transition:none}"
                                        . "\"]});\n} );</script>"
@@ -186,10 +186,10 @@ class OutputPageTest extends MediaWikiTestCase {
                        // Load two modules in separate groups
                        array(
                                array( array( 'test.group.foo', 'test.group.bar' ), ResourceLoaderModule::TYPE_COMBINED ),
-                               "<script>window.RLQ = window.RLQ || []; window.RLQ.push( function () {\n"
+                               "<script>(window.RLQ = window.RLQ || []).push(function () {\n"
                                        . 'mw.loader.load("http://127.0.0.1:8080/w/load.php?debug=false\u0026lang=en\u0026modules=test.group.bar\u0026skin=fallback");'
                                        . "\n} );</script>\n"
-                                       . "<script>window.RLQ = window.RLQ || []; window.RLQ.push( function () {\n"
+                                       . "<script>(window.RLQ = window.RLQ || []).push(function () {\n"
                                        . 'mw.loader.load("http://127.0.0.1:8080/w/load.php?debug=false\u0026lang=en\u0026modules=test.group.foo\u0026skin=fallback");'
                                        . "\n} );</script>"
                        ),
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 c95e69b..f5d0480 100644 (file)
@@ -1,7 +1,7 @@
 <?php
 
 /**
- * @author Adam Shorland
+ * @author Addshore
  */
 class StatusTest extends MediaWikiLangTestCase {
 
index aad435e..f06208b 100644 (file)
@@ -1,7 +1,7 @@
 <?php
 
 /**
- * @author Adam Shorland
+ * @author Addshore
  * @covers TitleArrayFromResult
  */
 class TitleArrayFromResultTest extends PHPUnit_Framework_TestCase {
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 2622ad4..70da12e 100644 (file)
@@ -5,7 +5,7 @@
  *
  * @group Database
  *
- * @author Adam Shorland
+ * @author Addshore
  */
 class CategoryMembershipChangeTest extends MediaWikiLangTestCase {
 
index 8a9d2ab..6a6cecc 100644 (file)
@@ -1,7 +1,7 @@
 <?php
 
 /**
- * @author Adam Shorland
+ * @author Addshore
  * @covers JsonContent
  */
 class JsonContentTest extends MediaWikiLangTestCase {
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 a546bec..f4757a4 100644 (file)
@@ -1,7 +1,7 @@
 <?php
 
 /**
- * @author Adam Shorland
+ * @author Addshore
  *
  * @group Diff
  */
index cbe0573..d15e6cd 100644 (file)
@@ -1,6 +1,6 @@
 <?php
 /**
- * @author Adam Shorland
+ * @author Addshore
  *
  * @group Diff
  */
index e0d7915..31e0f87 100644 (file)
@@ -1,7 +1,7 @@
 <?php
 
 /**
- * @author Adam Shorland
+ * @author Addshore
  *
  * @group Diff
  */
index 500b7e4..e6a1812 100644 (file)
@@ -1,7 +1,7 @@
 <?php
 /**
  * @covers BadTitleError
- * @author Adam Shorland
+ * @author Addshore
  */
 class BadTitleErrorTest extends MediaWikiTestCase {
 
index 9c4e4a0..d045268 100644 (file)
@@ -2,7 +2,7 @@
 
 /**
  * @covers ErrorPageError
- * @author Adam Shorland
+ * @author Addshore
  */
 class ErrorPageErrorTest extends MediaWikiTestCase {
 
index 6f6aba4..bb874e1 100644 (file)
@@ -2,7 +2,7 @@
 
 /**
  * @covers ReadOnlyError
- * @author Adam Shorland
+ * @author Addshore
  */
 class ReadOnlyErrorTest extends MediaWikiTestCase {
 
index a1cf84b..23bb1e8 100644 (file)
@@ -2,7 +2,7 @@
 
 /**
  * @covers ThrottledError
- * @author Adam Shorland
+ * @author Addshore
  */
 class ThrottledErrorTest extends MediaWikiTestCase {
 
index 591a0fa..644de0b 100644 (file)
@@ -2,7 +2,7 @@
 
 /**
  * @covers UserNotLoggedIn
- * @author Adam Shorland
+ * @author Addshore
  */
 class UserNotLoggedInTest extends MediaWikiTestCase {
 
index 93069d2..0550a93 100644 (file)
@@ -1,7 +1,7 @@
 <?php
 
 /**
- * @author Adam Shorland
+ * @author Addshore
  */
 class JobTest extends MediaWikiTestCase {
 
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 083223e..f5bb07d 100644 (file)
@@ -1604,6 +1604,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 1d4f5e5..7bfb861 100644 (file)
@@ -2,7 +2,7 @@
 
 /**
  * @licence GNU GPL v2+
- * @author Adam Shorland
+ * @author Addshore
  *
  * @covers SpecialBlankpage
  */
index 9c7b0f0..db8ae0f 100644 (file)
@@ -8,7 +8,7 @@
  * @licence GNU GPL v2+
  * @author Jeroen De Dauw < jeroendedauw@gmail.com >
  * @author Daniel Kinzler
- * @author Adam Shorland
+ * @author Addshore
  * @author Thiemo Mättig
  */
 abstract class SpecialPageTestBase extends MediaWikiTestCase {
index 469ad29..4bc7765 100644 (file)
@@ -1,7 +1,7 @@
 <?php
 
 /**
- * @author Adam Shorland
+ * @author Addshore
  * @covers UserArrayFromResult
  */
 class UserArrayFromResultTest extends MediaWikiTestCase {
index 64def91..8887499 100644 (file)
@@ -2,7 +2,7 @@
 
 /**
  * @covers MediaWikiTestCase
- * @author Adam Shorland
+ * @author Addshore
  */
 class MediaWikiTestCaseTest extends MediaWikiTestCase {