Merge "Add SpecialPage::getTitleValueFor()"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Thu, 11 Aug 2016 08:32:35 +0000 (08:32 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Thu, 11 Aug 2016 08:32:35 +0000 (08:32 +0000)
194 files changed:
autoload.php
docs/hooks.txt
includes/DefaultSettings.php
includes/FeedUtils.php
includes/Preferences.php
includes/Setup.php
includes/actions/PurgeAction.php
includes/api/ApiCreateAccount.php [deleted file]
includes/api/ApiLogin.php
includes/api/ApiQueryUsers.php
includes/api/ApiStashEdit.php
includes/api/ApiUpload.php
includes/api/i18n/de.json
includes/api/i18n/en.json
includes/api/i18n/gl.json
includes/api/i18n/qqq.json
includes/api/i18n/uk.json
includes/api/i18n/zh-hans.json
includes/auth/AuthManager.php
includes/dao/IDBAccessObject.php
includes/db/Database.php
includes/db/DatabaseMysql.php
includes/db/DatabaseMysqlBase.php
includes/db/DatabaseMysqli.php
includes/db/IDatabase.php
includes/db/loadbalancer/LBFactory.php
includes/db/loadbalancer/LBFactoryMulti.php
includes/db/loadbalancer/LBFactorySimple.php
includes/db/loadbalancer/LBFactorySingle.php
includes/db/loadbalancer/LoadBalancer.php
includes/filebackend/lockmanager/DBLockManager.php
includes/installer/MssqlUpdater.php
includes/installer/MysqlUpdater.php
includes/installer/OracleUpdater.php
includes/installer/PostgresUpdater.php
includes/installer/SqliteUpdater.php
includes/installer/i18n/bg.json
includes/installer/i18n/my.json
includes/jobqueue/JobRunner.php
includes/media/DjVuImage.php
includes/parser/Parser.php
includes/session/SessionManager.php
includes/skins/SkinTemplate.php
includes/specialpage/LoginSignupSpecialPage.php
includes/specialpage/SpecialPage.php
includes/specialpage/SpecialPageFactory.php
includes/specials/SpecialEditWatchlist.php
includes/specials/SpecialUpload.php
includes/specials/SpecialWatchlist.php
includes/specials/pre-authmanager/README [deleted file]
includes/specials/pre-authmanager/SpecialChangeEmail.php [deleted file]
includes/specials/pre-authmanager/SpecialChangePassword.php [deleted file]
includes/specials/pre-authmanager/SpecialCreateAccount.php [deleted file]
includes/specials/pre-authmanager/SpecialPasswordReset.php [deleted file]
includes/specials/pre-authmanager/SpecialUserlogin.php [deleted file]
includes/specials/pre-authmanager/SpecialUserlogout.php [deleted file]
includes/templates/Usercreate.php [deleted file]
includes/templates/Userlogin.php [deleted file]
includes/upload/UploadBase.php
includes/upload/UploadFromChunks.php
includes/upload/UploadFromStash.php
includes/user/User.php
includes/utils/AutoloadGenerator.php
languages/i18n/ar.json
languages/i18n/arz.json
languages/i18n/ast.json
languages/i18n/az.json
languages/i18n/azb.json
languages/i18n/ba.json
languages/i18n/bar.json
languages/i18n/bcl.json
languages/i18n/be-tarask.json
languages/i18n/bg.json
languages/i18n/bn.json
languages/i18n/bs.json
languages/i18n/ca.json
languages/i18n/cs.json
languages/i18n/cy.json
languages/i18n/da.json
languages/i18n/de.json
languages/i18n/diq.json
languages/i18n/dsb.json
languages/i18n/dty.json
languages/i18n/en.json
languages/i18n/eo.json
languages/i18n/es.json
languages/i18n/et.json
languages/i18n/eu.json
languages/i18n/fa.json
languages/i18n/fi.json
languages/i18n/fr.json
languages/i18n/gd.json
languages/i18n/gl.json
languages/i18n/gu.json
languages/i18n/he.json
languages/i18n/hr.json
languages/i18n/hsb.json
languages/i18n/ht.json
languages/i18n/hu.json
languages/i18n/ia.json
languages/i18n/ilo.json
languages/i18n/it.json
languages/i18n/ja.json
languages/i18n/jv.json
languages/i18n/kk-cyrl.json
languages/i18n/kn.json
languages/i18n/ko.json
languages/i18n/ksh.json
languages/i18n/la.json
languages/i18n/lb.json
languages/i18n/li.json
languages/i18n/lki.json
languages/i18n/lt.json
languages/i18n/lv.json
languages/i18n/mai.json
languages/i18n/min.json
languages/i18n/mk.json
languages/i18n/ml.json
languages/i18n/ms.json
languages/i18n/my.json
languages/i18n/nah.json
languages/i18n/nap.json
languages/i18n/nb.json
languages/i18n/nds.json
languages/i18n/ne.json
languages/i18n/nl.json
languages/i18n/nn.json
languages/i18n/pa.json
languages/i18n/pl.json
languages/i18n/pms.json
languages/i18n/pt-br.json
languages/i18n/pt.json
languages/i18n/qqq.json
languages/i18n/ro.json
languages/i18n/roa-tara.json
languages/i18n/ru.json
languages/i18n/sa.json
languages/i18n/sco.json
languages/i18n/sgs.json
languages/i18n/sh.json
languages/i18n/sl.json
languages/i18n/so.json
languages/i18n/sv.json
languages/i18n/szl.json
languages/i18n/te.json
languages/i18n/th.json
languages/i18n/tr.json
languages/i18n/tt-cyrl.json
languages/i18n/uk.json
languages/i18n/vec.json
languages/i18n/vi.json
languages/i18n/yi.json
languages/i18n/yo.json
languages/i18n/yue.json
languages/i18n/zh-hans.json
languages/i18n/zh-hant.json
maintenance/archives/patch-add-rc_name_type_patrolled_timestamp_index.sql [new file with mode: 0644]
maintenance/changePassword.php
maintenance/convertExtensionToRegistration.php
maintenance/createAndPromote.php
maintenance/initEditCount.php
maintenance/mssql/tables.sql
maintenance/oracle/archives/patch-add-rc_name_type_patrolled_timestamp_index.sql [new file with mode: 0644]
maintenance/oracle/tables.sql
maintenance/postgres/tables.sql
maintenance/purgeChangedFiles.php
maintenance/storage/fixBug20757.php
maintenance/tables.sql
resources/src/mediawiki.action/mediawiki.action.edit.stash.js
resources/src/mediawiki/mediawiki.js
tests/phpunit/includes/api/ApiLoginTest.php
tests/phpunit/includes/api/ApiTestCase.php
tests/phpunit/includes/auth/AbstractAuthenticationProviderTest.php
tests/phpunit/includes/auth/AbstractPasswordPrimaryAuthenticationProviderTest.php
tests/phpunit/includes/auth/AbstractPreAuthenticationProviderTest.php
tests/phpunit/includes/auth/AbstractPrimaryAuthenticationProviderTest.php
tests/phpunit/includes/auth/AbstractSecondaryAuthenticationProviderTest.php
tests/phpunit/includes/auth/AuthManagerTest.php
tests/phpunit/includes/auth/AuthPluginPrimaryAuthenticationProviderTest.php
tests/phpunit/includes/auth/AuthenticationRequestTest.php
tests/phpunit/includes/auth/AuthenticationRequestTestCase.php
tests/phpunit/includes/auth/AuthenticationResponseTest.php
tests/phpunit/includes/auth/CheckBlocksSecondaryAuthenticationProviderTest.php
tests/phpunit/includes/auth/ConfirmLinkSecondaryAuthenticationProviderTest.php
tests/phpunit/includes/auth/LegacyHookPreAuthenticationProviderTest.php
tests/phpunit/includes/auth/LocalPasswordPrimaryAuthenticationProviderTest.php
tests/phpunit/includes/auth/ResetPasswordSecondaryAuthenticationProviderTest.php
tests/phpunit/includes/auth/TemporaryPasswordPrimaryAuthenticationProviderTest.php
tests/phpunit/includes/auth/ThrottlePreAuthenticationProviderTest.php
tests/phpunit/includes/auth/ThrottlerTest.php
tests/phpunit/includes/db/DatabaseMysqlBaseTest.php
tests/phpunit/includes/session/SessionManagerTest.php
tests/phpunit/phpunit.php
tests/qunit/suites/resources/mediawiki/mediawiki.test.js

index 29f986e..513ec96 100644 (file)
@@ -28,7 +28,6 @@ $wgAutoloadLocalClasses = [
        'ApiClientLogin' => __DIR__ . '/includes/api/ApiClientLogin.php',
        'ApiComparePages' => __DIR__ . '/includes/api/ApiComparePages.php',
        'ApiContinuationManager' => __DIR__ . '/includes/api/ApiContinuationManager.php',
-       'ApiCreateAccount' => __DIR__ . '/includes/api/ApiCreateAccount.php',
        'ApiDelete' => __DIR__ . '/includes/api/ApiDelete.php',
        'ApiDisabled' => __DIR__ . '/includes/api/ApiDisabled.php',
        'ApiEditPage' => __DIR__ . '/includes/api/ApiEditPage.php',
@@ -748,8 +747,6 @@ $wgAutoloadLocalClasses = [
        'LoggedOutEditToken' => __DIR__ . '/includes/user/LoggedOutEditToken.php',
        'LoggedUpdateMaintenance' => __DIR__ . '/maintenance/Maintenance.php',
        'LoginForm' => __DIR__ . '/includes/specialpage/LoginSignupSpecialPage.php',
-       'LoginFormAuthManager' => __DIR__ . '/includes/specialpage/LoginSignupSpecialPage.php',
-       'LoginFormPreAuthManager' => __DIR__ . '/includes/specials/pre-authmanager/SpecialUserlogin.php',
        'LoginHelper' => __DIR__ . '/includes/specials/helpers/LoginHelper.php',
        'LoginSignupSpecialPage' => __DIR__ . '/includes/specialpage/LoginSignupSpecialPage.php',
        'LonelyPagesPage' => __DIR__ . '/includes/specials/SpecialLonelypages.php',
@@ -1281,13 +1278,10 @@ $wgAutoloadLocalClasses = [
        'SpecialChangeContentModel' => __DIR__ . '/includes/specials/SpecialChangeContentModel.php',
        'SpecialChangeCredentials' => __DIR__ . '/includes/specials/SpecialChangeCredentials.php',
        'SpecialChangeEmail' => __DIR__ . '/includes/specials/SpecialChangeEmail.php',
-       'SpecialChangeEmailPreAuthManager' => __DIR__ . '/includes/specials/pre-authmanager/SpecialChangeEmail.php',
        'SpecialChangePassword' => __DIR__ . '/includes/specials/SpecialChangePassword.php',
-       'SpecialChangePasswordPreAuthManager' => __DIR__ . '/includes/specials/pre-authmanager/SpecialChangePassword.php',
        'SpecialComparePages' => __DIR__ . '/includes/specials/SpecialComparePages.php',
        'SpecialContributions' => __DIR__ . '/includes/specials/SpecialContributions.php',
        'SpecialCreateAccount' => __DIR__ . '/includes/specials/SpecialCreateAccount.php',
-       'SpecialCreateAccountPreAuthManager' => __DIR__ . '/includes/specials/pre-authmanager/SpecialCreateAccount.php',
        'SpecialDiff' => __DIR__ . '/includes/specials/SpecialDiff.php',
        'SpecialEditTags' => __DIR__ . '/includes/specials/SpecialEditTags.php',
        'SpecialEditWatchlist' => __DIR__ . '/includes/specials/SpecialEditWatchlist.php',
@@ -1320,7 +1314,6 @@ $wgAutoloadLocalClasses = [
        'SpecialPageLanguage' => __DIR__ . '/includes/specials/SpecialPageLanguage.php',
        'SpecialPagesWithProp' => __DIR__ . '/includes/specials/SpecialPagesWithProp.php',
        'SpecialPasswordReset' => __DIR__ . '/includes/specials/SpecialPasswordReset.php',
-       'SpecialPasswordResetPreAuthManager' => __DIR__ . '/includes/specials/pre-authmanager/SpecialPasswordReset.php',
        'SpecialPermanentLink' => __DIR__ . '/includes/specials/SpecialPermanentLink.php',
        'SpecialPreferences' => __DIR__ . '/includes/specials/SpecialPreferences.php',
        'SpecialPrefixindex' => __DIR__ . '/includes/specials/SpecialPrefixindex.php',
@@ -1351,7 +1344,6 @@ $wgAutoloadLocalClasses = [
        'SpecialUploadStashTooLargeException' => __DIR__ . '/includes/specials/SpecialUploadStash.php',
        'SpecialUserLogin' => __DIR__ . '/includes/specials/SpecialUserLogin.php',
        'SpecialUserLogout' => __DIR__ . '/includes/specials/SpecialUserLogout.php',
-       'SpecialUserlogoutPreAuthManager' => __DIR__ . '/includes/specials/pre-authmanager/SpecialUserlogout.php',
        'SpecialVersion' => __DIR__ . '/includes/specials/SpecialVersion.php',
        'SpecialWatchlist' => __DIR__ . '/includes/specials/SpecialWatchlist.php',
        'SpecialWhatLinksHere' => __DIR__ . '/includes/specials/SpecialWhatlinkshere.php',
@@ -1487,8 +1479,6 @@ $wgAutoloadLocalClasses = [
        'UserOptions' => __DIR__ . '/maintenance/userOptions.inc',
        'UserPasswordPolicy' => __DIR__ . '/includes/password/UserPasswordPolicy.php',
        'UserRightsProxy' => __DIR__ . '/includes/user/UserRightsProxy.php',
-       'UsercreateTemplate' => __DIR__ . '/includes/templates/Usercreate.php',
-       'UserloginTemplate' => __DIR__ . '/includes/templates/Userlogin.php',
        'UserrightsPage' => __DIR__ . '/includes/specials/SpecialUserrights.php',
        'UsersPager' => __DIR__ . '/includes/specials/pagers/UsersPager.php',
        'UtfNormal' => __DIR__ . '/includes/compat/normal/UtfNormal.php',
index 8fa3793..5cf8ffe 100644 (file)
@@ -3373,6 +3373,18 @@ added to the descriptor
 &$radio: Boolean, if source type should be shown as radio button
 $selectedSourceType: The selected source type
 
+'UploadStashFile': Before a file is stashed (uploaded to stash).
+Note that code which has not been updated for MediaWiki 1.28 may not call this
+hook. If your extension absolutely, positively must prevent some files from
+being uploaded, use UploadVerifyFile or UploadVerifyUpload.
+$upload: (object) An instance of UploadBase, with all info about the upload
+$user: (object) An instance of User, the user uploading this file
+$props: (array) File properties, as returned by FSFile::getPropsFromPath()
+&$error: output: If the file stashing should be prevented, set this to the reason
+  in the form of array( messagename, param1, param2, ... ) or a MessageSpecifier
+  instance (you might want to use ApiMessage to provide machine-readable details
+  for the API).
+
 'UploadVerification': DEPRECATED! Use UploadVerifyFile instead.
 Additional chances to reject an uploaded file.
 $saveName: (string) destination file name
index 3c5e2d2..2ac31bf 100644 (file)
@@ -4447,13 +4447,6 @@ $wgPasswordPolicy = [
        ],
 ];
 
-/**
- * Disable AuthManager
- * @since 1.27
- * @deprecated since 1.27, for use during development only
- */
-$wgDisableAuthManager = false;
-
 /**
  * Configure AuthManager
  *
@@ -5058,7 +5051,7 @@ $wgGroupPermissions['user']['upload'] = true;
 $wgGroupPermissions['user']['reupload'] = true;
 $wgGroupPermissions['user']['reupload-shared'] = true;
 $wgGroupPermissions['user']['minoredit'] = true;
-$wgGroupPermissions['user']['purge'] = true; // can use ?action=purge without clicking "ok"
+$wgGroupPermissions['user']['purge'] = true;
 $wgGroupPermissions['user']['sendemail'] = true;
 $wgGroupPermissions['user']['applychangetags'] = true;
 $wgGroupPermissions['user']['changetags'] = true;
@@ -8173,13 +8166,6 @@ $wgTextModelsToParse = [
        CONTENT_MODEL_CSS, // Make categories etc work, people put them into comments.
 ];
 
-/**
- * Whether the user must enter their password to change their e-mail address
- *
- * @since 1.20
- */
-$wgRequirePasswordforEmailChange = true;
-
 /**
  * Register handlers for specific types of sites.
  *
index d7dbd22..071a3db 100644 (file)
@@ -39,6 +39,7 @@ class FeedUtils {
                global $wgRequest, $wgUser;
 
                $purge = $wgRequest->getVal( 'action' ) === 'purge';
+               // Allow users with 'purge' right to clear feed caches
                if ( $purge && $wgUser->isAllowed( 'purge' ) ) {
                        $cache = ObjectCache::getMainWANInstance();
                        $cache->delete( $timekey, 1 );
index 3083a8d..70addfc 100644 (file)
@@ -207,8 +207,9 @@ class Preferences {
         * @return void
         */
        static function profilePreferences( $user, IContextSource $context, &$defaultPreferences ) {
-               global $wgAuth, $wgContLang, $wgParser, $wgDisableAuthManager;
+               global $wgContLang, $wgParser;
 
+               $authManager = AuthManager::singleton();
                $config = $context->getConfig();
                // retrieving user name for GENDER and misc.
                $userName = $user->getName();
@@ -283,21 +284,19 @@ class Preferences {
                $canEditPrivateInfo = $user->isAllowed( 'editmyprivateinfo' );
 
                // Actually changeable stuff
-               $realnameChangeAllowed = $wgDisableAuthManager ? $wgAuth->allowPropChange( 'realname' )
-                       : AuthManager::singleton()->allowsPropertyChange( 'realname' );
                $defaultPreferences['realname'] = [
                        // (not really "private", but still shouldn't be edited without permission)
-                       'type' => $canEditPrivateInfo && $realnameChangeAllowed ? 'text' : 'info',
+                       'type' => $canEditPrivateInfo && $authManager->allowsPropertyChange( 'realname' )
+                               ? 'text' : 'info',
                        'default' => $user->getRealName(),
                        'section' => 'personal/info',
                        'label-message' => 'yourrealname',
                        'help-message' => 'prefs-help-realname',
                ];
 
-               $allowPasswordChange = $wgDisableAuthManager ? $wgAuth->allowPasswordChange()
-                       : AuthManager::singleton()->allowsAuthenticationDataChange(
-                               new PasswordAuthenticationRequest(), false )->isGood();
-               if ( $canEditPrivateInfo && $allowPasswordChange ) {
+               if ( $canEditPrivateInfo && $authManager->allowsAuthenticationDataChange(
+                       new PasswordAuthenticationRequest(), false )->isGood()
+               ) {
                        $link = Linker::link( SpecialPage::getTitleFor( 'ChangePassword' ),
                                $context->msg( 'prefs-resetpass' )->escaped(), [],
                                [ 'returnto' => SpecialPage::getTitleFor( 'Preferences' )->getPrefixedText() ] );
@@ -418,10 +417,8 @@ class Preferences {
                        'default' => $oldsigHTML,
                        'section' => 'personal/signature',
                ];
-               $nicknameChangeAllowed = $wgDisableAuthManager ? $wgAuth->allowPropChange( 'nickname' )
-                       : AuthManager::singleton()->allowsPropertyChange( 'nickname' );
                $defaultPreferences['nickname'] = [
-                       'type' => $nicknameChangeAllowed ? 'text' : 'info',
+                       'type' => $authManager->allowsPropertyChange( 'nickname' ) ? 'text' : 'info',
                        'maxlength' => $config->get( 'MaxSigChars' ),
                        'label-message' => 'yournick',
                        'validation-callback' => [ 'Preferences', 'validateSignature' ],
@@ -450,9 +447,7 @@ class Preferences {
                                }
 
                                $emailAddress = $user->getEmail() ? htmlspecialchars( $user->getEmail() ) : '';
-                               $emailChangeAllowed = $wgDisableAuthManager ? $wgAuth->allowPropChange( 'emailaddress' )
-                                       : AuthManager::singleton()->allowsPropertyChange( 'emailaddress' );
-                               if ( $canEditPrivateInfo && $emailChangeAllowed ) {
+                               if ( $canEditPrivateInfo && $authManager->allowsPropertyChange( 'emailaddress' ) ) {
                                        $link = Linker::link(
                                                SpecialPage::getTitleFor( 'ChangeEmail' ),
                                                $context->msg( $user->getEmail() ? 'prefs-changeemail' : 'prefs-setemail' )->escaped(),
index 6c5de90..7909889 100644 (file)
@@ -452,22 +452,6 @@ if ( $wgProfileOnly ) {
        $wgDebugLogFile = '';
 }
 
-// Disable AuthManager API modules if $wgDisableAuthManager
-if ( $wgDisableAuthManager ) {
-       $wgAPIModules += [
-               'clientlogin' => 'ApiDisabled',
-               'createaccount' => 'ApiCreateAccount', // Use the non-AuthManager version
-               'linkaccount' => 'ApiDisabled',
-               'unlinkaccount' => 'ApiDisabled',
-               'changeauthenticationdata' => 'ApiDisabled',
-               'removeauthenticationdata' => 'ApiDisabled',
-               'resetpassword' => 'ApiDisabled',
-       ];
-       $wgAPIMetaModules += [
-               'authmanagerinfo' => 'ApiQueryDisabled',
-       ];
-}
-
 // Backwards compatibility with old password limits
 if ( $wgMinimalPasswordLength !== false ) {
        $wgPasswordPolicy['policies']['default']['MinimalPasswordLength'] = $wgMinimalPasswordLength;
@@ -711,12 +695,10 @@ $wgContLang->initContLang();
 $wgRequest->interpolateTitle();
 
 if ( !is_object( $wgAuth ) ) {
-       $wgAuth = $wgDisableAuthManager ? new AuthPlugin : new MediaWiki\Auth\AuthManagerAuthPlugin;
+       $wgAuth = new MediaWiki\Auth\AuthManagerAuthPlugin;
        Hooks::run( 'AuthPluginSetup', [ &$wgAuth ] );
 }
-if ( !$wgDisableAuthManager &&
-       $wgAuth && !$wgAuth instanceof MediaWiki\Auth\AuthManagerAuthPlugin
-) {
+if ( $wgAuth && !$wgAuth instanceof MediaWiki\Auth\AuthManagerAuthPlugin ) {
        MediaWiki\Auth\AuthManager::singleton()->forcePrimaryAuthenticationProviders( [
                new MediaWiki\Auth\TemporaryPasswordPrimaryAuthenticationProvider( [
                        'authoritative' => false,
@@ -852,15 +834,11 @@ if ( !defined( 'MW_NO_SESSION' ) && !$wgCommandLineMode ) {
        $sessionUser = MediaWiki\Session\SessionManager::getGlobalSession()->getUser();
        if ( $sessionUser->getId() === 0 && User::isValidUserName( $sessionUser->getName() ) ) {
                $ps_autocreate = Profiler::instance()->scopedProfileIn( $fname . '-autocreate' );
-               if ( $wgDisableAuthManager ) {
-                       $res = MediaWiki\Session\SessionManager::autoCreateUser( $sessionUser );
-               } else {
-                       $res = MediaWiki\Auth\AuthManager::singleton()->autoCreateUser(
-                               $sessionUser,
-                               MediaWiki\Auth\AuthManager::AUTOCREATE_SOURCE_SESSION,
-                               true
-                       );
-               }
+               $res = MediaWiki\Auth\AuthManager::singleton()->autoCreateUser(
+                       $sessionUser,
+                       MediaWiki\Auth\AuthManager::AUTOCREATE_SOURCE_SESSION,
+                       true
+               );
                Profiler::instance()->scopedProfileOut( $ps_autocreate );
                \MediaWiki\Logger\LoggerFactory::getInstance( 'authmanager' )->info( 'Autocreation attempt', [
                        'event' => 'autocreate',
index 576533d..b2002ff 100644 (file)
  */
 
 /**
- * User-requested page cache purging.
- *
- * For users with 'purge', this will directly trigger the cache purging and
- * for users without that right, it will show a confirmation form.
+ * User-requested page cache purging
  *
  * @ingroup Actions
  */
@@ -48,10 +45,6 @@ class PurgeAction extends FormAction {
                return $this->page->doPurge();
        }
 
-       /**
-        * purge is slightly weird because it can be either formed or formless depending
-        * on user permissions
-        */
        public function show() {
                $this->setHeaders();
 
@@ -65,11 +58,7 @@ class PurgeAction extends FormAction {
                        return;
                }
 
-               if ( $user->isAllowed( 'purge' ) ) {
-                       // This will update the database immediately, even on HTTP GET.
-                       // Lots of uses may exist for this feature, so just ignore warnings.
-                       Profiler::instance()->getTransactionProfiler()->resetExpectations();
-
+               if ( $this->getRequest()->wasPosted() ) {
                        $this->redirectParams = wfArrayToCgi( array_diff_key(
                                $this->getRequest()->getQueryValues(),
                                [ 'title' => null, 'action' => null ]
diff --git a/includes/api/ApiCreateAccount.php b/includes/api/ApiCreateAccount.php
deleted file mode 100644 (file)
index 6a48610..0000000
+++ /dev/null
@@ -1,238 +0,0 @@
-<?php
-/**
- * Created on August 7, 2012
- *
- * Copyright © 2012 Tyler Romeo <tylerromeo@gmail.com>
- *
- * 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
- */
-use MediaWiki\Logger\LoggerFactory;
-
-/**
- * Unit to authenticate account registration attempts to the current wiki.
- *
- * @ingroup API
- * @deprecated since 1.27, only used when $wgDisableAuthManager is true
- */
-class ApiCreateAccount extends ApiBase {
-       public function execute() {
-               // If we're in a mode that breaks the same-origin policy, no tokens can
-               // be obtained
-               if ( $this->lacksSameOriginSecurity() ) {
-                       $this->dieUsage(
-                               'Cannot create account when the same-origin policy is not applied', 'aborted'
-                       );
-               }
-
-               // $loginForm->addNewaccountInternal will throw exceptions
-               // if wiki is read only (already handled by api), user is blocked or does not have rights.
-               // Use userCan in order to hit GlobalBlock checks (according to Special:userlogin)
-               $loginTitle = SpecialPage::getTitleFor( 'Userlogin' );
-               if ( !$loginTitle->userCan( 'createaccount', $this->getUser() ) ) {
-                       $this->dieUsage(
-                               'You do not have the right to create a new account',
-                               'permdenied-createaccount'
-                       );
-               }
-               if ( $this->getUser()->isBlockedFromCreateAccount() ) {
-                       $this->dieUsage(
-                               'You cannot create a new account because you are blocked',
-                               'blocked',
-                               0,
-                               [ 'blockinfo' => ApiQueryUserInfo::getBlockInfo( $this->getUser()->getBlock() ) ]
-                       );
-               }
-
-               $params = $this->extractRequestParams();
-
-               // Make sure session is persisted
-               MediaWiki\Session\SessionManager::getGlobalSession()->persist();
-
-               if ( $params['mailpassword'] && !$params['email'] ) {
-                       $this->dieUsageMsg( 'noemail' );
-               }
-
-               if ( $params['language'] && !Language::isSupportedLanguage( $params['language'] ) ) {
-                       $this->dieUsage( 'Invalid language parameter', 'langinvalid' );
-               }
-
-               $context = new DerivativeContext( $this->getContext() );
-               $context->setRequest( new DerivativeRequest(
-                       $this->getContext()->getRequest(),
-                       [
-                               'type' => 'signup',
-                               'uselang' => $params['language'],
-                               'wpName' => $params['name'],
-                               'wpPassword' => $params['password'],
-                               'wpRetype' => $params['password'],
-                               'wpDomain' => $params['domain'],
-                               'wpEmail' => $params['email'],
-                               'wpRealName' => $params['realname'],
-                               'wpCreateaccountToken' => $params['token'],
-                               'wpCreateaccount' => $params['mailpassword'] ? null : '1',
-                               'wpCreateaccountMail' => $params['mailpassword'] ? '1' : null
-                       ]
-               ) );
-
-               $loginForm = new LoginForm();
-               $loginForm->setContext( $context );
-               Hooks::run( 'AddNewAccountApiForm', [ $this, $loginForm ] );
-               $loginForm->load();
-
-               $status = $loginForm->addNewAccountInternal();
-               LoggerFactory::getInstance( 'authmanager' )->info( 'Account creation attempt via API', [
-                       'event' => 'accountcreation',
-                       'status' => $status,
-               ] );
-               $result = [];
-               if ( $status->isGood() ) {
-                       // Success!
-                       $user = $status->getValue();
-
-                       if ( $params['language'] ) {
-                               $user->setOption( 'language', $params['language'] );
-                       }
-
-                       if ( $params['mailpassword'] ) {
-                               // If mailpassword was set, disable the password and send an email.
-                               $user->setPassword( null );
-                               $status->merge( $loginForm->mailPasswordInternal(
-                                       $user,
-                                       false,
-                                       'createaccount-title',
-                                       'createaccount-text'
-                               ) );
-                       } elseif ( $this->getConfig()->get( 'EmailAuthentication' ) &&
-                               Sanitizer::validateEmail( $user->getEmail() )
-                       ) {
-                               // Send out an email authentication message if needed
-                               $status->merge( $user->sendConfirmationMail() );
-                       }
-
-                       // Save settings (including confirmation token)
-                       $user->saveSettings();
-
-                       Hooks::run( 'AddNewAccount', [ $user, $params['mailpassword'] ] );
-
-                       if ( $params['mailpassword'] ) {
-                               $logAction = 'byemail';
-                       } elseif ( $this->getUser()->isLoggedIn() ) {
-                               $logAction = 'create2';
-                       } else {
-                               $logAction = 'create';
-                       }
-                       $user->addNewUserLogEntry( $logAction, (string)$params['reason'] );
-
-                       // Add username, id, and token to result.
-                       $result['username'] = $user->getName();
-                       $result['userid'] = $user->getId();
-                       $result['token'] = $user->getToken();
-               }
-
-               $apiResult = $this->getResult();
-
-               if ( $status->hasMessage( 'sessionfailure' ) || $status->hasMessage( 'nocookiesfornew' ) ) {
-                       // 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()->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 );
-               } elseif ( !$status->isGood() ) {
-                       // Status is not good, but OK. This means warnings.
-                       $result['result'] = 'Warning';
-
-                       // Add any warnings to the result
-                       $warnings = $status->getErrorsByType( 'warning' );
-                       if ( $warnings ) {
-                               foreach ( $warnings as &$warning ) {
-                                       ApiResult::setIndexedTagName( $warning['params'], 'param' );
-                               }
-                               ApiResult::setIndexedTagName( $warnings, 'warning' );
-                               $result['warnings'] = $warnings;
-                       }
-               } else {
-                       // Everything was fine.
-                       $result['result'] = 'Success';
-               }
-
-               // Give extensions a chance to modify the API result data
-               Hooks::run( 'AddNewAccountApiResult', [ $this, $loginForm, &$result ] );
-
-               $apiResult->addValue( null, 'createaccount', $result );
-       }
-
-       public function mustBePosted() {
-               return true;
-       }
-
-       public function isReadMode() {
-               return false;
-       }
-
-       public function isWriteMode() {
-               return true;
-       }
-
-       public function getAllowedParams() {
-               return [
-                       'name' => [
-                               ApiBase::PARAM_TYPE => 'user',
-                               ApiBase::PARAM_REQUIRED => true
-                       ],
-                       'password' => [
-                               ApiBase::PARAM_TYPE => 'password',
-                       ],
-                       'domain' => null,
-                       'token' => [
-                               ApiBase::PARAM_TYPE => 'string',
-                               ApiBase::PARAM_REQUIRED => false, // for BC
-                               ApiBase::PARAM_HELP_MSG => [ 'api-help-param-token', 'createaccount' ],
-                       ],
-                       'email' => [
-                               ApiBase::PARAM_TYPE => 'string',
-                               ApiBase::PARAM_REQUIRED => $this->getConfig()->get( 'EmailConfirmToEdit' ),
-                       ],
-                       'realname' => null,
-                       'mailpassword' => [
-                               ApiBase::PARAM_TYPE => 'boolean',
-                               ApiBase::PARAM_DFLT => false
-                       ],
-                       'reason' => null,
-                       'language' => null
-               ];
-       }
-
-       protected function getExamplesMessages() {
-               return [
-                       'action=createaccount&name=testuser&password=test123'
-                               => 'apihelp-createaccount-example-pass',
-                       'action=createaccount&name=testmailuser&mailpassword=true&reason=MyReason'
-                               => 'apihelp-createaccount-example-mail',
-               ];
-       }
-
-       public function getHelpUrls() {
-               return 'https://www.mediawiki.org/wiki/API:Account_creation';
-       }
-}
index 0e4c6e0..b9f65b3 100644 (file)
@@ -42,9 +42,7 @@ class ApiLogin extends ApiBase {
        }
 
        protected function getDescriptionMessage() {
-               if ( $this->getConfig()->get( 'DisableAuthManager' ) ) {
-                       return 'apihelp-login-description-nonauthmanager';
-               } elseif ( $this->getConfig()->get( 'EnableBotPasswords' ) ) {
+               if ( $this->getConfig()->get( 'EnableBotPasswords' ) ) {
                        return 'apihelp-login-description';
                } else {
                        return 'apihelp-login-description-nobotpasswords';
@@ -124,85 +122,52 @@ class ApiLogin extends ApiBase {
                }
 
                if ( $authRes === false ) {
-                       if ( $this->getConfig()->get( 'DisableAuthManager' ) ) {
-                               // Non-AuthManager login
-                               $context->setRequest( new DerivativeRequest(
-                                       $this->getContext()->getRequest(),
-                                       [
-                                               'wpName' => $params['name'],
-                                               'wpPassword' => $params['password'],
-                                               'wpDomain' => $params['domain'],
-                                               'wpLoginToken' => $params['token'],
-                                               'wpRemember' => ''
-                                       ]
-                               ) );
-                               $loginForm = new LoginForm();
-                               $loginForm->setContext( $context );
-                               $authRes = $loginForm->authenticateUserData();
-                               $loginType = 'LoginForm';
-
-                               switch ( $authRes ) {
-                                       case LoginForm::SUCCESS:
-                                               $authRes = 'Success';
-                                               break;
-                                       case LoginForm::NEED_TOKEN:
-                                               $authRes = 'NeedToken';
-                                               break;
-                               }
-                       } else {
-                               // Simplified AuthManager login, for backwards compatibility
-                               $manager = AuthManager::singleton();
-                               $reqs = AuthenticationRequest::loadRequestsFromSubmission(
-                                       $manager->getAuthenticationRequests( AuthManager::ACTION_LOGIN, $this->getUser() ),
-                                       [
-                                               'username' => $params['name'],
-                                               'password' => $params['password'],
-                                               'domain' => $params['domain'],
-                                               'rememberMe' => true,
-                                       ]
-                               );
-                               $res = AuthManager::singleton()->beginAuthentication( $reqs, 'null:' );
-                               switch ( $res->status ) {
-                                       case AuthenticationResponse::PASS:
-                                               if ( $this->getConfig()->get( 'EnableBotPasswords' ) ) {
-                                                       $warn = 'Main-account login via action=login is deprecated and may stop working ' .
-                                                               'without warning.';
-                                                       $warn .= ' To continue login with action=login, see [[Special:BotPasswords]].';
-                                                       $warn .= ' To safely continue using main-account login, see action=clientlogin.';
-                                               } else {
-                                                       $warn = 'Login via action=login is deprecated and may stop working without warning.';
-                                                       $warn .= ' To safely log in, see action=clientlogin.';
-                                               }
-                                               $this->setWarning( $warn );
-                                               $authRes = 'Success';
-                                               $loginType = 'AuthManager';
-                                               break;
-
-                                       case AuthenticationResponse::FAIL:
-                                               // Hope it's not a PreAuthenticationProvider that failed...
-                                               $authRes = 'Failed';
-                                               $message = $res->message;
-                                               \MediaWiki\Logger\LoggerFactory::getInstance( 'authentication' )
-                                                       ->info( __METHOD__ . ': Authentication failed: ' . $message->plain() );
-                                               break;
-
-                                       default:
-                                               $authRes = 'Aborted';
-                                               break;
-                               }
+                       // Simplified AuthManager login, for backwards compatibility
+                       $manager = AuthManager::singleton();
+                       $reqs = AuthenticationRequest::loadRequestsFromSubmission(
+                               $manager->getAuthenticationRequests( AuthManager::ACTION_LOGIN, $this->getUser() ),
+                               [
+                                       'username' => $params['name'],
+                                       'password' => $params['password'],
+                                       'domain' => $params['domain'],
+                                       'rememberMe' => true,
+                               ]
+                       );
+                       $res = AuthManager::singleton()->beginAuthentication( $reqs, 'null:' );
+                       switch ( $res->status ) {
+                               case AuthenticationResponse::PASS:
+                                       if ( $this->getConfig()->get( 'EnableBotPasswords' ) ) {
+                                               $warn = 'Main-account login via action=login is deprecated and may stop working ' .
+                                                       'without warning.';
+                                               $warn .= ' To continue login with action=login, see [[Special:BotPasswords]].';
+                                               $warn .= ' To safely continue using main-account login, see action=clientlogin.';
+                                       } else {
+                                               $warn = 'Login via action=login is deprecated and may stop working without warning.';
+                                               $warn .= ' To safely log in, see action=clientlogin.';
+                                       }
+                                       $this->setWarning( $warn );
+                                       $authRes = 'Success';
+                                       $loginType = 'AuthManager';
+                                       break;
+
+                               case AuthenticationResponse::FAIL:
+                                       // Hope it's not a PreAuthenticationProvider that failed...
+                                       $authRes = 'Failed';
+                                       $message = $res->message;
+                                       \MediaWiki\Logger\LoggerFactory::getInstance( 'authentication' )
+                                               ->info( __METHOD__ . ': Authentication failed: ' . $message->plain() );
+                                       break;
+
+                               default:
+                                       $authRes = 'Aborted';
+                                       break;
                        }
                }
 
                $result['result'] = $authRes;
                switch ( $authRes ) {
                        case 'Success':
-                               if ( $this->getConfig()->get( 'DisableAuthManager' ) ) {
-                                       $user = $context->getUser();
-                                       $this->getContext()->setUser( $user );
-                                       $user->setCookies( $this->getRequest(), null, true );
-                               } else {
-                                       $user = $session->getUser();
-                               }
+                               $user = $session->getUser();
 
                                ApiQueryInfo::resetTokenCache();
 
@@ -252,65 +217,6 @@ class ApiLogin extends ApiBase {
                                }
                                break;
 
-                       // Results from LoginForm for when $wgDisableAuthManager is true
-                       case LoginForm::WRONG_TOKEN:
-                               $result['result'] = 'WrongToken';
-                               break;
-
-                       case LoginForm::NO_NAME:
-                               $result['result'] = 'NoName';
-                               break;
-
-                       case LoginForm::ILLEGAL:
-                               $result['result'] = 'Illegal';
-                               break;
-
-                       case LoginForm::WRONG_PLUGIN_PASS:
-                               $result['result'] = 'WrongPluginPass';
-                               break;
-
-                       case LoginForm::NOT_EXISTS:
-                               $result['result'] = 'NotExists';
-                               break;
-
-                       // bug 20223 - Treat a temporary password as wrong. Per SpecialUserLogin:
-                       // The e-mailed temporary password should not be used for actual logins.
-                       case LoginForm::RESET_PASS:
-                       case LoginForm::WRONG_PASS:
-                               $result['result'] = 'WrongPass';
-                               break;
-
-                       case LoginForm::EMPTY_PASS:
-                               $result['result'] = 'EmptyPass';
-                               break;
-
-                       case LoginForm::CREATE_BLOCKED:
-                               $result['result'] = 'CreateBlocked';
-                               $result['details'] = 'Your IP address is blocked from account creation';
-                               $block = $context->getUser()->getBlock();
-                               if ( $block ) {
-                                       $result = array_merge( $result, ApiQueryUserInfo::getBlockInfo( $block ) );
-                               }
-                               break;
-
-                       case LoginForm::THROTTLED:
-                               $result['result'] = 'Throttled';
-                               $result['wait'] = intval( $loginForm->mThrottleWait );
-                               break;
-
-                       case LoginForm::USER_BLOCKED:
-                               $result['result'] = 'Blocked';
-                               $block = User::newFromName( $params['name'] )->getBlock();
-                               if ( $block ) {
-                                       $result = array_merge( $result, ApiQueryUserInfo::getBlockInfo( $block ) );
-                               }
-                               break;
-
-                       case LoginForm::ABORTED:
-                               $result['result'] = 'Aborted';
-                               $result['reason'] = $loginForm->mAbortLoginErrorMsg;
-                               break;
-
                        default:
                                ApiBase::dieDebug( __METHOD__, "Unhandled case value: {$authRes}" );
                }
@@ -329,8 +235,7 @@ class ApiLogin extends ApiBase {
        }
 
        public function isDeprecated() {
-               return !$this->getConfig()->get( 'DisableAuthManager' ) &&
-                       !$this->getConfig()->get( 'EnableBotPasswords' );
+               return !$this->getConfig()->get( 'EnableBotPasswords' );
        }
 
        public function mustBePosted() {
index 5afb66f..cfc1e46 100644 (file)
@@ -261,7 +261,7 @@ class ApiQueryUsers extends ApiQueryBase {
                                        }
                                } else {
                                        $data[$u]['missing'] = true;
-                                       if ( isset( $this->prop['cancreate'] ) && !$this->getConfig()->get( 'DisableAuthManager' ) ) {
+                                       if ( isset( $this->prop['cancreate'] ) ) {
                                                $status = MediaWiki\Auth\AuthManager::singleton()->canCreateAccount( $u );
                                                $data[$u]['cancreate'] = $status->isGood();
                                                if ( !$status->isGood() ) {
@@ -307,7 +307,7 @@ class ApiQueryUsers extends ApiQueryBase {
        }
 
        public function getAllowedParams() {
-               $ret = [
+               return [
                        'prop' => [
                                ApiBase::PARAM_ISMULTI => true,
                                ApiBase::PARAM_TYPE => [
@@ -320,6 +320,7 @@ class ApiQueryUsers extends ApiQueryBase {
                                        'emailable',
                                        'gender',
                                        'centralids',
+                                       'cancreate',
                                        // When adding a prop, consider whether it should be added
                                        // to self::$publicProps
                                ],
@@ -336,10 +337,6 @@ class ApiQueryUsers extends ApiQueryBase {
                                ApiBase::PARAM_ISMULTI => true
                        ],
                ];
-               if ( !$this->getConfig()->get( 'DisableAuthManager' ) ) {
-                       $ret['prop'][ApiBase::PARAM_TYPE][] = 'cancreate';
-               }
-               return $ret;
        }
 
        protected function getExamplesMessages() {
index 446a98c..297c0fb 100644 (file)
@@ -39,6 +39,7 @@ class ApiStashEdit extends ApiBase {
        const ERROR_PARSE = 'error_parse';
        const ERROR_CACHE = 'error_cache';
        const ERROR_UNCACHEABLE = 'uncacheable';
+       const ERROR_BUSY = 'busy';
 
        const PRESUME_FRESH_TTL_SEC = 30;
        const MAX_CACHE_TTL = 300; // 5 minutes
@@ -51,6 +52,7 @@ class ApiStashEdit extends ApiBase {
                        $this->dieUsage( 'This interface is not supported for bots', 'botsnotsupported' );
                }
 
+               $cache = ObjectCache::getLocalClusterInstance();
                $page = $this->getTitleOrPageId( $params );
                $title = $page->getTitle();
 
@@ -60,8 +62,23 @@ class ApiStashEdit extends ApiBase {
                        $this->dieUsage( 'Unsupported content model/format', 'badmodelformat' );
                }
 
-               // Trim and fix newlines so the key SHA1's match (see RequestContext::getText())
-               $text = rtrim( str_replace( "\r\n", "\n", $params['text'] ) );
+               if ( strlen( $params['stashedtexthash'] ) ) {
+                       // Load from cache since the client indicates the text is the same as last stash
+                       $textHash = $params['stashedtexthash'];
+                       $textKey = $cache->makeKey( 'stashedit', 'text', $textHash );
+                       $text = $cache->get( $textKey );
+                       if ( !is_string( $text ) ) {
+                               $this->dieUsage( 'No stashed text found with the given hash', 'missingtext' );
+                       }
+               } elseif ( $params['text'] !== null ) {
+                       // Trim and fix newlines so the key SHA1's match (see WebRequest::getText())
+                       $text = rtrim( str_replace( "\r\n", "\n", $params['text'] ) );
+                       $textHash = sha1( $text );
+               } else {
+                       $this->dieUsage(
+                               'The text or stashedtexthash parameter must be given', 'missingtextparam' );
+               }
+
                $textContent = ContentHandler::makeContent(
                        $text, $title, $params['contentmodel'], $params['contentformat'] );
 
@@ -113,24 +130,24 @@ class ApiStashEdit extends ApiBase {
                // The user will abort the AJAX request by pressing "save", so ignore that
                ignore_user_abort( true );
 
-               // Use the master DB for fast blocking locks
-               $dbw = wfGetDB( DB_MASTER );
-
-               // Get a key based on the source text, format, and user preferences
-               $key = self::getStashKey( $title, $content, $user );
-               // De-duplicate requests on the same key
                if ( $user->pingLimiter( 'stashedit' ) ) {
                        $status = 'ratelimited';
-               } elseif ( $dbw->lock( $key, __METHOD__, 1 ) ) {
-                       $status = self::parseAndStash( $page, $content, $user, $params['summary'] );
-                       $dbw->unlock( $key, __METHOD__ );
                } else {
-                       $status = 'busy';
+                       $status = self::parseAndStash( $page, $content, $user, $params['summary'] );
+                       $textKey = $cache->makeKey( 'stashedit', 'text', $textHash );
+                       $cache->set( $textKey, $text, self::MAX_CACHE_TTL );
                }
 
                $this->getStats()->increment( "editstash.cache_stores.$status" );
 
-               $this->getResult()->addValue( null, $this->getModuleName(), [ 'status' => $status ] );
+               $this->getResult()->addValue(
+                       null,
+                       $this->getModuleName(),
+                       [
+                               'status' => $status,
+                               'texthash' => $textHash
+                       ]
+               );
        }
 
        /**
@@ -145,17 +162,41 @@ class ApiStashEdit extends ApiBase {
                $cache = ObjectCache::getLocalClusterInstance();
                $logger = LoggerFactory::getInstance( 'StashEdit' );
 
-               $format = $content->getDefaultFormat();
-               $editInfo = $page->prepareContentForEdit( $content, null, $user, $format, false );
                $title = $page->getTitle();
+               $key = self::getStashKey( $title, self::getContentHash( $content ), $user );
 
-               if ( $editInfo && $editInfo->output ) {
-                       $key = self::getStashKey( $title, $content, $user );
+               // Use the master DB for fast blocking locks
+               $dbw = wfGetDB( DB_MASTER );
+               if ( !$dbw->lock( $key, __METHOD__, 1 ) ) {
+                       // De-duplicate requests on the same key
+                       return self::ERROR_BUSY;
+               }
+               $unlocker = new ScopedCallback( function () use ( $dbw, $key ) {
+                       $dbw->unlock( $key, __METHOD__ );
+               } );
+
+               $cutoffTime = time() - self::PRESUME_FRESH_TTL_SEC;
+
+               // Reuse any freshly build matching edit stash cache
+               $editInfo = $cache->get( $key );
+               if ( $editInfo && wfTimestamp( TS_UNIX, $editInfo->timestamp ) >= $cutoffTime ) {
+                       $alreadyCached = true;
+               } else {
+                       $format = $content->getDefaultFormat();
+                       $editInfo = $page->prepareContentForEdit( $content, null, $user, $format, false );
+                       $alreadyCached = false;
+               }
 
+               if ( $editInfo && $editInfo->output ) {
                        // Let extensions add ParserOutput metadata or warm other caches
                        Hooks::run( 'ParserOutputStashForEdit',
                                [ $page, $content, $editInfo->output, $summary, $user ] );
 
+                       if ( $alreadyCached ) {
+                               $logger->debug( "Already cached parser output for key '$key' ('$title')." );
+                               return self::ERROR_NONE;
+                       }
+
                        list( $stashInfo, $ttl, $code ) = self::buildStashValue(
                                $editInfo->pstContent,
                                $editInfo->output,
@@ -207,7 +248,7 @@ class ApiStashEdit extends ApiBase {
                $logger = LoggerFactory::getInstance( 'StashEdit' );
                $stats = RequestContext::getMain()->getStats();
 
-               $key = self::getStashKey( $title, $content, $user );
+               $key = self::getStashKey( $title, self::getContentHash( $content ), $user );
                $editInfo = $cache->get( $key );
                if ( !is_object( $editInfo ) ) {
                        $start = microtime( true );
@@ -282,6 +323,20 @@ class ApiStashEdit extends ApiBase {
                return wfTimestampOrNull( TS_MW, $time );
        }
 
+       /**
+        * Get hash of the content, factoring in model/format
+        *
+        * @param Content $content
+        * @return string
+        */
+       private static function getContentHash( Content $content ) {
+               return sha1( implode( "\n", [
+                       $content->getModel(),
+                       $content->getDefaultFormat(),
+                       $content->serialize( $content->getDefaultFormat() )
+               ] ) );
+       }
+
        /**
         * Get the temporary prepared edit stash key for a user
         *
@@ -290,22 +345,19 @@ class ApiStashEdit extends ApiBase {
         *   - b) The parser output was made from the PST using cannonical matching options
         *
         * @param Title $title
-        * @param Content $content
+        * @param string $contentHash Result of getContentHash()
         * @param User $user User to get parser options from
         * @return string
         */
-       private static function getStashKey( Title $title, Content $content, User $user ) {
-               $hash = sha1( implode( ':', [
+       private static function getStashKey( Title $title, $contentHash, User $user ) {
+               return ObjectCache::getLocalClusterInstance()->makeKey(
+                       'prepared-edit',
+                       md5( $title->getPrefixedDBkey() ),
                        // Account for the edit model/text
-                       $content->getModel(),
-                       $content->getDefaultFormat(),
-                       sha1( $content->serialize( $content->getDefaultFormat() ) ),
+                       $contentHash,
                        // Account for user name related variables like signatures
-                       $user->getId(),
-                       md5( $user->getName() )
-               ] ) );
-
-               return wfMemcKey( 'prepared-edit', md5( $title->getPrefixedDBkey() ), $hash );
+                       md5( $user->getId() . "\n" . $user->getName() )
+               );
        }
 
        /**
@@ -313,7 +365,7 @@ class ApiStashEdit extends ApiBase {
         *
         * This makes a simple version of WikiPage::prepareContentForEdit() as stash info
         *
-        * @param Content $pstContent
+        * @param Content $pstContent Pre-Save transformed content
         * @param ParserOutput $parserOutput
         * @param string $timestamp TS_MW
         * @param User $user
@@ -355,7 +407,11 @@ class ApiStashEdit extends ApiBase {
                        ],
                        'text' => [
                                ApiBase::PARAM_TYPE => 'text',
-                               ApiBase::PARAM_REQUIRED => true
+                               ApiBase::PARAM_DFLT => null
+                       ],
+                       'stashedtexthash' => [
+                               ApiBase::PARAM_TYPE => 'string',
+                               ApiBase::PARAM_DFLT => null
                        ],
                        'summary' => [
                                ApiBase::PARAM_TYPE => 'string',
index 95659e5..89d9af8 100644 (file)
@@ -64,7 +64,8 @@ class ApiUpload extends ApiBase {
                                $this->dieUsage( 'No upload module set', 'nomodule' );
                        }
                } catch ( UploadStashException $e ) { // XXX: don't spam exception log
-                       $this->handleStashException( $e );
+                       list( $msg, $code ) = $this->handleStashException( get_class( $e ), $e->getMessage() );
+                       $this->dieUsage( $msg, $code );
                }
 
                // First check permission to upload
@@ -112,7 +113,8 @@ class ApiUpload extends ApiBase {
                                $result['imageinfo'] = $this->mUpload->getImageInfo( $this->getResult() );
                        }
                } catch ( UploadStashException $e ) { // XXX: don't spam exception log
-                       $this->handleStashException( $e );
+                       list( $msg, $code ) = $this->handleStashException( get_class( $e ), $e->getMessage() );
+                       $this->dieUsage( $msg, $code );
                }
 
                $this->getResult()->addValue( null, $this->getModuleName(), $result );
@@ -156,20 +158,13 @@ class ApiUpload extends ApiBase {
         */
        private function getStashResult( $warnings ) {
                $result = [];
+               $result['result'] = 'Success';
+               if ( $warnings && count( $warnings ) > 0 ) {
+                       $result['warnings'] = $warnings;
+               }
                // Some uploads can request they be stashed, so as not to publish them immediately.
                // In this case, a failure to stash ought to be fatal
-               try {
-                       $result['result'] = 'Success';
-                       $result['filekey'] = $this->performStash();
-                       $result['sessionkey'] = $result['filekey']; // backwards compatibility
-                       if ( $warnings && count( $warnings ) > 0 ) {
-                               $result['warnings'] = $warnings;
-                       }
-               } catch ( UploadStashException $e ) {
-                       $this->handleStashException( $e );
-               } catch ( Exception $e ) {
-                       $this->dieUsage( $e->getMessage(), 'stashfailed' );
-               }
+               $this->performStash( 'critical', $result );
 
                return $result;
        }
@@ -185,12 +180,7 @@ class ApiUpload extends ApiBase {
                $result['warnings'] = $warnings;
                // in case the warnings can be fixed with some further user action, let's stash this upload
                // and return a key they can use to restart it
-               try {
-                       $result['filekey'] = $this->performStash();
-                       $result['sessionkey'] = $result['filekey']; // backwards compatibility
-               } catch ( Exception $e ) {
-                       $result['warnings']['stashfailed'] = $e->getMessage();
-               }
+               $this->performStash( 'optional', $result );
 
                return $result;
        }
@@ -228,14 +218,7 @@ class ApiUpload extends ApiBase {
                }
 
                if ( $this->mParams['offset'] == 0 ) {
-                       try {
-                               $filekey = $this->performStash();
-                       } catch ( UploadStashException $e ) {
-                               $this->handleStashException( $e );
-                       } catch ( Exception $e ) {
-                               // FIXME: Error handling here is wrong/different from rest of this
-                               $this->dieUsage( $e->getMessage(), 'stashfailed' );
-                       }
+                       $filekey = $this->performStash( 'critical' );
                } else {
                        $filekey = $this->mParams['filekey'];
 
@@ -320,27 +303,57 @@ class ApiUpload extends ApiBase {
        }
 
        /**
-        * Stash the file and return the file key
-        * Also re-raises exceptions with slightly more informative message strings (useful for API)
-        * @throws MWException
-        * @return string File key
+        * Stash the file and add the file key, or error information if it fails, to the data.
+        *
+        * @param string $failureMode What to do on failure to stash:
+        *   - When 'critical', use dieStatus() to produce an error response and throw an exception.
+        *     Use this when stashing the file was the primary purpose of the API request.
+        *   - When 'optional', only add a 'stashfailed' key to the data and return null.
+        *     Use this when some error happened for a non-stash upload and we're stashing the file
+        *     only to save the client the trouble of re-uploading it.
+        * @param array &$data API result to which to add the information
+        * @return string|null File key
         */
-       private function performStash() {
+       private function performStash( $failureMode, &$data = null ) {
                try {
-                       $stashFile = $this->mUpload->stashFile( $this->getUser() );
+                       $status = $this->mUpload->tryStashFile( $this->getUser() );
 
-                       if ( !$stashFile ) {
-                               throw new MWException( 'Invalid stashed file' );
+                       if ( $status->isGood() && !$status->getValue() ) {
+                               // Not actually a 'good' status...
+                               $status->fatal( new ApiRawMessage( 'Invalid stashed file', 'stashfailed' ) );
                        }
-                       $fileKey = $stashFile->getFileKey();
                } catch ( Exception $e ) {
-                       $message = 'Stashing temporary file failed: ' . get_class( $e ) . ' ' . $e->getMessage();
-                       wfDebug( __METHOD__ . ' ' . $message . "\n" );
-                       $className = get_class( $e );
-                       throw new $className( $message );
+                       $debugMessage = 'Stashing temporary file failed: ' . get_class( $e ) . ' ' . $e->getMessage();
+                       wfDebug( __METHOD__ . ' ' . $debugMessage . "\n" );
+                       $status = Status::newFatal( new ApiRawMessage( $e->getMessage(), 'stashfailed' ) );
+               }
+
+               if ( $status->isGood() ) {
+                       $stashFile = $status->getValue();
+                       $data['filekey'] = $stashFile->getFileKey();
+                       // Backwards compatibility
+                       $data['sessionkey'] = $data['filekey'];
+                       return $data['filekey'];
+               }
+
+               if ( $status->getMessage()->getKey() === 'uploadstash-exception' ) {
+                       // The exceptions thrown by upload stash code and pretty silly and UploadBase returns poor
+                       // Statuses for it. Just extract the exception details and parse them ourselves.
+                       list( $exceptionType, $message ) = $status->getMessage()->getParams();
+                       $debugMessage = 'Stashing temporary file failed: ' . $exceptionType . ' ' . $message;
+                       wfDebug( __METHOD__ . ' ' . $debugMessage . "\n" );
+                       list( $msg, $code ) = $this->handleStashException( $exceptionType, $message );
+                       $status = Status::newFatal( new ApiRawMessage( $msg, $code ) );
                }
 
-               return $fileKey;
+               // Bad status
+               if ( $failureMode !== 'optional' ) {
+                       $this->dieStatus( $status );
+               } else {
+                       list( $code, $msg ) = $this->getErrorFromStatus( $status );
+                       $data['stashfailed'] = $msg;
+                       return null;
+               }
        }
 
        /**
@@ -354,12 +367,7 @@ class ApiUpload extends ApiBase {
         * @throws UsageException
         */
        private function dieRecoverableError( $error, $parameter, $data = [], $code = 'unknownerror' ) {
-               try {
-                       $data['filekey'] = $this->performStash();
-                       $data['sessionkey'] = $data['filekey'];
-               } catch ( Exception $e ) {
-                       $data['stashfailed'] = $e->getMessage();
-               }
+               $this->performStash( 'optional', $data );
                $data['invalidparameter'] = $parameter;
 
                $parsed = $this->parseMsg( $error );
@@ -653,49 +661,41 @@ class ApiUpload extends ApiBase {
 
        /**
         * Handles a stash exception, giving a useful error to the user.
-        * @param Exception $e The exception we encountered.
+        * @param string $exceptionType Class name of the exception we encountered.
+        * @param string $message Message of the exception we encountered.
+        * @return array Array of message and code, suitable for passing to dieUsage()
         */
-       protected function handleStashException( $e ) {
-               $exceptionType = get_class( $e );
-
+       protected function handleStashException( $exceptionType, $message ) {
                switch ( $exceptionType ) {
                        case 'UploadStashFileNotFoundException':
-                               $this->dieUsage(
-                                       'Could not find the file in the stash: ' . $e->getMessage(),
+                               return [
+                                       'Could not find the file in the stash: ' . $message,
                                        'stashedfilenotfound'
-                               );
-                               break;
+                               ];
                        case 'UploadStashBadPathException':
-                               $this->dieUsage(
-                                       'File key of improper format or otherwise invalid: ' . $e->getMessage(),
+                               return [
+                                       'File key of improper format or otherwise invalid: ' . $message,
                                        'stashpathinvalid'
-                               );
-                               break;
+                               ];
                        case 'UploadStashFileException':
-                               $this->dieUsage(
-                                       'Could not store upload in the stash: ' . $e->getMessage(),
+                               return [
+                                       'Could not store upload in the stash: ' . $message,
                                        'stashfilestorage'
-                               );
-                               break;
+                               ];
                        case 'UploadStashZeroLengthFileException':
-                               $this->dieUsage(
+                               return [
                                        'File is of zero length, and could not be stored in the stash: ' .
-                                               $e->getMessage(),
+                                               $message,
                                        'stashzerolength'
-                               );
-                               break;
+                               ];
                        case 'UploadStashNotLoggedInException':
-                               $this->dieUsage( 'Not logged in: ' . $e->getMessage(), 'stashnotloggedin' );
-                               break;
+                               return [ 'Not logged in: ' . $message, 'stashnotloggedin' ];
                        case 'UploadStashWrongOwnerException':
-                               $this->dieUsage( 'Wrong owner: ' . $e->getMessage(), 'stashwrongowner' );
-                               break;
+                               return [ 'Wrong owner: ' . $message, 'stashwrongowner' ];
                        case 'UploadStashNoSuchKeyException':
-                               $this->dieUsage( 'No such filekey: ' . $e->getMessage(), 'stashnosuchfilekey' );
-                               break;
+                               return [ 'No such filekey: ' . $message, 'stashnosuchfilekey' ];
                        default:
-                               $this->dieUsage( $exceptionType . ': ' . $e->getMessage(), 'stasherror' );
-                               break;
+                               return [ $exceptionType . ': ' . $message, 'stasherror' ];
                }
        }
 
index 8bbef02..6afeb47 100644 (file)
        "apihelp-query+watchlist-paramvalue-prop-userid": "Ergänzt die Kennung des Benutzers, der die Bearbeitung ausgeführt hat.",
        "apihelp-query+watchlist-paramvalue-prop-comment": "Ergänzt den Kommentar der Bearbeitung.",
        "apihelp-query+watchlist-paramvalue-prop-timestamp": "Ergänzt den Zeitstempel der Bearbeitung.",
+       "apihelp-query+watchlist-paramvalue-prop-patrol": "Markiert Bearbeitungen, die kontrolliert sind.",
        "apihelp-query+watchlist-paramvalue-prop-sizes": "Ergänzt die alten und neuen Längen der Seite.",
        "apihelp-query+watchlist-paramvalue-type-new": "Seitenerstellungen.",
        "apihelp-query+watchlist-paramvalue-type-log": "Logbucheinträge.",
        "apihelp-query+watchlistraw-param-prop": "Zusätzlich zurückzugebende Eigenschaften:",
+       "apihelp-resetpassword-param-user": "Benutzer, der zurückgesetzt werden soll.",
        "apihelp-rsd-description": "Ein RSD-Schema (Really Simple Discovery) exportieren.",
        "apihelp-rsd-example-simple": "Das RSD-Schema exportieren",
        "apihelp-setnotificationtimestamp-param-entirewatchlist": "An allen beobachteten Seiten arbeiten.",
+       "apihelp-stashedit-param-sectiontitle": "Der Titel für einen neuen Abschnitt.",
        "apihelp-stashedit-param-text": "Seiteninhalt.",
+       "apihelp-stashedit-param-summary": "Änderungszusammenfassung.",
        "apihelp-tag-param-reason": "Grund für die Änderung.",
+       "apihelp-tokens-param-type": "Abzufragende Tokentypen.",
+       "apihelp-tokens-example-edit": "Ruft einen Bearbeitungstoken ab (Standard).",
+       "apihelp-tokens-example-emailmove": "Ruft einen E-Mail- und Verschiebungstoken ab.",
        "apihelp-unblock-description": "Einen Benutzer freigeben.",
        "apihelp-unblock-param-id": "ID der Sperre zum Entsperren (über <kbd>list=blocks</kbd> erhalten). Darf nicht zusammen mit <var>$1user</var> verwendet werden.",
+       "apihelp-unblock-param-user": "Freizugebender Benutzername, IP-Adressbereich oder freizugebende IP-Adresse. Kann nicht zusammen mit <var>$1id</var> verwendet werden.",
        "apihelp-unblock-param-reason": "Grund für die Freigabe.",
        "apihelp-unblock-param-tags": "Auf den Benutzersperr-Logbuch-Eintrag anzuwendende Änderungsmarkierungen.",
        "apihelp-unblock-example-id": "Sperrkennung #<kbd>105</kbd> freigeben.",
        "api-help-permissions-granted-to": "{{PLURAL:$1|Gewährt an}}: $2",
        "api-help-right-apihighlimits": "Höhere Beschränkungen in API-Anfragen verwenden (langsame Anfragen: $1; schnelle Anfragen: $2). Die Beschränkungen für langsame Anfragen werden auch auf Mehrwertparameter angewandt.",
        "api-help-open-in-apisandbox": "<small>[in Spielwiese öffnen]</small>",
+       "api-help-authmanagerhelper-messageformat": "Zu verwendendes Format zur Rückgabe von Nachrichten.",
        "api-credits-header": "Danksagungen",
        "api-credits": "API-Entwickler:\n* Roan Kattouw (Hauptentwickler von September 2007 bis 2009)\n* Victor Vasiliev\n* Bryan Tong Minh\n* Sam Reed\n* Yuri Astrakhan (Autor, Hauptentwickler von September 2006 bis September 2007)\n* Brad Jorsch (Hauptentwickler seit 2013)\n\nBitte sende deine Kommentare, Vorschläge und Fragen an mediawiki-api@lists.wikimedia.org\noder reiche einen Fehlerbericht auf https://phabricator.wikimedia.org/ ein."
 }
index 7f30ef8..1815836 100644 (file)
 
        "apihelp-login-description": "Log in and get authentication cookies.\n\nThis action should only be used in combination with [[Special:BotPasswords]]; use for main-account login is deprecated and may fail without warning. To safely log in to the main account, use <kbd>[[Special:ApiHelp/clientlogin|action=clientlogin]]</kbd>.",
        "apihelp-login-description-nobotpasswords": "Log in and get authentication cookies.\n\nThis action is deprecated and may fail without warning. To safely log in, use <kbd>[[Special:ApiHelp/clientlogin|action=clientlogin]]</kbd>.",
-       "apihelp-login-description-nonauthmanager": "Log in and get authentication cookies.\n\nIn the event of a successful log-in, the needed cookies will be included in the HTTP response headers. In the event of a failed log-in, further attempts may be throttled to limit automated password guessing attacks.",
        "apihelp-login-param-name": "User name.",
        "apihelp-login-param-password": "Password.",
        "apihelp-login-param-domain": "Domain (optional).",
        "apihelp-stashedit-param-section": "Section number. <kbd>0</kbd> for the top section, <kbd>new</kbd> for a new section.",
        "apihelp-stashedit-param-sectiontitle": "The title for a new section.",
        "apihelp-stashedit-param-text": "Page content.",
+       "apihelp-stashedit-param-stashedtexthash": "Page content hash from a prior stash to use instead.",
        "apihelp-stashedit-param-contentmodel": "Content model of the new content.",
        "apihelp-stashedit-param-contentformat": "Content serialization format used for the input text.",
        "apihelp-stashedit-param-baserevid": "Revision ID of the base revision.",
index c5aef1d..0e218b8 100644 (file)
        "apihelp-import-example-import": "Importar [[meta:Help:ParserFunctions]] ó espazo de nomes 100 con todo o historial.",
        "apihelp-linkaccount-description": "Vincular unha conta dun provedor externo ó usuario actual.",
        "apihelp-linkaccount-example-link": "Comezar o proceso de vincular a unha conta de <kbd>Exemplo</kbd>.",
-       "apihelp-login-description": "No caso dunha conexión correcta, as cookies necesarias incluiranse nas cabeceiras HTTP de resposta. No caso dunha conexión fallida, os intentos posteriores poden ser reducidos para limitar ataques automaticos de roubo de contrasinais.",
+       "apihelp-login-description": "Iniciar sesión e obter as cookies de autenticación.\n\nEsta acción só debe utilizarse en combinación con [[Special:BotPasswords]]; para a cuenta de inicio de sesión non se utiliza e pode fallar sen previo aviso. Para iniciar a sesión de forma segura na conta principal, utilice <kbd>[[Special:ApiHelp/clientlogin|action=clientlogin]]</kbd>.",
        "apihelp-login-description-nobotpasswords": "Conectarse e obter as cookies de autenticación. \n\nEsta acción está obsoleta e pode fallar sen avisar. Para conectarse sen problema use <kbd>[[Special:ApiHelp/clientlogin|action=clientlogin]]</kbd>.",
-       "apihelp-login-description-nonauthmanager": "Conectarse e obter as cookies de autenticación. \n\nNo caso dunha conexión correcta, as cookies necesarias incluiranse nas cabeceiras HTTP de resposta. No caso dunha conexión fallida, os intentos posteriores poden ser reducidos para limitar ataques automaticos de roubo de contrasinais.",
        "apihelp-login-param-name": "Nome de usuario.",
        "apihelp-login-param-password": "Contrasinal",
        "apihelp-login-param-domain": "Dominio (opcional).",
index 6c47aa4..650acb9 100644 (file)
        "apihelp-linkaccount-example-link": "{{doc-apihelp-example|linkaccount}}",
        "apihelp-login-description": "{{doc-apihelp-description|login|info=This message is used when <code>$wgEnableBotPasswords</code> is true.|seealso=* {{msg-mw|apihelp-login-description-nobotpasswords}}}}",
        "apihelp-login-description-nobotpasswords": "{{doc-apihelp-description|login|info=This message is used when <code>$wgEnableBotPasswords</code> is false.|seealso=* {{msg-mw|apihelp-login-description}}}}",
-       "apihelp-login-description-nonauthmanager": "{{doc-apihelp-description|login|info=This message is used when <code>$wgDisableAuthManager</code> is true.|seealso=* {{msg-mw|apihelp-login-description}}}}",
        "apihelp-login-param-name": "{{doc-apihelp-param|login|name}}\n{{Identical|Username}}",
        "apihelp-login-param-password": "{{doc-apihelp-param|login|password}}\n{{Identical|Password}}",
        "apihelp-login-param-domain": "{{doc-apihelp-param|login|domain}}",
        "apihelp-stashedit-param-section": "{{doc-apihelp-param|stashedit|section}}",
        "apihelp-stashedit-param-sectiontitle": "{{doc-apihelp-param|stashedit|sectiontitle}}",
        "apihelp-stashedit-param-text": "{{doc-apihelp-param|stashedit|text}}",
+       "apihelp-stashedit-param-stashedtexthash": "{{doc-apihelp-param|stashedit|stashedtexthash}}",
        "apihelp-stashedit-param-contentmodel": "{{doc-apihelp-param|stashedit|contentmodel}}",
        "apihelp-stashedit-param-contentformat": "{{doc-apihelp-param|stashedit|contentformat}}",
        "apihelp-stashedit-param-baserevid": "{{doc-apihelp-param|stashedit|baserevid}}",
index 9e5d754..c8b8e0b 100644 (file)
        "apihelp-linkaccount-example-link": "Почати процес пов'язування з обліковм записом з <kbd>Example</kbd>.",
        "apihelp-login-description": "Увійти в систему й отримати куки автентифікації.\n\nЦю дію треба використовувати лише в комбінації з [[Special:BotPasswords]]; використання для входу в основний обліковий запис застаріле і може ламатися без попередження. Щоб безпечно увійти в основний обліковий запис, використовуйте <kbd>[[Special:ApiHelp/clientlogin|action=clientlogin]]</kbd>.",
        "apihelp-login-description-nobotpasswords": "Увійти й отримати куки автентифікації.\n\nЦя дія застаріла і може ламатися без попередження. Щоб безпечно входити в систему, використовуйте <kbd>[[Special:ApiHelp/clientlogin|action=clientlogin]]</kbd>.",
-       "apihelp-login-description-nonauthmanager": "Увійти й отримати куки автентифікації.\n\nУ випадку успішного входження в систему будуть включені в заголовки відповіді HTTP. У випадку невдалого входження подальші спроби можуть бути урізані, щоб обмежити атаки автоматичного вгадування пароля.",
        "apihelp-login-param-name": "Ім'я користувача.",
        "apihelp-login-param-password": "Пароль.",
        "apihelp-login-param-domain": "Домен (необов'язково).",
index 5c85832..a5c59ac 100644 (file)
        "apihelp-linkaccount-example-link": "开始从<kbd>Example</kbd>链接至账户的过程。",
        "apihelp-login-description": "登录并获取身份验证Cookie。\n\n此操作只应与[[Special:BotPasswords]]一起使用;用于主账户登录的方式已弃用,并可能在没有警告的情况下失败。要安全登录主账户,请使用<kbd>[[Special:ApiHelp/clientlogin|action=clientlogin]]</kbd>。",
        "apihelp-login-description-nobotpasswords": "登录并获取身份验证Cookie。\n\n此操作已弃用,并可能在没有警告的情况下失败。要安全登录,请使用<kbd>[[Special:ApiHelp/clientlogin|action=clientlogin]]</kbd>。",
-       "apihelp-login-description-nonauthmanager": "登录并获取身份验证Cookie。\n\n在成功登录的情况下,所需的Cookie将包含在HTTP响应头中。在登录失败的情况下,进一步的尝试可能会被自动密码猜解攻击的限制所遏制。",
        "apihelp-login-param-name": "用户名。",
        "apihelp-login-param-password": "密码。",
        "apihelp-login-param-domain": "域名(可选)。",
index 82eeff0..eab5068 100644 (file)
@@ -105,12 +105,6 @@ class AuthManager implements LoggerAwareInterface {
         * @return AuthManager
         */
        public static function singleton() {
-               global $wgDisableAuthManager;
-
-               if ( $wgDisableAuthManager ) {
-                       throw new \BadMethodCallException( '$wgDisableAuthManager is set' );
-               }
-
                if ( self::$instance === null ) {
                        self::$instance = new self(
                                \RequestContext::getMain()->getRequest(),
index 3690735..c24962b 100644 (file)
  *   - READ_EXCLUSIVE : Up-to-date read as of now, that locks (exclusive) the records
  * All record locks persist for the duration of the transaction.
  *
+ * A special constant READ_LATEST_IMMUTABLE can be used for fetching append-only data. Such
+ * data is either (a) on a slave and up-to-date or (b) not yet there, but on the master/quorum.
+ * Because the data is append-only, it can never be stale on a slave if present.
+ *
  * Callers should use READ_NORMAL (or pass in no flags) unless the read determines a write.
  * In theory, such cases may require READ_LOCKING, though to avoid contention, READ_LATEST is
  * often good enough. If UPDATE race condition checks are required on a row and expensive code
  * must run after the row is fetched to determine the UPDATE, it may help to do something like:
- *   - a) Read the current row
- *   - b) Determine the new row (expensive, so we don't want to hold locks now)
- *   - c) Re-read the current row with READ_LOCKING; if it changed then bail out
- *   - d) otherwise, do the updates
+ *   - a) Start transaction
+ *   - b) Read the current row with READ_LATEST
+ *   - c) Determine the new row (expensive, so we don't want to hold locks now)
+ *   - d) Re-read the current row with READ_LOCKING; if it changed then bail out
+ *   - e) otherwise, do the updates
+ *   - f) Commit transaction
  *
  * @since 1.20
  */
 interface IDBAccessObject {
-       // Constants for object loading bitfield flags (higher => higher QoS)
-       const READ_LATEST = 1; // read from the master
+       /** Constants for object loading bitfield flags (higher => higher QoS) */
+       /** @var integer Read from a slave/non-quorum */
+       const READ_NORMAL = 0;
+       /** @var integer Read from the master/quorum */
+       const READ_LATEST = 1;
+       /* @var integer Read from the master/quorum and lock out other writers */
        const READ_LOCKING = 3; // READ_LATEST (1) and "LOCK IN SHARE MODE" (2)
+       /** @var integer Read from the master/quorum and lock out other writers and locking readers */
        const READ_EXCLUSIVE = 7; // READ_LOCKING (3) and "FOR UPDATE" (4)
 
-       // Convenience constant for callers to explicitly request slave data
-       const READ_NORMAL = 0; // read from the slave
+       /** @var integer Read from a slave/non-quorum immutable data, using the master/quorum on miss */
+       const READ_LATEST_IMMUTABLE = 8;
 
        // Convenience constant for tracking how data was loaded (higher => higher QoS)
        const READ_NONE = -1; // not loaded yet (or the object was cleared)
index 3dc6e92..4e358d4 100644 (file)
@@ -783,6 +783,7 @@ abstract class DatabaseBase implements IDatabase {
        public function query( $sql, $fname = __METHOD__, $tempIgnore = false ) {
                global $wgUser;
 
+               $priorWritesPending = $this->writesOrCallbacksPending();
                $this->mLastQuery = $sql;
 
                $isWriteQuery = $this->isWriteQuery( $sql );
@@ -810,7 +811,10 @@ abstract class DatabaseBase implements IDatabase {
                // Or, for one-word queries (like "BEGIN" or COMMIT") add it to the end (bug 42598)
                $commentedSql = preg_replace( '/\s|$/', " /* $fname $userName */ ", $sql, 1 );
 
-               if ( !$this->mTrxLevel && $this->getFlag( DBO_TRX ) && $this->isTransactableQuery( $sql ) ) {
+               # Start implicit transactions that wrap the request if DBO_TRX is enabled
+               if ( !$this->mTrxLevel && $this->getFlag( DBO_TRX )
+                       && $this->isTransactableQuery( $sql )
+               ) {
                        $this->begin( __METHOD__ . " ($fname)" );
                        $this->mTrxAutomatic = true;
                }
@@ -862,31 +866,23 @@ abstract class DatabaseBase implements IDatabase {
 
                # Try reconnecting if the connection was lost
                if ( false === $ret && $this->wasErrorReissuable() ) {
-                       # Transaction is gone; this can mean lost writes or REPEATABLE-READ snapshots
-                       $hadTrx = $this->mTrxLevel;
-                       # T127428: for non-write transactions, a disconnect and a COMMIT are similar:
-                       # neither changed data and in both cases any read snapshots are reset anyway.
-                       $isNoopCommit = ( !$this->writesOrCallbacksPending() && $sql === 'COMMIT' );
-                       # Update state tracking to reflect transaction loss
-                       $this->mTrxLevel = 0;
-                       $this->mTrxIdleCallbacks = []; // bug 65263
-                       $this->mTrxPreCommitCallbacks = []; // bug 65263
-                       wfDebug( "Connection lost, reconnecting...\n" );
-                       # Stash the last error values since ping() might clear them
+                       $recoverable = $this->canRecoverFromDisconnect( $sql, $priorWritesPending );
+                       # Stash the last error values before anything might clear them
                        $lastError = $this->lastError();
                        $lastErrno = $this->lastErrno();
-                       if ( $this->ping() ) {
+                       # Update state tracking to reflect transaction loss due to disconnection
+                       $this->handleTransactionLoss();
+                       wfDebug( "Connection lost, reconnecting...\n" );
+                       if ( $this->reconnect() ) {
                                wfDebug( "Reconnected\n" );
-                               $server = $this->getServer();
-                               $msg = __METHOD__ . ": lost connection to $server; reconnected";
+                               $msg = __METHOD__ . ": lost connection to {$this->getServer()}; reconnected";
                                wfDebugLog( 'DBPerformance', "$msg:\n" . wfBacktrace( true ) );
 
-                               if ( ( $hadTrx && !$isNoopCommit ) || $this->mNamedLocksHeld ) {
-                                       # Leave $ret as false and let an error be reported.
-                                       # Callers may catch the exception and continue to use the DB.
-                                       $this->reportQueryError( $lastError, $lastErrno, $sql, $fname, $tempIgnore );
+                               if ( !$recoverable ) {
+                                       # Callers may catch the exception and continue to use the DB
+                                       $this->reportQueryError( $lastError, $lastErrno, $sql, $fname );
                                } else {
-                                       # Should be safe to silently retry (no trx/callbacks/locks)
+                                       # Should be safe to silently retry the query
                                        $startTime = microtime( true );
                                        $ret = $this->doQuery( $commentedSql );
                                        $queryRuntime = microtime( true ) - $startTime;
@@ -900,6 +896,17 @@ abstract class DatabaseBase implements IDatabase {
                }
 
                if ( false === $ret ) {
+                       # Deadlocks cause the entire transaction to abort, not just the statement.
+                       # http://dev.mysql.com/doc/refman/5.7/en/innodb-error-handling.html
+                       # https://www.postgresql.org/docs/9.1/static/explicit-locking.html
+                       if ( $this->wasDeadlock() ) {
+                               if ( $this->explicitTrxActive() || $priorWritesPending ) {
+                                       $tempIgnore = false; // not recoverable
+                               }
+                               # Update state tracking to reflect transaction loss
+                               $this->handleTransactionLoss();
+                       }
+
                        $this->reportQueryError(
                                $this->lastError(), $this->lastErrno(), $sql, $fname, $tempIgnore );
                }
@@ -918,6 +925,40 @@ abstract class DatabaseBase implements IDatabase {
                return $res;
        }
 
+       private function canRecoverFromDisconnect( $sql, $priorWritesPending ) {
+               # Transaction dropped; this can mean lost writes, or REPEATABLE-READ snapshots.
+               # Dropped connections also mean that named locks are automatically released.
+               # Only allow error suppression in autocommit mode or when the lost transaction
+               # didn't matter anyway (aside from DBO_TRX snapshot loss).
+               if ( $this->mNamedLocksHeld ) {
+                       return false; // possible critical section violation
+               } elseif ( $sql === 'COMMIT' ) {
+                       return !$priorWritesPending; // nothing written anyway? (T127428)
+               } elseif ( $sql === 'ROLLBACK' ) {
+                       return true; // transaction lost...which is also what was requested :)
+               } elseif ( $this->explicitTrxActive() ) {
+                       return false; // don't drop atomocity
+               } elseif ( $priorWritesPending ) {
+                       return false; // prior writes lost from implicit transaction
+               }
+
+               return true;
+       }
+
+       private function handleTransactionLoss() {
+               $this->mTrxLevel = 0;
+               $this->mTrxIdleCallbacks = []; // bug 65263
+               $this->mTrxPreCommitCallbacks = []; // bug 65263
+               try {
+                       // Handle callbacks in mTrxEndCallbacks
+                       $this->runOnTransactionIdleCallbacks( self::TRIGGER_ROLLBACK );
+                       return null;
+               } catch ( Exception $e ) {
+                       // Already logged; move on...
+                       return $e;
+               }
+       }
+
        public function reportQueryError( $error, $errno, $sql, $fname, $tempIgnore = false ) {
                if ( $this->ignoreErrors() || $tempIgnore ) {
                        wfDebug( "SQL ERROR (ignored): $error\n" );
@@ -2509,6 +2550,7 @@ abstract class DatabaseBase implements IDatabase {
         *
         * @param integer $trigger IDatabase::TRIGGER_* constant
         * @since 1.20
+        * @throws Exception
         */
        public function runOnTransactionIdleCallbacks( $trigger ) {
                if ( $this->suppressPostCommitCallbacks ) {
@@ -2516,7 +2558,7 @@ abstract class DatabaseBase implements IDatabase {
                }
 
                $autoTrx = $this->getFlag( DBO_TRX ); // automatic begin() enabled?
-
+               /** @var Exception $e */
                $e = $ePrior = null; // last exception
                do { // callbacks may add callbacks :)
                        $callbacks = array_merge(
@@ -2642,13 +2684,13 @@ abstract class DatabaseBase implements IDatabase {
                                        "$fname: Transaction already in progress (from {$this->mTrxFname}), " .
                                                " performing implicit commit!"
                                );
-                       } else {
+                       } elseif ( $this->mTrxDoneWrites ) {
                                // The transaction was automatic and has done write operations
-                               if ( $this->mTrxDoneWrites ) {
-                                       wfLogDBError( "$fname: Automatic transaction with writes in progress" .
+                               throw new DBUnexpectedError(
+                                       $this,
+                                       "$fname: Automatic transaction with writes in progress" .
                                                " (from {$this->mTrxFname}), performing implicit commit!\n"
-                                       );
-                               }
+                               );
                        }
 
                        $this->runOnTransactionPreCommitCallbacks();
@@ -2718,7 +2760,10 @@ abstract class DatabaseBase implements IDatabase {
                                wfWarn( "$fname: No transaction to commit, something got out of sync!" );
                                return; // nothing to do
                        } elseif ( $this->mTrxAutomatic ) {
-                               wfWarn( "$fname: Explicit commit of implicit transaction. Something may be out of sync!" );
+                               throw new DBUnexpectedError(
+                                       $this,
+                                       "$fname: Explicit commit of implicit transaction."
+                               );
                        }
                }
 
@@ -2785,11 +2830,20 @@ abstract class DatabaseBase implements IDatabase {
         */
        protected function doRollback( $fname ) {
                if ( $this->mTrxLevel ) {
-                       $this->query( 'ROLLBACK', $fname, true );
+                       # Disconnects cause rollback anyway, so ignore those errors
+                       $ignoreErrors = true;
+                       $this->query( 'ROLLBACK', $fname, $ignoreErrors );
                        $this->mTrxLevel = 0;
                }
        }
 
+       /**
+        * @return bool
+        */
+       protected function explicitTrxActive() {
+               return $this->mTrxLevel && ( $this->mTrxAtomicLevels || !$this->mTrxAutomatic );
+       }
+
        /**
         * Creates a new table with structure copied from existing table
         * Note that unlike most database abstraction functions, this function does not
@@ -2891,6 +2945,19 @@ abstract class DatabaseBase implements IDatabase {
        }
 
        public function ping() {
+               try {
+                       // This will reconnect if possible, or error out if not
+                       $this->query( "SELECT 1 AS ping", __METHOD__ );
+                       return true;
+               } catch ( DBError $e ) {
+                       return false;
+               }
+       }
+
+       /**
+        * @return bool
+        */
+       protected function reconnect() {
                # Stub. Not essential to override.
                return true;
        }
index 5b15147..87330b0 100644 (file)
@@ -201,10 +201,4 @@ class DatabaseMysql extends DatabaseMysqlBase {
 
                return mysql_real_escape_string( $s, $conn );
        }
-
-       protected function mysqlPing() {
-               $conn = $this->getBindingHandle();
-
-               return mysql_ping( $conn );
-       }
 }
index ee84224..6380fe7 100644 (file)
@@ -570,14 +570,7 @@ abstract class DatabaseMysqlBase extends Database {
         * @return string
         */
        function strencode( $s ) {
-               $sQuoted = $this->mysqlRealEscapeString( $s );
-
-               if ( $sQuoted === false ) {
-                       $this->ping();
-                       $sQuoted = $this->mysqlRealEscapeString( $s );
-               }
-
-               return $sQuoted;
+               return $this->mysqlRealEscapeString( $s );
        }
 
        /**
@@ -606,18 +599,7 @@ abstract class DatabaseMysqlBase extends Database {
                return strlen( $name ) && $name[0] == '`' && substr( $name, -1, 1 ) == '`';
        }
 
-       /**
-        * @return bool
-        */
-       function ping() {
-               $ping = $this->mysqlPing();
-               if ( $ping ) {
-                       // Connection was good or lost but reconnected...
-                       // @note: mysqlnd (php 5.6+) does not support this (PHP bug 52561)
-                       return true;
-               }
-
-               // Try a full disconnect/reconnect cycle if ping() failed
+       function reconnect() {
                $this->closeConnection();
                $this->mOpened = false;
                $this->mConn = false;
@@ -626,13 +608,6 @@ abstract class DatabaseMysqlBase extends Database {
                return true;
        }
 
-       /**
-        * Ping a server connection or reconnect if there is no connection
-        *
-        * @return bool
-        */
-       abstract protected function mysqlPing();
-
        function getLag() {
                if ( $this->getLagDetectionMethod() === 'pt-heartbeat' ) {
                        return $this->getLagFromPtHeartbeat();
@@ -1186,12 +1161,6 @@ abstract class DatabaseMysqlBase extends Database {
                return $this->lastErrno() == 1205;
        }
 
-       /**
-        * Determines if the last query error was something that should be dealt
-        * with by pinging the connection and reissuing the query
-        *
-        * @return bool
-        */
        function wasErrorReissuable() {
                return $this->lastErrno() == 2013 || $this->lastErrno() == 2006;
        }
index d45805a..cb580cc 100644 (file)
@@ -309,12 +309,6 @@ class DatabaseMysqli extends DatabaseMysqlBase {
                return $conn->real_escape_string( $s );
        }
 
-       protected function mysqlPing() {
-               $conn = $this->getBindingHandle();
-
-               return $conn->ping();
-       }
-
        /**
         * Give an id for the connection
         *
index 9dcbd7f..43592e2 100644 (file)
@@ -1156,7 +1156,6 @@ interface IDatabase {
 
        /**
         * Determines how long the server has been up
-        * STUB
         *
         * @return int
         */
@@ -1164,7 +1163,6 @@ interface IDatabase {
 
        /**
         * Determines if the last failure was due to a deadlock
-        * STUB
         *
         * @return bool
         */
@@ -1172,16 +1170,14 @@ interface IDatabase {
 
        /**
         * Determines if the last failure was due to a lock timeout
-        * STUB
         *
         * @return bool
         */
        public function wasLockTimeout();
 
        /**
-        * Determines if the last query error was something that should be dealt
-        * with by pinging the connection and reissuing the query.
-        * STUB
+        * Determines if the last query error was due to a dropped connection and should
+        * be dealt with by pinging the connection and reissuing the query.
         *
         * @return bool
         */
@@ -1189,7 +1185,6 @@ interface IDatabase {
 
        /**
         * Determines if the last failure was due to the database being read-only.
-        * STUB
         *
         * @return bool
         */
index 053f9f8..4078a39 100644 (file)
@@ -31,15 +31,16 @@ use MediaWiki\Logger\LoggerFactory;
  * @ingroup Database
  */
 abstract class LBFactory implements DestructibleService {
-
        /** @var ChronologyProtector */
        protected $chronProt;
-
        /** @var TransactionProfiler */
        protected $trxProfiler;
-
        /** @var LoggerInterface */
-       protected $logger;
+       protected $trxLogger;
+       /** @var BagOStuff */
+       protected $srvCache;
+       /** @var WANObjectCache */
+       protected $wanCache;
 
        /** @var string|bool Reason all LBs are read-only or false if not */
        protected $readOnlyReason = false;
@@ -49,15 +50,28 @@ abstract class LBFactory implements DestructibleService {
        /**
         * Construct a factory based on a configuration array (typically from $wgLBFactoryConf)
         * @param array $conf
+        * @TODO: inject objects via dependency framework
         */
        public function __construct( array $conf ) {
                if ( isset( $conf['readOnlyReason'] ) && is_string( $conf['readOnlyReason'] ) ) {
                        $this->readOnlyReason = $conf['readOnlyReason'];
                }
-
                $this->chronProt = $this->newChronologyProtector();
                $this->trxProfiler = Profiler::instance()->getTransactionProfiler();
-               $this->logger = LoggerFactory::getInstance( 'DBTransaction' );
+               // Use APC/memcached style caching, but avoids loops with CACHE_DB (T141804)
+               $cache = ObjectCache::getLocalServerInstance();
+               if ( $cache->getQoS( $cache::ATTR_EMULATION ) > $cache::QOS_EMULATION_SQL ) {
+                       $this->srvCache = $cache;
+               } else {
+                       $this->srvCache = new EmptyBagOStuff();
+               }
+               $wCache = ObjectCache::getMainWANInstance();
+               if ( $wCache->getQoS( $wCache::ATTR_EMULATION ) > $wCache::QOS_EMULATION_SQL ) {
+                       $this->wanCache = $wCache;
+               } else {
+                       $this->wanCache = WANObjectCache::newEmpty();
+               }
+               $this->trxLogger = LoggerFactory::getInstance( 'DBTransaction' );
        }
 
        /**
@@ -261,7 +275,7 @@ abstract class LBFactory implements DestructibleService {
                        foreach ( $callersByDB as $db => $callers ) {
                                $msg .= "$db: " . implode( '; ', $callers ) . "\n";
                        }
-                       $this->logger->info( $msg );
+                       $this->trxLogger->info( $msg );
                }
        }
 
index 32b1a0f..0f3ca93 100644 (file)
@@ -317,7 +317,9 @@ class LBFactoryMulti extends LBFactory {
                        'servers' => $this->makeServerArray( $template, $loads, $groupLoads ),
                        'loadMonitor' => $this->loadMonitorClass,
                        'readOnlyReason' => $readOnlyReason,
-                       'trxProfiler' => $this->trxProfiler
+                       'trxProfiler' => $this->trxProfiler,
+                       'srvCache' => $this->srvCache,
+                       'wanCache' => $this->wanCache
                ] );
        }
 
index 1b0a1f3..14baf2e 100644 (file)
@@ -84,12 +84,7 @@ class LBFactorySimple extends LBFactory {
                        ] ];
                }
 
-               return new LoadBalancer( [
-                       'servers' => $servers,
-                       'loadMonitor' => $this->loadMonitorClass,
-                       'readOnlyReason' => $this->readOnlyReason,
-                       'trxProfiler' => $this->trxProfiler
-               ] );
+               return $this->newLoadBalancer( $servers );
        }
 
        /**
@@ -118,12 +113,7 @@ class LBFactorySimple extends LBFactory {
                        throw new MWException( __METHOD__ . ": Unknown cluster \"$cluster\"" );
                }
 
-               return new LoadBalancer( [
-                       'servers' => $wgExternalServers[$cluster],
-                       'loadMonitor' => $this->loadMonitorClass,
-                       'readOnlyReason' => $this->readOnlyReason,
-                       'trxProfiler' => $this->trxProfiler
-               ] );
+               return $this->newLoadBalancer( $wgExternalServers[$cluster] );
        }
 
        /**
@@ -141,6 +131,17 @@ class LBFactorySimple extends LBFactory {
                return $this->extLBs[$cluster];
        }
 
+       private function newLoadBalancer( array $servers ) {
+               return new LoadBalancer( [
+                       'servers' => $servers,
+                       'loadMonitor' => $this->loadMonitorClass,
+                       'readOnlyReason' => $this->readOnlyReason,
+                       'trxProfiler' => $this->trxProfiler,
+                       'srvCache' => $this->srvCache,
+                       'wanCache' => $this->wanCache
+               ] );
+       }
+
        /**
         * Execute a function for each tracked load balancer
         * The callback is called with the load balancer as the first parameter,
index 79ca3a7..14c1c28 100644 (file)
@@ -37,7 +37,9 @@ class LBFactorySingle extends LBFactory {
 
                $this->lb = new LoadBalancerSingle( [
                        'readOnlyReason' => $this->readOnlyReason,
-                       'trxProfiler' => $this->trxProfiler
+                       'trxProfiler' => $this->trxProfiler,
+                       'srvCache' => $this->srvCache,
+                       'wanCache' => $this->wanCache
                ] + $conf );
        }
 
@@ -106,7 +108,9 @@ class LoadBalancerSingle extends LoadBalancer {
                                        'load' => 1,
                                ]
                        ],
-                       'trxProfiler' => $this->trxProfiler
+                       'trxProfiler' => isset( $params['trxProfiler'] ) ? $params['trxProfiler'] : null,
+                       'srvCache' => isset( $params['srvCache'] ) ? $params['srvCache'] : null,
+                       'wanCache' => isset( $params['wanCache'] ) ? $params['wanCache'] : null
                ] );
 
                if ( isset( $params['readOnlyReason'] ) ) {
index 1269c3e..a7c486c 100644 (file)
@@ -91,6 +91,8 @@ class LoadBalancer {
         *  - servers : Required. Array of server info structures.
         *  - loadMonitor : Name of a class used to fetch server lag and load.
         *  - readOnlyReason : Reason the master DB is read-only if so [optional]
+        *  - srvCache : BagOStuff object [optional]
+        *  - wanCache : WANObjectCache object [optional]
         * @throws MWException
         */
        public function __construct( array $params ) {
@@ -138,21 +140,16 @@ class LoadBalancer {
                        }
                }
 
-               // Use APC/memcached style caching, but avoids loops with CACHE_DB (T141804)
-               // @TODO: inject these in via LBFactory at some point
-               $cache = ObjectCache::getLocalServerInstance();
-               if ( $cache->getQoS( $cache::ATTR_EMULATION ) > $cache::QOS_EMULATION_SQL ) {
-                       $this->srvCache = $cache;
+               if ( isset( $params['srvCache'] ) ) {
+                       $this->srvCache = $params['srvCache'];
                } else {
                        $this->srvCache = new EmptyBagOStuff();
                }
-               $wCache = ObjectCache::getMainWANInstance();
-               if ( $wCache->getQoS( $wCache::ATTR_EMULATION ) > $wCache::QOS_EMULATION_SQL ) {
-                       $this->wanCache = $wCache;
+               if ( isset( $params['wanCache'] ) ) {
+                       $this->wanCache = $params['wanCache'];
                } else {
                        $this->wanCache = WANObjectCache::newEmpty();
                }
-
                if ( isset( $params['trxProfiler'] ) ) {
                        $this->trxProfiler = $params['trxProfiler'];
                } else {
index e5ded45..b61b08d 100644 (file)
@@ -150,8 +150,7 @@ abstract class DBLockManager extends QuorumLockManager {
                if ( !isset( $this->conns[$lockDb] ) ) {
                        $db = null;
                        if ( $lockDb === 'localDBMaster' ) {
-                               $lb = wfGetLBFactory()->getMainLB( $this->domain );
-                               $db = $lb->getConnection( DB_MASTER, [], $this->domain );
+                               $db = $this->getLocalLB()->getConnection( DB_MASTER, [], $this->domain );
                        } elseif ( isset( $this->dbServers[$lockDb] ) ) {
                                $config = $this->dbServers[$lockDb];
                                $db = DatabaseBase::factory( $config['type'], $config );
@@ -178,6 +177,13 @@ abstract class DBLockManager extends QuorumLockManager {
                return $this->conns[$lockDb];
        }
 
+       /**
+        * @return LoadBalancer
+        */
+       protected function getLocalLB() {
+               return wfGetLBFactory()->getMainLB( $this->domain );
+       }
+
        /**
         * Do additional initialization for new lock DB connection
         *
@@ -249,10 +255,11 @@ class MySqlLockManager extends DBLockManager {
                self::LOCK_EX => self::LOCK_EX
        ];
 
-       /**
-        * @param string $lockDb
-        * @param IDatabase $db
-        */
+       protected function getLocalLB() {
+               // Use a separate connection so releaseAllLocks() doesn't rollback the main trx
+               return wfGetLBFactory()->newMainLB( $this->domain );
+       }
+
        protected function initConnection( $lockDb, IDatabase $db ) {
                # Let this transaction see lock rows from other transactions
                $db->query( "SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;" );
index accc42f..770d3bf 100644 (file)
@@ -87,7 +87,11 @@ class MssqlUpdater extends DatabaseUpdater {
                        [ 'updateSchema', 'recentchanges', 'recentchanges-drop-fks',
                                'patch-recentchanges-drop-fks.sql' ],
                        [ 'updateSchema', 'logging', 'logging-drop-fks', 'patch-logging-drop-fks.sql' ],
-                       [ 'updateSchema', 'archive', 'archive-drop-fks', 'patch-archive-drop-fks.sql' ]
+                       [ 'updateSchema', 'archive', 'archive-drop-fks', 'patch-archive-drop-fks.sql' ],
+
+                       // 1.28
+                       [ 'addIndex', 'recentchanges', 'rc_name_type_patrolled_timestamp',
+                               'patch-add-rc_name_type_patrolled_timestamp_index.sql' ],
                ];
        }
 
index d414d90..719b66a 100644 (file)
@@ -283,6 +283,10 @@ class MysqlUpdater extends DatabaseUpdater {
                        [ 'addIndex', 'categorylinks', 'cl_collation_ext',
                                'patch-add-cl_collation_ext_index.sql' ],
                        [ 'doCollationUpdate' ],
+
+                       // 1.28
+                       [ 'addIndex', 'recentchanges', 'rc_name_type_patrolled_timestamp',
+                               'patch-add-rc_name_type_patrolled_timestamp_index.sql' ],
                ];
        }
 
index 334256b..8075aac 100644 (file)
@@ -113,6 +113,10 @@ class OracleUpdater extends DatabaseUpdater {
                        [ 'dropTable', 'msg_resource' ],
                        [ 'addField', 'watchlist', 'wl_id', 'patch-watchlist-wl_id.sql' ],
 
+                       // 1.28
+                       [ 'addIndex', 'recentchanges', 'rc_name_type_patrolled_timestamp',
+                               'patch-add-rc_name_type_patrolled_timestamp_index.sql' ],
+
                        // KEEP THIS AT THE BOTTOM!!
                        [ 'doRebuildDuplicateFunction' ],
 
index a3b50ac..be94d91 100644 (file)
@@ -433,6 +433,10 @@ class PostgresUpdater extends DatabaseUpdater {
                                'addPgField', 'watchlist', 'wl_id',
                                "INTEGER NOT NULL PRIMARY KEY DEFAULT nextval('watchlist_wl_id_seq')"
                        ],
+
+                       // 1.28
+                       [ 'addPgIndex', 'recentchanges', 'rc_name_type_patrolled_timestamp',
+                               '( rc_namespace, rc_type, rc_patrolled, rc_timestamp )' ],
                ];
        }
 
index 86dccd7..1c6e6eb 100644 (file)
@@ -152,6 +152,10 @@ class SqliteUpdater extends DatabaseUpdater {
                        [ 'addIndex', 'categorylinks', 'cl_collation_ext',
                                'patch-add-cl_collation_ext_index.sql' ],
                        [ 'doCollationUpdate' ],
+
+                       // 1.28
+                       [ 'addIndex', 'recentchanges', 'rc_name_type_patrolled_timestamp',
+                               'patch-add-rc_name_type_patrolled_timestamp_index.sql' ],
                ];
        }
 
index cc31402..0ccbc7b 100644 (file)
        "config-ns-site-name": "Същото като името на уикито: $1",
        "config-ns-other": "Друго (уточняване)",
        "config-ns-other-default": "МоетоУики",
-       "config-project-namespace-help": "Следвайки примера на Уикипедия, много уикита съхраняват страниците си с правила в \"'''именно пространство на проекта'''\", отделно от основното съдържание.\nВсички заглавия на страниците в това именно пространство започват с определена представка, която може да бъде зададена тук.\nОбикновено представката произлиза от името на уикито, но не може да съдържа символи като \"#\" или \":\".",
+       "config-project-namespace-help": "Следвайки примера на Уикипедия, много уикита съхраняват страниците си с правила в '''именно пространство на проекта''', отделно от основното съдържание.\nВсички заглавия на страниците в това именно пространство започват с определена представка, която може да бъде зададена тук.\nОбикновено представката произлиза от името на уикито, но не може да съдържа символи като \"#\" или \":\".",
        "config-ns-invalid": "Посоченото именно пространство \"<nowiki>$1</nowiki>\" е невалидно.\nНеобходимо е да бъде посочено друго.",
        "config-ns-conflict": "Посоченото именно пространство \"<nowiki>$1</nowiki>\" е в конфликт с използваното по подразбиране именно пространство MediaWiki.\nНеобходимо е да се посочи друго именно пространство.",
        "config-admin-box": "Администраторска сметка",
        "config-install-mainpage": "Създаване на Началната страница със съдържание по подразбиране",
        "config-install-extension-tables": "Създаване на таблици за включените разширения",
        "config-install-mainpage-failed": "Вмъкването на Началната страница беше невъзможно: $1",
-       "config-install-done": "'''Поздравления!'''\nИнсталирането на МедияУики приключи успешно.\n\nИнсталаторът създаде файл <code>LocalSettings.php</code>.\nТой съдържа всичката необходима основна конфигурация на уикито.\n\nНеобходимо е той да бъде изтеглен и поставен в основната директория на уикито (директорията, в която е и index.php). Изтеглянето би трябвало да започне автоматично.\n\nАко изтеглянето не започне автоматично или е било прекратено, файлът може да бъде изтеглен чрез щракване на препратката по-долу:\n\n$3\n\n'''Забележка''': Ако това не бъде извършено сега, генерираният конфигурационен файл няма да е достъпен на по-късен етап ако не бъде изтеглен сега или инсталацията приключи без изтеглянето му.\n\nКогато файлът вече е в основната директория, '''[$2 уикито ще е достъпно на този адрес]'''.",
+       "config-install-done": "<strong>Поздравления!</strong>\nИнсталирането на МедияУики приключи успешно.\n\nИнсталаторът създаде файл <code>LocalSettings.php</code>.\nТой съдържа всичката необходима основна конфигурация на уикито.\n\nНеобходимо е той да бъде изтеглен и поставен в основната директория на уикито (директорията, в която е и index.php). Изтеглянето би трябвало да започне автоматично.\n\nАко изтеглянето не започне автоматично или е било прекратено, файлът може да бъде изтеглен чрез щракване на препратката по-долу:\n\n$3\n\n<strong>Забележка:</strong> Ако това не бъде извършено сега, генерираният конфигурационен файл няма да е достъпен на по-късен етап ако не бъде изтеглен сега или инсталацията приключи без изтеглянето му.\n\nКогато файлът вече е в основната директория, <strong>[$2 уикито ще е достъпно на този адрес]</strong>.",
        "config-download-localsettings": "Изтегляне на <code>LocalSettings.php</code>",
        "config-help": "помощ",
        "config-nofile": "Файлът „$1“ не може да бъде открит. Да не е бил изтрит?",
        "config-extension-link": "Знаете ли, че това уики поддържа [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Extensions разширения]?\n\nМожете да разгледате [https://www.mediawiki.org/wiki/Special:MyLanguage/Category:Extensions_by_category разширенията по категория] или [https://www.mediawiki.org/wiki/Extension_Matrix Матрицата на разширенията] за пълен списък на разширенията.",
-       "mainpagetext": "'''Уикито беше успешно инсталирано.'''",
+       "mainpagetext": "<strong>Уикито беше успешно инсталирано.</strong>",
        "mainpagedocfooter": "Разгледайте [https://meta.wikimedia.org/wiki/Help:Contents ръководството] за подробна информация относно използването на уики софтуера.\n\n== Първи стъпки ==\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings Настройки за конфигуриране]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ ЧЗВ за МедияУики]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce Пощенски списък относно нови версии на МедияУики]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation#Translation_resources Локализиране на МедияУики]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Combating_spam Научете как да се справяте със спама във вашето уики]"
 }
index 1d9a78d..0fc0e9f 100644 (file)
@@ -1,8 +1,9 @@
 {
        "@metadata": {
                "authors": [
-                       "Lionslayer"
+                       "Lionslayer",
+                       "Ninjastrikers"
                ]
        },
-       "mainpagetext": "'''မီဒီယာဝီကီကို အောင်မြင်စွာ သွင်းပြီးပါပြီ။'''"
+       "mainpagetext": "<strong>မီဒီယာဝီကီကို အောင်မြင်စွာ သွင်းပြီးပါပြီ။</strong>"
 }
index 98d7d12..a132dc5 100644 (file)
@@ -534,7 +534,7 @@ class JobRunner implements LoggerAwareInterface {
                wfGetLBFactory()->forEachLB( function( LoadBalancer $lb ) use ( $fname ) {
                        $lb->forEachOpenConnection( function( IDatabase $conn ) use ( $fname ) {
                                if ( $conn->writesOrCallbacksPending() ) {
-                                       $conn->query( "SELECT 1", $fname );
+                                       $conn->ping();
                                }
                        } );
                } );
index 16740d8..ed361eb 100644 (file)
@@ -84,11 +84,9 @@ class DjVuImage {
        function dump() {
                $file = fopen( $this->mFilename, 'rb' );
                $header = fread( $file, 12 );
-               // @todo FIXME: Would be good to replace this extract() call with
-               // something that explicitly initializes local variables.
-               extract( unpack( 'a4magic/a4chunk/NchunkLength', $header ) );
-               /** @var string $chunk
-                * @var string $chunkLength */
+               $arr = unpack( 'a4magic/a4chunk/NchunkLength', $header );
+               $chunk = $arr['chunk'];
+               $chunkLength = $arr['chunkLength'];
                echo "$chunk $chunkLength\n";
                $this->dumpForm( $file, $chunkLength, 1 );
                fclose( $file );
@@ -103,11 +101,9 @@ class DjVuImage {
                        if ( $chunkHeader == '' ) {
                                break;
                        }
-                       // @todo FIXME: Would be good to replace this extract() call with
-                       // something that explicitly initializes local variables.
-                       extract( unpack( 'a4chunk/NchunkLength', $chunkHeader ) );
-                       /** @var string $chunk
-                        * @var string $chunkLength */
+                       $arr = unpack( 'a4chunk/NchunkLength', $chunkHeader );
+                       $chunk = $arr['chunk'];
+                       $chunkLength = $arr['chunkLength'];
                        echo str_repeat( ' ', $indent * 4 ) . "$chunk $chunkLength\n";
 
                        if ( $chunk == 'FORM' ) {
@@ -138,24 +134,19 @@ class DjVuImage {
                if ( strlen( $header ) < 16 ) {
                        wfDebug( __METHOD__ . ": too short file header\n" );
                } else {
-                       // @todo FIXME: Would be good to replace this extract() call with
-                       // something that explicitly initializes local variables.
-                       extract( unpack( 'a4magic/a4form/NformLength/a4subtype', $header ) );
-
-                       /** @var string $magic
-                        * @var string $subtype
-                        * @var string $formLength
-                        * @var string $formType */
-                       if ( $magic != 'AT&T' ) {
+                       $arr = unpack( 'a4magic/a4form/NformLength/a4subtype', $header );
+
+                       $subtype = $arr['subtype'];
+                       if ( $arr['magic'] != 'AT&T' ) {
                                wfDebug( __METHOD__ . ": not a DjVu file\n" );
                        } elseif ( $subtype == 'DJVU' ) {
                                // Single-page document
                                $info = $this->getPageInfo( $file );
                        } elseif ( $subtype == 'DJVM' ) {
                                // Multi-page document
-                               $info = $this->getMultiPageInfo( $file, $formLength );
+                               $info = $this->getMultiPageInfo( $file, $arr['formLength'] );
                        } else {
-                               wfDebug( __METHOD__ . ": unrecognized DJVU file type '$formType'\n" );
+                               wfDebug( __METHOD__ . ": unrecognized DJVU file type '{$arr['subtype']}'\n" );
                        }
                }
                fclose( $file );
@@ -168,13 +159,9 @@ class DjVuImage {
                if ( strlen( $header ) < 8 ) {
                        return [ false, 0 ];
                } else {
-                       // @todo FIXME: Would be good to replace this extract() call with
-                       // something that explicitly initializes local variables.
-                       extract( unpack( 'a4chunk/Nlength', $header ) );
+                       $arr = unpack( 'a4chunk/Nlength', $header );
 
-                       /** @var string $chunk
-                        * @var string $length */
-                       return [ $chunk, $length ];
+                       return [ $arr['chunk'], $arr['length'] ];
                }
        }
 
@@ -236,31 +223,22 @@ class DjVuImage {
                        return false;
                }
 
-               // @todo FIXME: Would be good to replace this extract() call with
-               // something that explicitly initializes local variables.
-               extract( unpack(
+               $arr = unpack(
                        'nwidth/' .
                        'nheight/' .
                        'Cminor/' .
                        'Cmajor/' .
                        'vresolution/' .
-                       'Cgamma', $data ) );
+                       'Cgamma', $data );
 
                # Newer files have rotation info in byte 10, but we don't use it yet.
 
-               /** @var string $width
-                * @var string $height
-                * @var string $major
-                * @var string $minor
-                * @var string $resolution
-                * @var string $length
-                * @var string $gamma */
                return [
-                       'width' => $width,
-                       'height' => $height,
-                       'version' => "$major.$minor",
-                       'resolution' => $resolution,
-                       'gamma' => $gamma / 10.0 ];
+                       'width' => $arr['width'],
+                       'height' => $arr['height'],
+                       'version' => "{$arr['major']}.{$arr['minor']}",
+                       'resolution' => $arr['resolution'],
+                       'gamma' => $arr['gamma'] / 10.0 ];
        }
 
        /**
index f9eea48..206ad00 100644 (file)
@@ -251,7 +251,7 @@ class Parser {
        protected $mProfiler;
 
        /**
-        * @var LinkRenderer
+        * @var \MediaWiki\Linker\LinkRenderer
         */
        protected $mLinkRenderer;
 
@@ -882,10 +882,10 @@ class Parser {
        }
 
        /**
-        * Get a LinkRenderer instance to make links with
+        * Get a \MediaWiki\Linker\LinkRenderer instance to make links with
         *
         * @since 1.28
-        * @return LinkRenderer
+        * @return \MediaWiki\Linker\LinkRenderer
         */
        public function getLinkRenderer() {
                if ( !$this->mLinkRenderer ) {
index 3e5ef3b..8ccb6d1 100644 (file)
@@ -374,202 +374,15 @@ final class SessionManager implements SessionManagerInterface {
         * @deprecated since 1.27, use MediaWiki\Auth\AuthManager::autoCreateUser instead
         * @param User $user User to auto-create
         * @return bool Success
+        * @codeCoverageIgnore
         */
        public static function autoCreateUser( User $user ) {
-               global $wgAuth, $wgDisableAuthManager;
-
-               // @codeCoverageIgnoreStart
-               if ( !$wgDisableAuthManager ) {
-                       wfDeprecated( __METHOD__, '1.27' );
-                       return \MediaWiki\Auth\AuthManager::singleton()->autoCreateUser(
-                               $user,
-                               \MediaWiki\Auth\AuthManager::AUTOCREATE_SOURCE_SESSION,
-                               false
-                       )->isGood();
-               }
-               // @codeCoverageIgnoreEnd
-
-               $logger = self::singleton()->logger;
-
-               // Much of this code is based on that in CentralAuth
-
-               // Try the local user from the slave DB
-               $localId = User::idFromName( $user->getName() );
-               $flags = 0;
-
-               // Fetch the user ID from the master, so that we don't try to create the user
-               // when they already exist, due to replication lag
-               // @codeCoverageIgnoreStart
-               if ( !$localId && wfGetLB()->getReaderIndex() != 0 ) {
-                       $localId = User::idFromName( $user->getName(), User::READ_LATEST );
-                       $flags = User::READ_LATEST;
-               }
-               // @codeCoverageIgnoreEnd
-
-               if ( $localId ) {
-                       // User exists after all.
-                       $user->setId( $localId );
-                       $user->loadFromId( $flags );
-                       return false;
-               }
-
-               // Denied by AuthPlugin? But ignore AuthPlugin itself.
-               if ( get_class( $wgAuth ) !== 'AuthPlugin' && !$wgAuth->autoCreate() ) {
-                       $logger->debug( __METHOD__ . ': denied by AuthPlugin' );
-                       $user->setId( 0 );
-                       $user->loadFromId();
-                       return false;
-               }
-
-               // Wiki is read-only?
-               if ( wfReadOnly() ) {
-                       $logger->debug( __METHOD__ . ': denied by wfReadOnly()' );
-                       $user->setId( 0 );
-                       $user->loadFromId();
-                       return false;
-               }
-
-               $userName = $user->getName();
-
-               // Check the session, if we tried to create this user already there's
-               // no point in retrying.
-               $session = self::getGlobalSession();
-               $reason = $session->get( 'MWSession::AutoCreateBlacklist' );
-               if ( $reason ) {
-                       $logger->debug( __METHOD__ . ": blacklisted in session ($reason)" );
-                       $user->setId( 0 );
-                       $user->loadFromId();
-                       return false;
-               }
-
-               // Is the IP user able to create accounts?
-               $anon = new User;
-               if ( !$anon->isAllowedAny( 'createaccount', 'autocreateaccount' )
-                       || $anon->isBlockedFromCreateAccount()
-               ) {
-                       // Blacklist the user to avoid repeated DB queries subsequently
-                       $logger->debug( __METHOD__ . ': user is blocked from this wiki, blacklisting' );
-                       $session->set( 'MWSession::AutoCreateBlacklist', 'blocked', 600 );
-                       $session->persist();
-                       $user->setId( 0 );
-                       $user->loadFromId();
-                       return false;
-               }
-
-               // Check for validity of username
-               if ( !User::isCreatableName( $userName ) ) {
-                       $logger->debug( __METHOD__ . ': Invalid username, blacklisting' );
-                       $session->set( 'MWSession::AutoCreateBlacklist', 'invalid username', 600 );
-                       $session->persist();
-                       $user->setId( 0 );
-                       $user->loadFromId();
-                       return false;
-               }
-
-               // Give other extensions a chance to stop auto creation.
-               $user->loadDefaults( $userName );
-               $abortMessage = '';
-               if ( !\Hooks::run( 'AbortAutoAccount', [ $user, &$abortMessage ] ) ) {
-                       // In this case we have no way to return the message to the user,
-                       // but we can log it.
-                       $logger->debug( __METHOD__ . ": denied by hook: $abortMessage" );
-                       $session->set( 'MWSession::AutoCreateBlacklist', "hook aborted: $abortMessage", 600 );
-                       $session->persist();
-                       $user->setId( 0 );
-                       $user->loadFromId();
-                       return false;
-               }
-
-               // Make sure the name has not been changed
-               if ( $user->getName() !== $userName ) {
-                       $user->setId( 0 );
-                       $user->loadFromId();
-                       throw new \UnexpectedValueException(
-                               'AbortAutoAccount hook tried to change the user name'
-                       );
-               }
-
-               // Ignore warnings about master connections/writes...hard to avoid here
-               \Profiler::instance()->getTransactionProfiler()->resetExpectations();
-
-               $cache = \ObjectCache::getLocalClusterInstance();
-               $backoffKey = wfMemcKey( 'MWSession', 'autocreate-failed', md5( $userName ) );
-               if ( $cache->get( $backoffKey ) ) {
-                       $logger->debug( __METHOD__ . ': denied by prior creation attempt failures' );
-                       $user->setId( 0 );
-                       $user->loadFromId();
-                       return false;
-               }
-
-               // Checks passed, create the user...
-               $from = isset( $_SERVER['REQUEST_URI'] ) ? $_SERVER['REQUEST_URI'] : 'CLI';
-               $logger->info( __METHOD__ . ': creating new user ({username}) - from: {url}',
-                       [
-                               'username' => $userName,
-                               'url' => $from,
-               ] );
-
-               try {
-                       // Insert the user into the local DB master
-                       $status = $user->addToDatabase();
-                       if ( !$status->isOK() ) {
-                               // @codeCoverageIgnoreStart
-                               // double-check for a race condition (T70012)
-                               $id = User::idFromName( $user->getName(), User::READ_LATEST );
-                               if ( $id ) {
-                                       $logger->info( __METHOD__ . ': tried to autocreate existing user',
-                                               [
-                                                       'username' => $userName,
-                                               ] );
-                               } else {
-                                       $logger->error(
-                                               __METHOD__ . ': failed with message ' . $status->getWikiText( false, false, 'en' ),
-                                               [
-                                                       'username' => $userName,
-                                               ]
-                                       );
-                               }
-                               $user->setId( $id );
-                               $user->loadFromId( User::READ_LATEST );
-                               return false;
-                               // @codeCoverageIgnoreEnd
-                       }
-               } catch ( \Exception $ex ) {
-                       // @codeCoverageIgnoreStart
-                       $logger->error( __METHOD__ . ': failed with exception {exception}', [
-                               'exception' => $ex,
-                               'username' => $userName,
-                       ] );
-                       // Do not keep throwing errors for a while
-                       $cache->set( $backoffKey, 1, 600 );
-                       // Bubble up error; which should normally trigger DB rollbacks
-                       throw $ex;
-                       // @codeCoverageIgnoreEnd
-               }
-
-               # Notify AuthPlugin
-               // @codeCoverageIgnoreStart
-               $tmpUser = $user;
-               $wgAuth->initUser( $tmpUser, true );
-               if ( $tmpUser !== $user ) {
-                       $logger->warning( __METHOD__ . ': ' .
-                               get_class( $wgAuth ) . '::initUser() replaced the user object' );
-               }
-               // @codeCoverageIgnoreEnd
-
-               # Notify hooks (e.g. Newuserlog)
-               \Hooks::run( 'AuthPluginAutoCreate', [ $user ] );
-               \Hooks::run( 'LocalUserCreated', [ $user, true ] );
-
-               $user->saveSettings();
-
-               # Update user count
-               \DeferredUpdates::addUpdate( new \SiteStatsUpdate( 0, 0, 0, 0, 1 ) );
-
-               # Watch user's userpage and talk page
-               $user->addWatch( $user->getUserPage(), User::IGNORE_USER_RIGHTS );
-
-               return true;
+               wfDeprecated( __METHOD__, '1.27' );
+               return \MediaWiki\Auth\AuthManager::singleton()->autoCreateUser(
+                       $user,
+                       \MediaWiki\Auth\AuthManager::AUTOCREATE_SOURCE_SESSION,
+                       false
+               )->isGood();
        }
 
        /**
index 69e2e8b..22413b9 100644 (file)
@@ -665,34 +665,17 @@ class SkinTemplate extends Skin {
                                ? 'nav-login-createaccount'
                                : 'pt-login';
 
-                       // TODO remove this after AuthManager is stable
-                       global $wgDisableAuthManager;
-                       if ( $wgDisableAuthManager ) {
-                               $is_signup = $request->getText( 'type' ) == 'signup';
-                               $login_url = [
-                                       'text' => $this->msg( $loginlink )->text(),
-                                       'href' => self::makeSpecialUrl( 'Userlogin', $returnto ),
-                                       'active' => $title->isSpecial( 'Userlogin' )
-                                               && ( $loginlink == 'nav-login-createaccount' || !$is_signup ),
-                               ];
-                               $createaccount_url = [
-                                       'text' => $this->msg( 'pt-createaccount' )->text(),
-                                       'href' => self::makeSpecialUrl( 'Userlogin', "$returnto&type=signup" ),
-                                       'active' => $title->isSpecial( 'Userlogin' ) && $is_signup,
-                               ];
-                       } else {
-                               $login_url = [
-                                       'text' => $this->msg( $loginlink )->text(),
-                                       'href' => self::makeSpecialUrl( 'Userlogin', $returnto ),
-                                       'active' => $title->isSpecial( 'Userlogin' ) ||
-                                               $title->isSpecial( 'CreateAccount' ) && $useCombinedLoginLink,
-                               ];
-                               $createaccount_url = [
-                                       'text' => $this->msg( 'pt-createaccount' )->text(),
-                                       'href' => self::makeSpecialUrl( 'CreateAccount', $returnto ),
-                                       'active' => $title->isSpecial( 'CreateAccount' ),
-                               ];
-                       }
+                       $login_url = [
+                               'text' => $this->msg( $loginlink )->text(),
+                               'href' => self::makeSpecialUrl( 'Userlogin', $returnto ),
+                               'active' => $title->isSpecial( 'Userlogin' )
+                                       || $title->isSpecial( 'CreateAccount' ) && $useCombinedLoginLink,
+                       ];
+                       $createaccount_url = [
+                               'text' => $this->msg( 'pt-createaccount' )->text(),
+                               'href' => self::makeSpecialUrl( 'CreateAccount', $returnto ),
+                               'active' => $title->isSpecial( 'CreateAccount' ),
+                       ];
 
                        // No need to show Talk and Contributions to anons if they can't contribute!
                        if ( User::groupHasPermission( '*', 'edit' ) ) {
index 5dab221..8a2e0d6 100644 (file)
@@ -1342,196 +1342,12 @@ class FakeAuthTemplate extends BaseTemplate {
        }
 }
 
-/**
- * A horrible hack to handle AuthManager's feature flag. For other special pages this is done in
- * SpecialPageFactory, but LoginForm is used directly by some extensions. Will be killed as soon
- * as AuthManager is stable.
- */
-class LoginForm extends SpecialPage {
-       private $realLoginForm;
-
-       public function __construct( $request = null ) {
-               global $wgDisableAuthManager;
-               if ( $wgDisableAuthManager ) {
-                       $this->realLoginForm = new LoginFormPreAuthManager( $request );
-               } else {
-                       $this->realLoginForm = new LoginFormAuthManager( $request );
-               }
-       }
-
-       // proxy everything
-
-       public function __get( $name ) {
-               return $this->realLoginForm->$name;
-       }
-
-       public function __set( $name, $value ) {
-               $this->realLoginForm->$name = $value;
-       }
-
-       public function __call( $name, $args ) {
-               return call_user_func_array( [ $this->realLoginForm, $name ], $args );
-       }
-
-       public static function __callStatic( $name, $args ) {
-               global $wgDisableAuthManager;
-               return call_user_func_array( [ $wgDisableAuthManager ? LoginFormPreAuthManager::class
-                       : LoginFormAuthManager::class, $name ], $args );
-       }
-
-       // all public SpecialPage methods need to be proxied explicitly
-
-       public function getName() {
-               return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
-       }
-       public function getRestriction() {
-               return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
-       }
-       public function isListed() {
-               return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
-       }
-       public function setListed( $listed ) {
-               return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
-       }
-       public function listed( $x = null ) {
-               return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
-       }
-       public function isIncludable() {
-               return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
-       }
-       public function including( $x = null ) {
-               return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
-       }
-       public function getLocalName() {
-               return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
-       }
-       public function isExpensive() {
-               return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
-       }
-       public function isCached() {
-               return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
-       }
-       public function isRestricted() {
-               return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
-       }
-       public function userCanExecute( User $user ) {
-               return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
-       }
-       public function displayRestrictionError() {
-               return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
-       }
-       public function checkPermissions() {
-               return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
-       }
-       public function checkReadOnly() {
-               return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
-       }
-       public function requireLogin(
-               $reasonMsg = 'exception-nologin-text', $titleMsg = 'exception-nologin'
-       ) {
-               return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
-       }
-       public function prefixSearchSubpages( $search, $limit, $offset ) {
-               return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
-       }
-       public function execute( $subPage ) {
-               return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
-       }
-       public function getDescription() {
-               return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
-       }
-       function getTitle( $subpage = false ) {
-               return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
-       }
-       function getPageTitle( $subpage = false ) {
-               return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
-       }
-       public function setContext( $context ) {
-               return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
-       }
-       public function getContext() {
-               return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
-       }
-       public function getRequest() {
-               return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
-       }
-       public function getOutput() {
-               return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
-       }
-       public function getUser() {
-               return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
-       }
-       public function getSkin() {
-               return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
-       }
-       public function getLanguage() {
-               return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
-       }
-       public function getConfig() {
-               return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
-       }
-       public function getFullTitle() {
-               return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
-       }
-       public function getFinalGroupName() {
-               return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
-       }
-       public function doesWrites() {
-               return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
-       }
-
-       // no way to proxy constants and static properties
-
-       const SUCCESS = 0;
-       const NO_NAME = 1;
-       const ILLEGAL = 2;
-       const WRONG_PLUGIN_PASS = 3;
-       const NOT_EXISTS = 4;
-       const WRONG_PASS = 5;
-       const EMPTY_PASS = 6;
-       const RESET_PASS = 7;
-       const ABORTED = 8;
-       const CREATE_BLOCKED = 9;
-       const THROTTLED = 10;
-       const USER_BLOCKED = 11;
-       const NEED_TOKEN = 12;
-       const WRONG_TOKEN = 13;
-       const USER_MIGRATED = 14;
-
-       public static $statusCodes = [
-               self::SUCCESS => 'success',
-               self::NO_NAME => 'no_name',
-               self::ILLEGAL => 'illegal',
-               self::WRONG_PLUGIN_PASS => 'wrong_plugin_pass',
-               self::NOT_EXISTS => 'not_exists',
-               self::WRONG_PASS => 'wrong_pass',
-               self::EMPTY_PASS => 'empty_pass',
-               self::RESET_PASS => 'reset_pass',
-               self::ABORTED => 'aborted',
-               self::CREATE_BLOCKED => 'create_blocked',
-               self::THROTTLED => 'throttled',
-               self::USER_BLOCKED => 'user_blocked',
-               self::NEED_TOKEN => 'need_token',
-               self::WRONG_TOKEN => 'wrong_token',
-               self::USER_MIGRATED => 'user_migrated',
-       ];
-
-       public static $validErrorMessages = [
-               'exception-nologin-text',
-               'watchlistanontext',
-               'changeemail-no-info',
-               'resetpass-no-info',
-               'confirmemail_needlogin',
-               'prefsnologintext2',
-       ];
-}
-
 /**
  * LoginForm as a special page has been replaced by SpecialUserLogin and SpecialCreateAccount,
  * but some extensions called its public methods directly, so the class is retained as a
  * B/C wrapper. Anything that used it before should use AuthManager instead.
  */
-class LoginFormAuthManager extends SpecialPage {
+class LoginForm extends SpecialPage {
        const SUCCESS = 0;
        const NO_NAME = 1;
        const ILLEGAL = 2;
index 44b8fff..00d8c4a 100644 (file)
@@ -61,7 +61,7 @@ class SpecialPage {
        protected $mContext;
 
        /**
-        * @var LinkRenderer|null
+        * @var \MediaWiki\Linker\LinkRenderer|null
         */
        private $linkRenderer;
 
@@ -851,7 +851,7 @@ class SpecialPage {
 
        /**
         * @since 1.28
-        * @return LinkRenderer
+        * @return \MediaWiki\Linker\LinkRenderer
         */
        protected function getLinkRenderer() {
                if ( $this->linkRenderer ) {
@@ -863,7 +863,7 @@ class SpecialPage {
 
        /**
         * @since 1.28
-        * @param LinkRenderer $linkRenderer
+        * @param \MediaWiki\Linker\LinkRenderer $linkRenderer
         */
        public function setLinkRenderer( LinkRenderer $linkRenderer ) {
                $this->linkRenderer = $linkRenderer;
index 68c817c..4356bc5 100644 (file)
@@ -84,8 +84,8 @@ class SpecialPageFactory {
 
                // Authentication
                'Userlogin' => 'SpecialUserLogin',
-               'Userlogout' => 'SpecialUserlogoutPreAuthManager',
-               'CreateAccount' => 'SpecialCreateAccountPreAuthManager',
+               'Userlogout' => 'SpecialUserLogout',
+               'CreateAccount' => 'SpecialCreateAccount',
                'LinkAccounts' => 'SpecialLinkAccounts',
                'UnlinkAccounts' => 'SpecialUnlinkAccounts',
                'ChangeCredentials' => 'SpecialChangeCredentials',
@@ -96,9 +96,9 @@ class SpecialPageFactory {
                'Block' => 'SpecialBlock',
                'Unblock' => 'SpecialUnblock',
                'BlockList' => 'SpecialBlockList',
-               'ChangePassword' => 'SpecialChangePasswordPreAuthManager',
+               'ChangePassword' => 'SpecialChangePassword',
                'BotPasswords' => 'SpecialBotPasswords',
-               'PasswordReset' => 'SpecialPasswordResetPreAuthManager',
+               'PasswordReset' => 'SpecialPasswordReset',
                'DeletedContributions' => 'DeletedContributionsPage',
                'Preferences' => 'SpecialPreferences',
                'ResetTokens' => 'SpecialResetTokens',
@@ -231,7 +231,6 @@ class SpecialPageFactory {
                global $wgDisableInternalSearch, $wgEmailAuthentication;
                global $wgEnableEmail, $wgEnableJavaScriptTest;
                global $wgPageLanguageUseDB, $wgContentHandlerUseDB;
-               global $wgDisableAuthManager;
 
                if ( !is_array( self::$list ) ) {
 
@@ -247,7 +246,7 @@ class SpecialPageFactory {
                        }
 
                        if ( $wgEnableEmail ) {
-                               self::$list['ChangeEmail'] = 'SpecialChangeEmailPreAuthManager';
+                               self::$list['ChangeEmail'] = 'SpecialChangeEmail';
                        }
 
                        if ( $wgEnableJavaScriptTest ) {
@@ -261,20 +260,6 @@ class SpecialPageFactory {
                                self::$list['ChangeContentModel'] = 'SpecialChangeContentModel';
                        }
 
-                       // horrible hack to allow selection between old and new classes via a feature flag - T110756
-                       // will be removed once AuthManager is stable
-                       if ( !$wgDisableAuthManager ) {
-                               self::$list = array_map( function ( $class ) {
-                                       return preg_replace( '/PreAuthManager$/', '', $class );
-                               }, self::$list );
-                               self::$list['Userlogout'] = 'SpecialUserLogout'; // case matters
-                       } else {
-                               self::$list['Userlogin'] = 'LoginForm';
-                               self::$list = array_diff_key( self::$list, array_fill_keys( [
-                                       'LinkAccounts', 'UnlinkAccounts', 'ChangeCredentials', 'RemoveCredentials',
-                               ], true ) );
-                       }
-
                        // Add extension special pages
                        self::$list = array_merge( self::$list, $wgSpecialPages );
 
index 627dd2c..a5a45d5 100644 (file)
@@ -2,7 +2,6 @@
 /**
  * @defgroup Watchlist Users watchlist handling
  */
-use MediaWiki\Linker\LinkTarget;
 
 /**
  * Implements Special:EditWatchlist
@@ -27,6 +26,8 @@ use MediaWiki\Linker\LinkTarget;
  * @ingroup Watchlist
  */
 
+use MediaWiki\Linker\LinkRenderer;
+use MediaWiki\Linker\LinkTarget;
 use MediaWiki\MediaWikiServices;
 
 /**
@@ -138,7 +139,13 @@ class SpecialEditWatchlist extends UnlistedSpecialPage {
        protected function outputSubtitle() {
                $out = $this->getOutput();
                $out->addSubtitle( $this->msg( 'watchlistfor2', $this->getUser()->getName() )
-                       ->rawParams( SpecialEditWatchlist::buildTools( null ) ) );
+                       ->rawParams(
+                               self::buildTools(
+                                       $this->getLanguage(),
+                                       $this->getLinkRenderer()
+                               )
+                       )
+               );
        }
 
        /**
@@ -277,7 +284,7 @@ class SpecialEditWatchlist extends UnlistedSpecialPage {
         * @param string $output
         */
        private function showTitles( $titles, &$output ) {
-               $talk = $this->msg( 'talkpagelinktext' )->escaped();
+               $talk = $this->msg( 'talkpagelinktext' )->text();
                // Do a batch existence check
                $batch = new LinkBatch();
                if ( count( $titles ) >= 100 ) {
@@ -300,6 +307,7 @@ class SpecialEditWatchlist extends UnlistedSpecialPage {
                // Print out the list
                $output .= "<ul>\n";
 
+               $linkRenderer = $this->getLinkRenderer();
                foreach ( $titles as $title ) {
                        if ( !$title instanceof Title ) {
                                $title = Title::newFromText( $title );
@@ -307,9 +315,9 @@ class SpecialEditWatchlist extends UnlistedSpecialPage {
 
                        if ( $title instanceof Title ) {
                                $output .= '<li>' .
-                                       Linker::link( $title ) . ' ' .
+                                       $linkRenderer->makeLink( $title ) . ' ' .
                                        $this->msg( 'parentheses' )->rawParams(
-                                               Linker::link( $title->getTalkPage(), $talk )
+                                               $linkRenderer->makeLink( $title->getTalkPage(), $talk )
                                        )->escaped() .
                                        "</li>\n";
                        }
@@ -610,26 +618,27 @@ class SpecialEditWatchlist extends UnlistedSpecialPage {
         * @return string
         */
        private function buildRemoveLine( $title ) {
-               $link = Linker::link( $title );
+               $linkRenderer = $this->getLinkRenderer();
+               $link = $linkRenderer->makeLink( $title );
 
-               $tools['talk'] = Linker::link(
+               $tools['talk'] = $linkRenderer->makeLink(
                        $title->getTalkPage(),
-                       $this->msg( 'talkpagelinktext' )->escaped()
+                       $this->msg( 'talkpagelinktext' )->text()
                );
 
                if ( $title->exists() ) {
-                       $tools['history'] = Linker::linkKnown(
+                       $tools['history'] = $linkRenderer->makeKnownLink(
                                $title,
-                               $this->msg( 'history_short' )->escaped(),
+                               $this->msg( 'history_short' )->text(),
                                [],
                                [ 'action' => 'history' ]
                        );
                }
 
                if ( $title->getNamespace() == NS_USER && !$title->isSubpage() ) {
-                       $tools['contributions'] = Linker::linkKnown(
+                       $tools['contributions'] = $linkRenderer->makeKnownLink(
                                SpecialPage::getTitleFor( 'Contributions', $title->getText() ),
-                               $this->msg( 'contributions' )->escaped()
+                               $this->msg( 'contributions' )->text()
                        );
                }
 
@@ -724,11 +733,19 @@ class SpecialEditWatchlist extends UnlistedSpecialPage {
         * Build a set of links for convenient navigation
         * between watchlist viewing and editing modes
         *
-        * @param null $unused
+        * @param Language $lang
+        * @param LinkRenderer|null $linkRenderer
         * @return string
         */
-       public static function buildTools( $unused ) {
-               global $wgLang;
+       public static function buildTools( $lang, LinkRenderer $linkRenderer = null ) {
+               if ( !$lang instanceof Language ) {
+                       // back-compat where the first parameter was $unused
+                       global $wgLang;
+                       $lang = $wgLang;
+               }
+               if ( !$linkRenderer ) {
+                       $linkRenderer = MediaWikiServices::getInstance()->getLinkRenderer();
+               }
 
                $tools = [];
                $modes = [
@@ -740,16 +757,16 @@ class SpecialEditWatchlist extends UnlistedSpecialPage {
 
                foreach ( $modes as $mode => $arr ) {
                        // can use messages 'watchlisttools-view', 'watchlisttools-edit', 'watchlisttools-raw'
-                       $tools[] = Linker::linkKnown(
+                       $tools[] = $linkRenderer->makeKnownLink(
                                SpecialPage::getTitleFor( $arr[0], $arr[1] ),
-                               wfMessage( "watchlisttools-{$mode}" )->escaped()
+                               wfMessage( "watchlisttools-{$mode}" )->text()
                        );
                }
 
                return Html::rawElement(
                        'span',
                        [ 'class' => 'mw-watchlist-toollinks' ],
-                       wfMessage( 'parentheses' )->rawParams( $wgLang->pipeList( $tools ) )->escaped()
+                       wfMessage( 'parentheses' )->rawParams( $lang->pipeList( $tools ) )->escaped()
                );
        }
 }
index bfb52e8..6ca1100 100644 (file)
@@ -339,7 +339,13 @@ class SpecialUpload extends SpecialPage {
         * @param string $message HTML message to be passed to mainUploadForm
         */
        protected function showRecoverableUploadError( $message ) {
-               $sessionKey = $this->mUpload->stashFile()->getFileKey();
+               $stashStatus = $this->mUpload->tryStashFile( $this->getUser() );
+               if ( $stashStatus->isGood() ) {
+                       $sessionKey = $stashStatus->getValue()->getFileKey();
+               } else {
+                       $sessionKey = null;
+                       // TODO Add a warning message about the failure to stash here?
+               }
                $message = '<h2>' . $this->msg( 'uploaderror' )->escaped() . "</h2>\n" .
                        '<div class="error">' . $message . "</div>\n";
 
@@ -368,7 +374,13 @@ class SpecialUpload extends SpecialPage {
                        return false;
                }
 
-               $sessionKey = $this->mUpload->stashFile()->getFileKey();
+               $stashStatus = $this->mUpload->tryStashFile( $this->getUser() );
+               if ( $stashStatus->isGood() ) {
+                       $sessionKey = $stashStatus->getValue()->getFileKey();
+               } else {
+                       $sessionKey = null;
+                       // TODO Add a warning message about the failure to stash here?
+               }
 
                // Add styles for the warning, reused from the live preview
                $this->getOutput()->addModuleStyles( 'mediawiki.special.upload.styles' );
index 58cde7e..17d77ba 100644 (file)
@@ -429,7 +429,10 @@ class SpecialWatchlist extends ChangesListSpecialPage {
 
                $out->addSubtitle(
                        $this->msg( 'watchlistfor2', $user->getName() )
-                               ->rawParams( SpecialEditWatchlist::buildTools( null ) )
+                               ->rawParams( SpecialEditWatchlist::buildTools(
+                                       $this->getLanguage(),
+                                       $this->getLinkRenderer()
+                               ) )
                );
 
                $this->setTopText( $opts );
diff --git a/includes/specials/pre-authmanager/README b/includes/specials/pre-authmanager/README
deleted file mode 100644 (file)
index 1cfdd5f..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-This directory temporarily hosts pre-AuthManager code as a way of feature-flagging.
-Class names are postfixed with 'PreAuthManager' and SpecialPageFactory adds/removes
-that postfix based on the feature flag.
-
-This is a horrible hack that will only be in place for a few weeks, to allow instant
-rollback while AuthManager is tested in WMF production and major problems are ironed
-out. In the past such issues have been handled via deployment branches, but that
-meant blocking the work of all WMF developers from being deployed. This is hoped
-to be a less disruptive method.
-
diff --git a/includes/specials/pre-authmanager/SpecialChangeEmail.php b/includes/specials/pre-authmanager/SpecialChangeEmail.php
deleted file mode 100644 (file)
index 7861562..0000000
+++ /dev/null
@@ -1,216 +0,0 @@
-<?php
-/**
- * Implements Special:ChangeEmail
- *
- * 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 SpecialPage
- */
-
-/**
- * Let users change their email address.
- *
- * @ingroup SpecialPage
- */
-class SpecialChangeEmailPreAuthManager extends FormSpecialPage {
-       /**
-        * @var Status
-        */
-       private $status;
-
-       public function __construct() {
-               parent::__construct( 'ChangeEmail', 'editmyprivateinfo' );
-       }
-
-       public function doesWrites() {
-               return true;
-       }
-
-       /**
-        * @return bool
-        */
-       public function isListed() {
-               global $wgAuth;
-
-               return $wgAuth->allowPropChange( 'emailaddress' );
-       }
-
-       /**
-        * Main execution point
-        * @param string $par
-        */
-       function execute( $par ) {
-               $out = $this->getOutput();
-               $out->disallowUserJs();
-
-               parent::execute( $par );
-       }
-
-       protected function checkExecutePermissions( User $user ) {
-               global $wgAuth;
-
-               if ( !$wgAuth->allowPropChange( 'emailaddress' ) ) {
-                       throw new ErrorPageError( 'changeemail', 'cannotchangeemail' );
-               }
-
-               $this->requireLogin( 'changeemail-no-info' );
-
-               // This could also let someone check the current email address, so
-               // require both permissions.
-               if ( !$this->getUser()->isAllowed( 'viewmyprivateinfo' ) ) {
-                       throw new PermissionsError( 'viewmyprivateinfo' );
-               }
-
-               parent::checkExecutePermissions( $user );
-       }
-
-       protected function getFormFields() {
-               $user = $this->getUser();
-
-               $fields = [
-                       'Name' => [
-                               'type' => 'info',
-                               'label-message' => 'username',
-                               'default' => $user->getName(),
-                       ],
-                       'OldEmail' => [
-                               'type' => 'info',
-                               'label-message' => 'changeemail-oldemail',
-                               'default' => $user->getEmail() ?: $this->msg( 'changeemail-none' )->text(),
-                       ],
-                       'NewEmail' => [
-                               'type' => 'email',
-                               'label-message' => 'changeemail-newemail',
-                               'autofocus' => true,
-                               'help-message' => 'changeemail-newemail-help',
-                       ],
-               ];
-
-               if ( $this->getConfig()->get( 'RequirePasswordforEmailChange' ) ) {
-                       $fields['Password'] = [
-                               'type' => 'password',
-                               'label-message' => 'changeemail-password'
-                       ];
-               }
-
-               return $fields;
-       }
-
-       protected function getDisplayFormat() {
-               return 'ooui';
-       }
-
-       protected function alterForm( HTMLForm $form ) {
-               $form->setId( 'mw-changeemail-form' );
-               $form->setTableId( 'mw-changeemail-table' );
-               $form->setSubmitTextMsg( 'changeemail-submit' );
-               $form->addHiddenFields( $this->getRequest()->getValues( 'returnto', 'returntoquery' ) );
-
-               $form->addHeaderText( $this->msg( 'changeemail-header' )->parseAsBlock() );
-               if ( $this->getConfig()->get( 'RequirePasswordforEmailChange' ) ) {
-                       $form->addHeaderText( $this->msg( 'changeemail-passwordrequired' )->parseAsBlock() );
-               }
-       }
-
-       public function onSubmit( array $data ) {
-               $password = isset( $data['Password'] ) ? $data['Password'] : null;
-               $status = $this->attemptChange( $this->getUser(), $password, $data['NewEmail'] );
-
-               $this->status = $status;
-
-               return $status;
-       }
-
-       public function onSuccess() {
-               $request = $this->getRequest();
-
-               $returnto = $request->getVal( 'returnto' );
-               $titleObj = $returnto !== null ? Title::newFromText( $returnto ) : null;
-               if ( !$titleObj instanceof Title ) {
-                       $titleObj = Title::newMainPage();
-               }
-               $query = $request->getVal( 'returntoquery' );
-
-               if ( $this->status->value === true ) {
-                       $this->getOutput()->redirect( $titleObj->getFullURL( $query ) );
-               } elseif ( $this->status->value === 'eauth' ) {
-                       # Notify user that a confirmation email has been sent...
-                       $this->getOutput()->wrapWikiMsg( "<div class='error' style='clear: both;'>\n$1\n</div>",
-                               'eauthentsent', $this->getUser()->getName() );
-                       // just show the link to go back
-                       $this->getOutput()->addReturnTo( $titleObj, wfCgiToArray( $query ) );
-               }
-       }
-
-       /**
-        * @param User $user
-        * @param string $pass
-        * @param string $newaddr
-        * @return Status
-        */
-       private function attemptChange( User $user, $pass, $newaddr ) {
-               global $wgAuth;
-
-               if ( $newaddr != '' && !Sanitizer::validateEmail( $newaddr ) ) {
-                       return Status::newFatal( 'invalidemailaddress' );
-               }
-
-               if ( $newaddr === $user->getEmail() ) {
-                       return Status::newFatal( 'changeemail-nochange' );
-               }
-
-               $throttleInfo = LoginForm::incrementLoginThrottle( $user->getName() );
-               if ( $throttleInfo ) {
-                       $lang = $this->getLanguage();
-                       return Status::newFatal(
-                               'changeemail-throttled',
-                               $lang->formatDuration( $throttleInfo['wait'] )
-                       );
-               }
-
-               if ( $this->getConfig()->get( 'RequirePasswordforEmailChange' )
-                       && !$user->checkTemporaryPassword( $pass )
-                       && !$user->checkPassword( $pass )
-               ) {
-                       return Status::newFatal( 'wrongpassword' );
-               }
-
-               LoginForm::clearLoginThrottle( $user->getName() );
-
-               $oldaddr = $user->getEmail();
-               $status = $user->setEmailWithConfirmation( $newaddr );
-               if ( !$status->isGood() ) {
-                       return $status;
-               }
-
-               Hooks::run( 'PrefsEmailAudit', [ $user, $oldaddr, $newaddr ] );
-
-               $user->saveSettings();
-
-               $wgAuth->updateExternalDB( $user );
-
-               return $status;
-       }
-
-       public function requiresUnblock() {
-               return false;
-       }
-
-       protected function getGroupName() {
-               return 'users';
-       }
-}
diff --git a/includes/specials/pre-authmanager/SpecialChangePassword.php b/includes/specials/pre-authmanager/SpecialChangePassword.php
deleted file mode 100644 (file)
index 3955fee..0000000
+++ /dev/null
@@ -1,343 +0,0 @@
-<?php
-/**
- * Implements Special:ChangePassword
- *
- * 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 SpecialPage
- */
-
-/**
- * Let users recover their password.
- *
- * @ingroup SpecialPage
- */
-class SpecialChangePasswordPreAuthManager extends FormSpecialPage {
-       protected $mUserName;
-       protected $mDomain;
-
-       // Optional Wikitext Message to show above the password change form
-       protected $mPreTextMessage = null;
-
-       // label for old password input
-       protected $mOldPassMsg = null;
-
-       public function __construct() {
-               parent::__construct( 'ChangePassword', 'editmyprivateinfo' );
-               $this->listed( false );
-       }
-
-       public function doesWrites() {
-               return true;
-       }
-
-       /**
-        * Main execution point
-        * @param string|null $par
-        */
-       function execute( $par ) {
-               $this->getOutput()->disallowUserJs();
-
-               parent::execute( $par );
-       }
-
-       protected function checkExecutePermissions( User $user ) {
-               parent::checkExecutePermissions( $user );
-
-               if ( !$this->getRequest()->wasPosted() ) {
-                       $this->requireLogin( 'resetpass-no-info' );
-               }
-       }
-
-       /**
-        * Set a message at the top of the Change Password form
-        * @since 1.23
-        * @param Message $msg Message to parse and add to the form header
-        */
-       public function setChangeMessage( Message $msg ) {
-               $this->mPreTextMessage = $msg;
-       }
-
-       /**
-        * Set a message at the top of the Change Password form
-        * @since 1.23
-        * @param string $msg Message label for old/temp password field
-        */
-       public function setOldPasswordMessage( $msg ) {
-               $this->mOldPassMsg = $msg;
-       }
-
-       protected function getFormFields() {
-               $user = $this->getUser();
-               $request = $this->getRequest();
-
-               $oldpassMsg = $this->mOldPassMsg;
-               if ( $oldpassMsg === null ) {
-                       $oldpassMsg = $user->isLoggedIn() ? 'oldpassword' : 'resetpass-temp-password';
-               }
-
-               $fields = [
-                       'Name' => [
-                               'type' => 'info',
-                               'label-message' => 'username',
-                               'default' => $request->getVal( 'wpName', $user->getName() ),
-                       ],
-                       'Password' => [
-                               'type' => 'password',
-                               'label-message' => $oldpassMsg,
-                       ],
-                       'NewPassword' => [
-                               'type' => 'password',
-                               'label-message' => 'newpassword',
-                       ],
-                       'Retype' => [
-                               'type' => 'password',
-                               'label-message' => 'retypenew',
-                       ],
-               ];
-
-               if ( !$this->getUser()->isLoggedIn() ) {
-                       $fields['LoginOnChangeToken'] = [
-                               'type' => 'hidden',
-                               'label' => 'Change Password Token',
-                               'default' => LoginForm::getLoginToken()->toString(),
-                       ];
-               }
-
-               $extraFields = [];
-               Hooks::run( 'ChangePasswordForm', [ &$extraFields ] );
-               foreach ( $extraFields as $extra ) {
-                       list( $name, $label, $type, $default ) = $extra;
-                       $fields[$name] = [
-                               'type' => $type,
-                               'name' => $name,
-                               'label-message' => $label,
-                               'default' => $default,
-                       ];
-               }
-
-               if ( !$user->isLoggedIn() ) {
-                       $fields['Remember'] = [
-                               'type' => 'check',
-                               'label' => $this->msg( 'remembermypassword' )
-                                               ->numParams(
-                                                       ceil( $this->getConfig()->get( 'CookieExpiration' ) / ( 3600 * 24 ) )
-                                               )->text(),
-                               'default' => $request->getVal( 'wpRemember' ),
-                       ];
-               }
-
-               return $fields;
-       }
-
-       protected function alterForm( HTMLForm $form ) {
-               $form->setId( 'mw-resetpass-form' );
-               $form->setTableId( 'mw-resetpass-table' );
-               $form->setWrapperLegendMsg( 'resetpass_header' );
-               $form->setSubmitTextMsg(
-                       $this->getUser()->isLoggedIn()
-                               ? 'resetpass-submit-loggedin'
-                               : 'resetpass_submit'
-               );
-               $form->addButton( [
-                       'name' => 'wpCancel',
-                       'value' => $this->msg( 'resetpass-submit-cancel' )->text()
-               ] );
-               $form->setHeaderText( $this->msg( 'resetpass_text' )->parseAsBlock() );
-               if ( $this->mPreTextMessage instanceof Message ) {
-                       $form->addPreText( $this->mPreTextMessage->parseAsBlock() );
-               }
-               $form->addHiddenFields(
-                       $this->getRequest()->getValues( 'wpName', 'wpDomain', 'returnto', 'returntoquery' ) );
-       }
-
-       public function onSubmit( array $data ) {
-               global $wgAuth;
-
-               $request = $this->getRequest();
-
-               if ( $request->getCheck( 'wpLoginToken' ) ) {
-                       // This comes from Special:Userlogin when logging in with a temporary password
-                       return false;
-               }
-
-               if ( !$this->getUser()->isLoggedIn()
-                       && !LoginForm::getLoginToken()->match( $request->getVal( 'wpLoginOnChangeToken' ) )
-               ) {
-                       // Potential CSRF (bug 62497)
-                       return false;
-               }
-
-               if ( $request->getCheck( 'wpCancel' ) ) {
-                       $returnto = $request->getVal( 'returnto' );
-                       $titleObj = $returnto !== null ? Title::newFromText( $returnto ) : null;
-                       if ( !$titleObj instanceof Title ) {
-                               $titleObj = Title::newMainPage();
-                       }
-                       $query = $request->getVal( 'returntoquery' );
-                       $this->getOutput()->redirect( $titleObj->getFullURL( $query ) );
-
-                       return true;
-               }
-
-               $this->mUserName = $request->getVal( 'wpName', $this->getUser()->getName() );
-               $this->mDomain = $wgAuth->getDomain();
-
-               if ( !$wgAuth->allowPasswordChange() ) {
-                       throw new ErrorPageError( 'changepassword', 'resetpass_forbidden' );
-               }
-
-               $status = $this->attemptReset( $data['Password'], $data['NewPassword'], $data['Retype'] );
-
-               return $status;
-       }
-
-       public function onSuccess() {
-               if ( $this->getUser()->isLoggedIn() ) {
-                       $this->getOutput()->wrapWikiMsg(
-                               "<div class=\"successbox\">\n$1\n</div>",
-                               'changepassword-success'
-                       );
-                       $this->getOutput()->returnToMain();
-               } else {
-                       $request = $this->getRequest();
-                       LoginForm::clearLoginToken();
-                       $token = LoginForm::getLoginToken()->toString();
-                       $data = [
-                               'action' => 'submitlogin',
-                               'wpName' => $this->mUserName,
-                               'wpDomain' => $this->mDomain,
-                               'wpLoginToken' => $token,
-                               'wpPassword' => $request->getVal( 'wpNewPassword' ),
-                       ] + $request->getValues( 'wpRemember', 'returnto', 'returntoquery' );
-                       $login = new LoginForm( new DerivativeRequest( $request, $data, true ) );
-                       $login->setContext( $this->getContext() );
-                       $login->execute( null );
-               }
-       }
-
-       /**
-        * Checks the new password if it meets the requirements for passwords and set
-        * it as a current password, otherwise set the passed Status object to fatal
-        * and doesn't change anything
-        *
-        * @param string $oldpass The current (temporary) password.
-        * @param string $newpass The password to set.
-        * @param string $retype The string of the retype password field to check with newpass
-        * @return Status
-        */
-       protected function attemptReset( $oldpass, $newpass, $retype ) {
-               $isSelf = ( $this->mUserName === $this->getUser()->getName() );
-               if ( $isSelf ) {
-                       $user = $this->getUser();
-               } else {
-                       $user = User::newFromName( $this->mUserName );
-               }
-
-               if ( !$user || $user->isAnon() ) {
-                       return Status::newFatal( $this->msg( 'nosuchusershort', $this->mUserName ) );
-               }
-
-               if ( $newpass !== $retype ) {
-                       Hooks::run( 'PrefsPasswordAudit', [ $user, $newpass, 'badretype' ] );
-                       return Status::newFatal( $this->msg( 'badretype' ) );
-               }
-
-               $throttleInfo = LoginForm::incrementLoginThrottle( $this->mUserName );
-               if ( $throttleInfo ) {
-                       return Status::newFatal( $this->msg( 'changepassword-throttled' )
-                               ->durationParams( $throttleInfo['wait'] )
-                       );
-               }
-
-               // @todo Make these separate messages, since the message is written for both cases
-               if ( !$user->checkTemporaryPassword( $oldpass ) && !$user->checkPassword( $oldpass ) ) {
-                       Hooks::run( 'PrefsPasswordAudit', [ $user, $newpass, 'wrongpassword' ] );
-                       return Status::newFatal( $this->msg( 'resetpass-wrong-oldpass' ) );
-               }
-
-               // User is resetting their password to their old password
-               if ( $oldpass === $newpass ) {
-                       return Status::newFatal( $this->msg( 'resetpass-recycled' ) );
-               }
-
-               // Do AbortChangePassword after checking mOldpass, so we don't leak information
-               // by possibly aborting a new password before verifying the old password.
-               $abortMsg = 'resetpass-abort-generic';
-               if ( !Hooks::run( 'AbortChangePassword', [ $user, $oldpass, $newpass, &$abortMsg ] ) ) {
-                       Hooks::run( 'PrefsPasswordAudit', [ $user, $newpass, 'abortreset' ] );
-                       return Status::newFatal( $this->msg( $abortMsg ) );
-               }
-
-               // Please reset throttle for successful logins, thanks!
-               LoginForm::clearLoginThrottle( $this->mUserName );
-
-               try {
-                       $user->setPassword( $newpass );
-                       Hooks::run( 'PrefsPasswordAudit', [ $user, $newpass, 'success' ] );
-               } catch ( PasswordError $e ) {
-                       Hooks::run( 'PrefsPasswordAudit', [ $user, $newpass, 'error' ] );
-                       return Status::newFatal( new RawMessage( $e->getMessage() ) );
-               }
-
-               if ( $isSelf ) {
-                       // This is needed to keep the user connected since
-                       // changing the password also modifies the user's token.
-                       $remember = $this->getRequest()->getCookie( 'Token' ) !== null;
-                       $user->setCookies( null, null, $remember );
-               }
-               $user->saveSettings();
-               $this->resetPasswordExpiration( $user );
-               return Status::newGood();
-       }
-
-       public function requiresUnblock() {
-               return false;
-       }
-
-       protected function getGroupName() {
-               return 'users';
-       }
-
-       /**
-        * For resetting user password expiration, until AuthManager comes along
-        * @param User $user
-        */
-       private function resetPasswordExpiration( User $user ) {
-               global $wgPasswordExpirationDays;
-               $newExpire = null;
-               if ( $wgPasswordExpirationDays ) {
-                       $newExpire = wfTimestamp(
-                               TS_MW,
-                               time() + ( $wgPasswordExpirationDays * 24 * 3600 )
-                       );
-               }
-               // Give extensions a chance to force an expiration
-               Hooks::run( 'ResetPasswordExpiration', [ $this, &$newExpire ] );
-               $dbw = wfGetDB( DB_MASTER );
-               $dbw->update(
-                       'user',
-                       [ 'user_password_expires' => $dbw->timestampOrNull( $newExpire ) ],
-                       [ 'user_id' => $user->getId() ],
-                       __METHOD__
-               );
-       }
-
-       protected function getDisplayFormat() {
-               return 'ooui';
-       }
-}
diff --git a/includes/specials/pre-authmanager/SpecialCreateAccount.php b/includes/specials/pre-authmanager/SpecialCreateAccount.php
deleted file mode 100644 (file)
index 14f70b5..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-<?php
-/**
- * Redirect page: Special:CreateAccount --> Special:UserLogin/signup.
- *
- * 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 SpecialPage
- */
-
-/**
- * Redirect page: Special:CreateAccount --> Special:UserLogin/signup.
- * @todo FIXME: This (and the rest of the login frontend) needs to die a horrible painful death
- *
- * @ingroup SpecialPage
- */
-class SpecialCreateAccountPreAuthManager extends SpecialRedirectToSpecial {
-       function __construct() {
-               parent::__construct(
-                       'CreateAccount',
-                       'Userlogin',
-                       'signup',
-                       [ 'returnto', 'returntoquery', 'uselang' ]
-               );
-       }
-
-       public function doesWrites() {
-               return true;
-       }
-
-       // No reason to hide this link on Special:Specialpages
-       public function isListed() {
-               return true;
-       }
-
-       public function isRestricted() {
-               return !User::groupHasPermission( '*', 'createaccount' );
-       }
-
-       public function userCanExecute( User $user ) {
-               return $user->isAllowed( 'createaccount' );
-       }
-
-       protected function getGroupName() {
-               return 'login';
-       }
-}
diff --git a/includes/specials/pre-authmanager/SpecialPasswordReset.php b/includes/specials/pre-authmanager/SpecialPasswordReset.php
deleted file mode 100644 (file)
index e8719a7..0000000
+++ /dev/null
@@ -1,378 +0,0 @@
-<?php
-/**
- * Implements Special:PasswordReset
- *
- * 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 SpecialPage
- */
-
-/**
- * Special page for requesting a password reset email
- *
- * @ingroup SpecialPage
- */
-class SpecialPasswordResetPreAuthManager extends FormSpecialPage {
-       /**
-        * @var Message
-        */
-       private $email;
-
-       /**
-        * @var User
-        */
-       private $firstUser;
-
-       /**
-        * @var Status
-        */
-       private $result;
-
-       /**
-        * @var string $method Identifies which password reset field was specified by the user.
-        */
-       private $method;
-
-       public function __construct() {
-               parent::__construct( 'PasswordReset', 'editmyprivateinfo' );
-       }
-
-       public function doesWrites() {
-               return true;
-       }
-
-       public function userCanExecute( User $user ) {
-               return $this->canChangePassword( $user ) === true && parent::userCanExecute( $user );
-       }
-
-       public function checkExecutePermissions( User $user ) {
-               $error = $this->canChangePassword( $user );
-               if ( is_string( $error ) ) {
-                       throw new ErrorPageError( 'internalerror', $error );
-               } elseif ( !$error ) {
-                       throw new ErrorPageError( 'internalerror', 'resetpass_forbidden' );
-               }
-
-               parent::checkExecutePermissions( $user );
-       }
-
-       protected function getFormFields() {
-               global $wgAuth;
-               $resetRoutes = $this->getConfig()->get( 'PasswordResetRoutes' );
-               $a = [];
-               if ( isset( $resetRoutes['username'] ) && $resetRoutes['username'] ) {
-                       $a['Username'] = [
-                               'type' => 'text',
-                               'label-message' => 'passwordreset-username',
-                       ];
-
-                       if ( $this->getUser()->isLoggedIn() ) {
-                               $a['Username']['default'] = $this->getUser()->getName();
-                       }
-               }
-
-               if ( isset( $resetRoutes['email'] ) && $resetRoutes['email'] ) {
-                       $a['Email'] = [
-                               'type' => 'email',
-                               'label-message' => 'passwordreset-email',
-                       ];
-               }
-
-               if ( isset( $resetRoutes['domain'] ) && $resetRoutes['domain'] ) {
-                       $domains = $wgAuth->domainList();
-                       $a['Domain'] = [
-                               'type' => 'select',
-                               'options' => $domains,
-                               'label-message' => 'passwordreset-domain',
-                       ];
-               }
-
-               if ( $this->getUser()->isAllowed( 'passwordreset' ) ) {
-                       $a['Capture'] = [
-                               'type' => 'check',
-                               'label-message' => 'passwordreset-capture',
-                               'help-message' => 'passwordreset-capture-help',
-                       ];
-               }
-
-               return $a;
-       }
-
-       protected function getDisplayFormat() {
-               return 'ooui';
-       }
-
-       public function alterForm( HTMLForm $form ) {
-               $resetRoutes = $this->getConfig()->get( 'PasswordResetRoutes' );
-
-               $form->addHiddenFields( $this->getRequest()->getValues( 'returnto', 'returntoquery' ) );
-
-               $i = 0;
-               if ( isset( $resetRoutes['username'] ) && $resetRoutes['username'] ) {
-                       $i++;
-               }
-               if ( isset( $resetRoutes['email'] ) && $resetRoutes['email'] ) {
-                       $i++;
-               }
-               if ( isset( $resetRoutes['domain'] ) && $resetRoutes['domain'] ) {
-                       $i++;
-               }
-
-               $message = ( $i > 1 ) ? 'passwordreset-text-many' : 'passwordreset-text-one';
-
-               $form->setHeaderText( $this->msg( $message, $i )->parseAsBlock() );
-               $form->setSubmitTextMsg( 'mailmypassword' );
-       }
-
-       /**
-        * Process the form.  At this point we know that the user passes all the criteria in
-        * userCanExecute(), and if the data array contains 'Username', etc, then Username
-        * resets are allowed.
-        * @param array $data
-        * @throws MWException
-        * @throws ThrottledError|PermissionsError
-        * @return bool|array
-        */
-       public function onSubmit( array $data ) {
-               global $wgAuth, $wgMinimalPasswordLength;
-
-               if ( isset( $data['Domain'] ) ) {
-                       if ( $wgAuth->validDomain( $data['Domain'] ) ) {
-                               $wgAuth->setDomain( $data['Domain'] );
-                       } else {
-                               $wgAuth->setDomain( 'invaliddomain' );
-                       }
-               }
-
-               if ( isset( $data['Capture'] ) && !$this->getUser()->isAllowed( 'passwordreset' ) ) {
-                       // The user knows they don't have the passwordreset permission,
-                       // but they tried to spoof the form. That's naughty
-                       throw new PermissionsError( 'passwordreset' );
-               }
-
-               /**
-                * @var $firstUser User
-                * @var $users User[]
-                */
-
-               if ( isset( $data['Username'] ) && $data['Username'] !== '' ) {
-                       $method = 'username';
-                       $users = [ User::newFromName( $data['Username'] ) ];
-               } elseif ( isset( $data['Email'] )
-                       && $data['Email'] !== ''
-                       && Sanitizer::validateEmail( $data['Email'] )
-               ) {
-                       $method = 'email';
-                       $res = wfGetDB( DB_SLAVE )->select(
-                               'user',
-                               User::selectFields(),
-                               [ 'user_email' => $data['Email'] ],
-                               __METHOD__
-                       );
-
-                       if ( $res ) {
-                               $users = [];
-
-                               foreach ( $res as $row ) {
-                                       $users[] = User::newFromRow( $row );
-                               }
-                       } else {
-                               // Some sort of database error, probably unreachable
-                               throw new MWException( 'Unknown database error in ' . __METHOD__ );
-                       }
-               } else {
-                       // The user didn't supply any data
-                       return false;
-               }
-
-               // Check for hooks (captcha etc), and allow them to modify the users list
-               $error = [];
-               if ( !Hooks::run( 'SpecialPasswordResetOnSubmit', [ &$users, $data, &$error ] ) ) {
-                       return [ $error ];
-               }
-
-               $this->method = $method;
-
-               if ( count( $users ) == 0 ) {
-                       if ( $method == 'email' ) {
-                               // Don't reveal whether or not an email address is in use
-                               return true;
-                       } else {
-                               return [ 'noname' ];
-                       }
-               }
-
-               $firstUser = $users[0];
-
-               if ( !$firstUser instanceof User || !$firstUser->getId() ) {
-                       // Don't parse username as wikitext (bug 65501)
-                       return [ [ 'nosuchuser', wfEscapeWikiText( $data['Username'] ) ] ];
-               }
-
-               // Check against the rate limiter
-               if ( $this->getUser()->pingLimiter( 'mailpassword' ) ) {
-                       throw new ThrottledError;
-               }
-
-               // Check against password throttle
-               foreach ( $users as $user ) {
-                       if ( $user->isPasswordReminderThrottled() ) {
-
-                               # Round the time in hours to 3 d.p., in case someone is specifying
-                               # minutes or seconds.
-                               return [ [
-                                       'throttled-mailpassword',
-                                       round( $this->getConfig()->get( 'PasswordReminderResendTime' ), 3 )
-                               ] ];
-                       }
-               }
-
-               // All the users will have the same email address
-               if ( $firstUser->getEmail() == '' ) {
-                       // This won't be reachable from the email route, so safe to expose the username
-                       return [ [ 'noemail', wfEscapeWikiText( $firstUser->getName() ) ] ];
-               }
-
-               // We need to have a valid IP address for the hook, but per bug 18347, we should
-               // send the user's name if they're logged in.
-               $ip = $this->getRequest()->getIP();
-               if ( !$ip ) {
-                       return [ 'badipaddress' ];
-               }
-               $caller = $this->getUser();
-               Hooks::run( 'User::mailPasswordInternal', [ &$caller, &$ip, &$firstUser ] );
-               $username = $caller->getName();
-               $msg = IP::isValid( $username )
-                       ? 'passwordreset-emailtext-ip'
-                       : 'passwordreset-emailtext-user';
-
-               // Send in the user's language; which should hopefully be the same
-               $userLanguage = $firstUser->getOption( 'language' );
-
-               $passwords = [];
-               foreach ( $users as $user ) {
-                       $password = PasswordFactory::generateRandomPasswordString( $wgMinimalPasswordLength );
-                       $user->setNewpassword( $password );
-                       $user->saveSettings();
-                       $passwords[] = $this->msg( 'passwordreset-emailelement', $user->getName(), $password )
-                               ->inLanguage( $userLanguage )->text(); // We'll escape the whole thing later
-               }
-               $passwordBlock = implode( "\n\n", $passwords );
-
-               $this->email = $this->msg( $msg )->inLanguage( $userLanguage );
-               $this->email->params(
-                       $username,
-                       $passwordBlock,
-                       count( $passwords ),
-                       '<' . Title::newMainPage()->getCanonicalURL() . '>',
-                       round( $this->getConfig()->get( 'NewPasswordExpiry' ) / 86400 )
-               );
-
-               $title = $this->msg( 'passwordreset-emailtitle' )->inLanguage( $userLanguage );
-
-               $this->result = $firstUser->sendMail( $title->text(), $this->email->text() );
-
-               if ( isset( $data['Capture'] ) && $data['Capture'] ) {
-                       // Save the user, will be used if an error occurs when sending the email
-                       $this->firstUser = $firstUser;
-               } else {
-                       // Blank the email if the user is not supposed to see it
-                       $this->email = null;
-               }
-
-               if ( $this->result->isGood() ) {
-                       return true;
-               } elseif ( isset( $data['Capture'] ) && $data['Capture'] ) {
-                       // The email didn't send, but maybe they knew that and that's why they captured it
-                       return true;
-               } else {
-                       // @todo FIXME: The email wasn't sent, but we have already set
-                       // the password throttle timestamp, so they won't be able to try
-                       // again until it expires...  :(
-                       return [ [ 'mailerror', $this->result->getMessage() ] ];
-               }
-       }
-
-       public function onSuccess() {
-               if ( $this->getUser()->isAllowed( 'passwordreset' ) && $this->email != null ) {
-                       // @todo Logging
-
-                       if ( $this->result->isGood() ) {
-                               $this->getOutput()->addWikiMsg( 'passwordreset-emailsent-capture' );
-                       } else {
-                               $this->getOutput()->addWikiMsg( 'passwordreset-emailerror-capture',
-                                       $this->result->getMessage(), $this->firstUser->getName() );
-                       }
-
-                       $this->getOutput()->addHTML( Html::rawElement( 'pre', [], $this->email->escaped() ) );
-               }
-
-               if ( $this->method === 'email' ) {
-                       $this->getOutput()->addWikiMsg( 'passwordreset-emailsentemail' );
-               } else {
-                       $this->getOutput()->addWikiMsg( 'passwordreset-emailsentusername' );
-               }
-
-               $this->getOutput()->returnToMain();
-       }
-
-       protected function canChangePassword( User $user ) {
-               global $wgAuth;
-               $resetRoutes = $this->getConfig()->get( 'PasswordResetRoutes' );
-
-               // Maybe password resets are disabled, or there are no allowable routes
-               if ( !is_array( $resetRoutes ) ||
-                       !in_array( true, array_values( $resetRoutes ) )
-               ) {
-                       return 'passwordreset-disabled';
-               }
-
-               // Maybe the external auth plugin won't allow local password changes
-               if ( !$wgAuth->allowPasswordChange() ) {
-                       return 'resetpass_forbidden';
-               }
-
-               // Maybe email features have been disabled
-               if ( !$this->getConfig()->get( 'EnableEmail' ) ) {
-                       return 'passwordreset-emaildisabled';
-               }
-
-               // Maybe the user is blocked (check this here rather than relying on the parent
-               // method as we have a more specific error message to use here
-               if ( $user->isBlocked() ) {
-                       return 'blocked-mailpassword';
-               }
-
-               return true;
-       }
-
-       /**
-        * Hide the password reset page if resets are disabled.
-        * @return bool
-        */
-       function isListed() {
-               if ( $this->canChangePassword( $this->getUser() ) === true ) {
-                       return parent::isListed();
-               }
-
-               return false;
-       }
-
-       protected function getGroupName() {
-               return 'users';
-       }
-}
diff --git a/includes/specials/pre-authmanager/SpecialUserlogin.php b/includes/specials/pre-authmanager/SpecialUserlogin.php
deleted file mode 100644 (file)
index 09132f2..0000000
+++ /dev/null
@@ -1,1847 +0,0 @@
-<?php
-/**
- * Implements Special:UserLogin
- *
- * 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 SpecialPage
- */
-use MediaWiki\Logger\LoggerFactory;
-use Psr\Log\LogLevel;
-use MediaWiki\Session\SessionManager;
-
-/**
- * Implements Special:UserLogin
- *
- * @ingroup SpecialPage
- */
-class LoginFormPreAuthManager extends SpecialPage {
-       const SUCCESS = 0;
-       const NO_NAME = 1;
-       const ILLEGAL = 2;
-       const WRONG_PLUGIN_PASS = 3;
-       const NOT_EXISTS = 4;
-       const WRONG_PASS = 5;
-       const EMPTY_PASS = 6;
-       const RESET_PASS = 7;
-       const ABORTED = 8;
-       const CREATE_BLOCKED = 9;
-       const THROTTLED = 10;
-       const USER_BLOCKED = 11;
-       const NEED_TOKEN = 12;
-       const WRONG_TOKEN = 13;
-       const USER_MIGRATED = 14;
-
-       public static $statusCodes = [
-               self::SUCCESS => 'success',
-               self::NO_NAME => 'no_name',
-               self::ILLEGAL => 'illegal',
-               self::WRONG_PLUGIN_PASS => 'wrong_plugin_pass',
-               self::NOT_EXISTS => 'not_exists',
-               self::WRONG_PASS => 'wrong_pass',
-               self::EMPTY_PASS => 'empty_pass',
-               self::RESET_PASS => 'reset_pass',
-               self::ABORTED => 'aborted',
-               self::CREATE_BLOCKED => 'create_blocked',
-               self::THROTTLED => 'throttled',
-               self::USER_BLOCKED => 'user_blocked',
-               self::NEED_TOKEN => 'need_token',
-               self::WRONG_TOKEN => 'wrong_token',
-               self::USER_MIGRATED => 'user_migrated',
-       ];
-
-       /**
-        * Valid error and warning messages
-        *
-        * Special:Userlogin can show an error or warning message on the form when
-        * coming from another page. This is done via the ?error= or ?warning= GET
-        * parameters.
-        *
-        * This array is the list of valid message keys. All other values will be
-        * ignored.
-        *
-        * @since 1.24
-        * @var string[]
-        */
-       public static $validErrorMessages = [
-               'exception-nologin-text',
-               'watchlistanontext',
-               'changeemail-no-info',
-               'resetpass-no-info',
-               'confirmemail_needlogin',
-               'prefsnologintext2',
-       ];
-
-       public $mAbortLoginErrorMsg = null;
-       /**
-        * @var int How many seconds user is throttled for
-        * @since 1.27
-        */
-       public $mThrottleWait = '?';
-
-       protected $mUsername;
-       protected $mPassword;
-       protected $mRetype;
-       protected $mReturnTo;
-       protected $mCookieCheck;
-       protected $mPosted;
-       protected $mAction;
-       protected $mCreateaccount;
-       protected $mCreateaccountMail;
-       protected $mLoginattempt;
-       protected $mRemember;
-       protected $mEmail;
-       protected $mDomain;
-       protected $mLanguage;
-       protected $mSkipCookieCheck;
-       protected $mReturnToQuery;
-       protected $mToken;
-       protected $mStickHTTPS;
-       protected $mType;
-       protected $mReason;
-       protected $mRealName;
-       protected $mEntryError = '';
-       protected $mEntryErrorType = 'error';
-
-       private $mTempPasswordUsed;
-       private $mLoaded = false;
-       private $mSecureLoginUrl;
-
-       /** @var WebRequest */
-       private $mOverrideRequest = null;
-
-       /** @var WebRequest Effective request; set at the beginning of load */
-       private $mRequest = null;
-
-       /**
-        * @param WebRequest $request
-        */
-       public function __construct( $request = null ) {
-               global $wgUseMediaWikiUIEverywhere;
-               parent::__construct( 'Userlogin' );
-
-               $this->mOverrideRequest = $request;
-               // Override UseMediaWikiEverywhere to true, to force login and create form to use mw ui
-               $wgUseMediaWikiUIEverywhere = true;
-       }
-
-       public function doesWrites() {
-               return true;
-       }
-
-       /**
-        * Returns an array of all valid error messages.
-        *
-        * @return array
-        */
-       public static function getValidErrorMessages() {
-               static $messages = null;
-               if ( !$messages ) {
-                       $messages = self::$validErrorMessages;
-                       Hooks::run( 'LoginFormValidErrorMessages', [ &$messages ] );
-               }
-
-               return $messages;
-       }
-
-       /**
-        * Loader
-        */
-       function load() {
-               global $wgAuth, $wgHiddenPrefs, $wgEnableEmail;
-
-               if ( $this->mLoaded ) {
-                       return;
-               }
-               $this->mLoaded = true;
-
-               if ( $this->mOverrideRequest === null ) {
-                       $request = $this->getRequest();
-               } else {
-                       $request = $this->mOverrideRequest;
-               }
-               $this->mRequest = $request;
-
-               $this->mType = $request->getText( 'type' );
-               $this->mUsername = $request->getText( 'wpName' );
-               $this->mPassword = $request->getText( 'wpPassword' );
-               $this->mRetype = $request->getText( 'wpRetype' );
-               $this->mDomain = $request->getText( 'wpDomain' );
-               $this->mReason = $request->getText( 'wpReason' );
-               $this->mCookieCheck = $request->getVal( 'wpCookieCheck' );
-               $this->mPosted = $request->wasPosted();
-               $this->mCreateaccountMail = $request->getCheck( 'wpCreateaccountMail' )
-                       && $wgEnableEmail;
-               $this->mCreateaccount = $request->getCheck( 'wpCreateaccount' ) && !$this->mCreateaccountMail;
-               $this->mLoginattempt = $request->getCheck( 'wpLoginattempt' );
-               $this->mAction = $request->getVal( 'action' );
-               $this->mRemember = $request->getCheck( 'wpRemember' );
-               $this->mFromHTTP = $request->getBool( 'fromhttp', false )
-                       || $request->getBool( 'wpFromhttp', false );
-               $this->mStickHTTPS = ( !$this->mFromHTTP && $request->getProtocol() === 'https' )
-                       || $request->getBool( 'wpForceHttps', false );
-               $this->mLanguage = $request->getText( 'uselang' );
-               $this->mSkipCookieCheck = $request->getCheck( 'wpSkipCookieCheck' );
-               $this->mToken = $this->mType == 'signup'
-                       ? $request->getVal( 'wpCreateaccountToken' )
-                       : $request->getVal( 'wpLoginToken' );
-               $this->mReturnTo = $request->getVal( 'returnto', '' );
-               $this->mReturnToQuery = $request->getVal( 'returntoquery', '' );
-
-               // Show an error or warning passed on from a previous page
-               $entryError = $this->msg( $request->getVal( 'error', '' ) );
-               $entryWarning = $this->msg( $request->getVal( 'warning', '' ) );
-               // bc: provide login link as a parameter for messages where the translation
-               // was not updated
-               $loginreqlink = Linker::linkKnown(
-                       $this->getPageTitle(),
-                       $this->msg( 'loginreqlink' )->escaped(),
-                       [],
-                       [
-                               'returnto' => $this->mReturnTo,
-                               'returntoquery' => $this->mReturnToQuery,
-                               'uselang' => $this->mLanguage,
-                               'fromhttp' => $this->mFromHTTP ? '1' : '0',
-                       ]
-               );
-
-               // Only show valid error or warning messages.
-               if ( $entryError->exists()
-                       && in_array( $entryError->getKey(), self::getValidErrorMessages() )
-               ) {
-                       $this->mEntryErrorType = 'error';
-                       $this->mEntryError = $entryError->rawParams( $loginreqlink )->parse();
-
-               } elseif ( $entryWarning->exists()
-                       && in_array( $entryWarning->getKey(), self::getValidErrorMessages() )
-               ) {
-                       $this->mEntryErrorType = 'warning';
-                       $this->mEntryError = $entryWarning->rawParams( $loginreqlink )->parse();
-               }
-
-               if ( $wgEnableEmail ) {
-                       $this->mEmail = $request->getText( 'wpEmail' );
-               } else {
-                       $this->mEmail = '';
-               }
-               if ( !in_array( 'realname', $wgHiddenPrefs ) ) {
-                       $this->mRealName = $request->getText( 'wpRealName' );
-               } else {
-                       $this->mRealName = '';
-               }
-
-               if ( !$wgAuth->validDomain( $this->mDomain ) ) {
-                       $this->mDomain = $wgAuth->getDomain();
-               }
-               $wgAuth->setDomain( $this->mDomain );
-
-               # 1. When switching accounts, it sucks to get automatically logged out
-               # 2. Do not return to PasswordReset after a successful password change
-               #    but goto Wiki start page (Main_Page) instead ( bug 33997 )
-               $returnToTitle = Title::newFromText( $this->mReturnTo );
-               if ( is_object( $returnToTitle )
-                       && ( $returnToTitle->isSpecial( 'Userlogout' )
-                               || $returnToTitle->isSpecial( 'PasswordReset' ) )
-               ) {
-                       $this->mReturnTo = '';
-                       $this->mReturnToQuery = '';
-               }
-       }
-
-       function getDescription() {
-               if ( $this->mType === 'signup' ) {
-                       return $this->msg( 'createaccount' )->text();
-               } else {
-                       return $this->msg( 'login' )->text();
-               }
-       }
-
-       /**
-        * @param string|null $subPage
-        */
-       public function execute( $subPage ) {
-               // Make sure session is persisted
-               $session = SessionManager::getGlobalSession();
-               $session->persist();
-
-               $this->load();
-
-               // Check for [[Special:Userlogin/signup]]. This affects form display and
-               // page title.
-               if ( $subPage == 'signup' ) {
-                       $this->mType = 'signup';
-               }
-               $this->setHeaders();
-
-               // Make sure it's possible to log in
-               if ( $this->mType !== 'signup' && !$session->canSetUser() ) {
-                       throw new ErrorPageError(
-                               'cannotloginnow-title',
-                               'cannotloginnow-text',
-                               [
-                                       $session->getProvider()->describe( RequestContext::getMain()->getLanguage() )
-                               ]
-                       );
-               }
-
-               /**
-                * In the case where the user is already logged in, and was redirected to
-                * the login form from a page that requires login, do not show the login
-                * page. The use case scenario for this is when a user opens a large number
-                * of tabs, is redirected to the login page on all of them, and then logs
-                * in on one, expecting all the others to work properly.
-                *
-                * However, do show the form if it was visited intentionally (no 'returnto'
-                * is present). People who often switch between several accounts have grown
-                * accustomed to this behavior.
-                */
-               if (
-                       $this->mType !== 'signup' &&
-                       !$this->mPosted &&
-                       $this->getUser()->isLoggedIn() &&
-                       ( $this->mReturnTo !== '' || $this->mReturnToQuery !== '' )
-               ) {
-                       $this->successfulLogin();
-               }
-
-               // If logging in and not on HTTPS, either redirect to it or offer a link.
-               global $wgSecureLogin;
-               if ( $this->mRequest->getProtocol() !== 'https' ) {
-                       $title = $this->getFullTitle();
-                       $query = [
-                               'returnto' => $this->mReturnTo !== '' ? $this->mReturnTo : null,
-                               'returntoquery' => $this->mReturnToQuery !== '' ?
-                                       $this->mReturnToQuery : null,
-                               'title' => null,
-                               ( $this->mEntryErrorType === 'error' ? 'error' : 'warning' ) => $this->mEntryError,
-                       ] + $this->mRequest->getQueryValues();
-                       $url = $title->getFullURL( $query, false, PROTO_HTTPS );
-                       if ( $wgSecureLogin
-                               && wfCanIPUseHTTPS( $this->getRequest()->getIP() )
-                               && !$this->mFromHTTP ) // Avoid infinite redirect
-                       {
-                               $url = wfAppendQuery( $url, 'fromhttp=1' );
-                               $this->getOutput()->redirect( $url );
-                               // Since we only do this redir to change proto, always vary
-                               $this->getOutput()->addVaryHeader( 'X-Forwarded-Proto' );
-
-                               return;
-                       } else {
-                               // A wiki without HTTPS login support should set $wgServer to
-                               // http://somehost, in which case the secure URL generated
-                               // above won't actually start with https://
-                               if ( substr( $url, 0, 8 ) === 'https://' ) {
-                                       $this->mSecureLoginUrl = $url;
-                               }
-                       }
-               }
-
-               if ( !is_null( $this->mCookieCheck ) ) {
-                       $this->onCookieRedirectCheck( $this->mCookieCheck );
-
-                       return;
-               } elseif ( $this->mPosted ) {
-                       if ( $this->mCreateaccount ) {
-                               $this->addNewAccount();
-
-                               return;
-                       } elseif ( $this->mCreateaccountMail ) {
-                               $this->addNewAccountMailPassword();
-
-                               return;
-                       } elseif ( ( 'submitlogin' == $this->mAction ) || $this->mLoginattempt ) {
-                               $this->processLogin();
-
-                               return;
-                       }
-               }
-               $this->mainLoginForm( $this->mEntryError, $this->mEntryErrorType );
-       }
-
-       /**
-        * @private
-        */
-       function addNewAccountMailPassword() {
-               if ( $this->mEmail == '' ) {
-                       $this->mainLoginForm( $this->msg( 'noemailcreate' )->escaped() );
-
-                       return;
-               }
-
-               $status = $this->addNewAccountInternal();
-               LoggerFactory::getInstance( 'authmanager' )->info(
-                       'Account creation attempt with mailed password',
-                       [ 'event' => 'accountcreation', 'status' => $status ]
-               );
-               if ( !$status->isGood() ) {
-                       $error = $status->getMessage();
-                       $this->mainLoginForm( $error->toString() );
-
-                       return;
-               }
-
-               /** @var User $u */
-               $u = $status->getValue();
-
-               // Wipe the initial password and mail a temporary one
-               $u->setPassword( null );
-               $u->saveSettings();
-               $result = $this->mailPasswordInternal( $u, false, 'createaccount-title', 'createaccount-text' );
-
-               Hooks::run( 'AddNewAccount', [ $u, true ] );
-               $u->addNewUserLogEntry( 'byemail', $this->mReason );
-
-               $out = $this->getOutput();
-               $out->setPageTitle( $this->msg( 'accmailtitle' ) );
-
-               if ( !$result->isGood() ) {
-                       $this->mainLoginForm( $this->msg( 'mailerror', $result->getWikiText() )->text() );
-               } else {
-                       $out->addWikiMsg( 'accmailtext', $u->getName(), $u->getEmail() );
-                       $this->executeReturnTo( 'success' );
-               }
-       }
-
-       /**
-        * @private
-        * @return bool
-        */
-       function addNewAccount() {
-               global $wgContLang, $wgUser, $wgEmailAuthentication, $wgLoginLanguageSelector;
-
-               # Create the account and abort if there's a problem doing so
-               $status = $this->addNewAccountInternal();
-               LoggerFactory::getInstance( 'authmanager' )->info( 'Account creation attempt', [
-                       'event' => 'accountcreation',
-                       'status' => $status,
-               ] );
-
-               if ( !$status->isGood() ) {
-                       $error = $status->getMessage();
-                       $this->mainLoginForm( $error->toString() );
-
-                       return false;
-               }
-
-               $u = $status->getValue();
-
-               # Only save preferences if the user is not creating an account for someone else.
-               if ( $this->getUser()->isAnon() ) {
-                       # If we showed up language selection links, and one was in use, be
-                       # smart (and sensible) and save that language as the user's preference
-                       if ( $wgLoginLanguageSelector && $this->mLanguage ) {
-                               $u->setOption( 'language', $this->mLanguage );
-                       } else {
-
-                               # Otherwise the user's language preference defaults to $wgContLang,
-                               # but it may be better to set it to their preferred $wgContLang variant,
-                               # based on browser preferences or URL parameters.
-                               $u->setOption( 'language', $wgContLang->getPreferredVariant() );
-                       }
-                       if ( $wgContLang->hasVariants() ) {
-                               $u->setOption( 'variant', $wgContLang->getPreferredVariant() );
-                       }
-               }
-
-               $out = $this->getOutput();
-
-               # Send out an email authentication message if needed
-               if ( $wgEmailAuthentication && Sanitizer::validateEmail( $u->getEmail() ) ) {
-                       $status = $u->sendConfirmationMail();
-                       if ( $status->isGood() ) {
-                               $out->addWikiMsg( 'confirmemail_oncreate' );
-                       } else {
-                               $out->addWikiText( $status->getWikiText( 'confirmemail_sendfailed' ) );
-                       }
-               }
-
-               # Save settings (including confirmation token)
-               $u->saveSettings();
-
-               # If not logged in, assume the new account as the current one and set
-               # session cookies then show a "welcome" message or a "need cookies"
-               # message as needed
-               if ( $this->getUser()->isAnon() ) {
-                       $u->setCookies();
-                       $wgUser = $u;
-                       // This should set it for OutputPage and the Skin
-                       // which is needed or the personal links will be
-                       // wrong.
-                       $this->getContext()->setUser( $u );
-                       Hooks::run( 'AddNewAccount', [ $u, false ] );
-                       $u->addNewUserLogEntry( 'create' );
-                       if ( $this->hasSessionCookie() ) {
-                               $this->successfulCreation();
-                       } else {
-                               $this->cookieRedirectCheck( 'new' );
-                       }
-               } else {
-                       # Confirm that the account was created
-                       $out->setPageTitle( $this->msg( 'accountcreated' ) );
-                       $out->addWikiMsg( 'accountcreatedtext', $u->getName() );
-                       $out->addReturnTo( $this->getPageTitle() );
-                       Hooks::run( 'AddNewAccount', [ $u, false ] );
-                       $u->addNewUserLogEntry( 'create2', $this->mReason );
-               }
-
-               return true;
-       }
-
-       /**
-        * Make a new user account using the loaded data.
-        * @private
-        * @throws PermissionsError|ReadOnlyError
-        * @return Status
-        */
-       public function addNewAccountInternal() {
-               global $wgAuth, $wgAccountCreationThrottle, $wgEmailConfirmToEdit;
-
-               // If the user passes an invalid domain, something is fishy
-               if ( !$wgAuth->validDomain( $this->mDomain ) ) {
-                       return Status::newFatal( 'wrongpassword' );
-               }
-
-               // If we are not allowing users to login locally, we should be checking
-               // to see if the user is actually able to authenticate to the authenti-
-               // cation server before they create an account (otherwise, they can
-               // create a local account and login as any domain user). We only need
-               // to check this for domains that aren't local.
-               if ( 'local' != $this->mDomain && $this->mDomain != '' ) {
-                       if (
-                               !$wgAuth->canCreateAccounts() &&
-                               (
-                                       !$wgAuth->userExists( $this->mUsername ) ||
-                                       !$wgAuth->authenticate( $this->mUsername, $this->mPassword )
-                               )
-                       ) {
-                               return Status::newFatal( 'wrongpassword' );
-                       }
-               }
-
-               if ( wfReadOnly() ) {
-                       throw new ReadOnlyError;
-               }
-
-               # Request forgery checks.
-               $token = self::getCreateaccountToken();
-               if ( $token->wasNew() ) {
-                       return Status::newFatal( 'nocookiesfornew' );
-               }
-
-               # The user didn't pass a createaccount token
-               if ( !$this->mToken ) {
-                       return Status::newFatal( 'sessionfailure' );
-               }
-
-               # Validate the createaccount token
-               if ( !$token->match( $this->mToken ) ) {
-                       return Status::newFatal( 'sessionfailure' );
-               }
-
-               # Check permissions
-               $currentUser = $this->getUser();
-               $creationBlock = $currentUser->isBlockedFromCreateAccount();
-               if ( !$currentUser->isAllowed( 'createaccount' ) ) {
-                       throw new PermissionsError( 'createaccount' );
-               } elseif ( $creationBlock instanceof Block ) {
-                       // Throws an ErrorPageError.
-                       $this->userBlockedMessage( $creationBlock );
-
-                       // This should never be reached.
-                       return false;
-               }
-
-               # Include checks that will include GlobalBlocking (Bug 38333)
-               $permErrors = $this->getPageTitle()->getUserPermissionsErrors(
-                       'createaccount',
-                       $currentUser,
-                       true
-               );
-
-               if ( count( $permErrors ) ) {
-                       throw new PermissionsError( 'createaccount', $permErrors );
-               }
-
-               $ip = $this->getRequest()->getIP();
-               if ( $currentUser->isDnsBlacklisted( $ip, true /* check $wgProxyWhitelist */ ) ) {
-                       return Status::newFatal( 'sorbs_create_account_reason' );
-               }
-
-               # Now create a dummy user ($u) and check if it is valid
-               $u = User::newFromName( $this->mUsername, 'creatable' );
-               if ( !$u ) {
-                       return Status::newFatal( 'noname' );
-               }
-
-               $cache = ObjectCache::getLocalClusterInstance();
-               # Make sure the user does not exist already
-               $lock = $cache->getScopedLock( $cache->makeGlobalKey( 'account', md5( $this->mUsername ) ) );
-               if ( !$lock ) {
-                       return Status::newFatal( 'usernameinprogress' );
-               } elseif ( $u->idForName( User::READ_LOCKING ) ) {
-                       return Status::newFatal( 'userexists' );
-               }
-
-               if ( $this->mCreateaccountMail ) {
-                       # do not force a password for account creation by email
-                       # set invalid password, it will be replaced later by a random generated password
-                       $this->mPassword = null;
-               } else {
-                       if ( $this->mPassword !== $this->mRetype ) {
-                               return Status::newFatal( 'badretype' );
-                       }
-
-                       # check for password validity, return a fatal Status if invalid
-                       $validity = $u->checkPasswordValidity( $this->mPassword, 'create' );
-                       if ( !$validity->isGood() ) {
-                               $validity->ok = false; // make sure this Status is fatal
-                               return $validity;
-                       }
-               }
-
-               # if you need a confirmed email address to edit, then obviously you
-               # need an email address.
-               if ( $wgEmailConfirmToEdit && strval( $this->mEmail ) === '' ) {
-                       return Status::newFatal( 'noemailtitle' );
-               }
-
-               if ( strval( $this->mEmail ) !== '' && !Sanitizer::validateEmail( $this->mEmail ) ) {
-                       return Status::newFatal( 'invalidemailaddress' );
-               }
-
-               # Set some additional data so the AbortNewAccount hook can be used for
-               # more than just username validation
-               $u->setEmail( $this->mEmail );
-               $u->setRealName( $this->mRealName );
-
-               $abortError = '';
-               $abortStatus = null;
-               if ( !Hooks::run( 'AbortNewAccount', [ $u, &$abortError, &$abortStatus ] ) ) {
-                       // Hook point to add extra creation throttles and blocks
-                       wfDebug( "LoginForm::addNewAccountInternal: a hook blocked creation\n" );
-                       if ( $abortStatus === null ) {
-                               // Report back the old string as a raw message status.
-                               // This will report the error back as 'createaccount-hook-aborted'
-                               // with the given string as the message.
-                               // To return a different error code, return a Status object.
-                               $abortError = new Message( 'createaccount-hook-aborted', [ $abortError ] );
-                               $abortError->text();
-
-                               return Status::newFatal( $abortError );
-                       } else {
-                               // For MediaWiki 1.23+ and updated hooks, return the Status object
-                               // returned from the hook.
-                               return $abortStatus;
-                       }
-               }
-
-               // Hook point to check for exempt from account creation throttle
-               if ( !Hooks::run( 'ExemptFromAccountCreationThrottle', [ $ip ] ) ) {
-                       wfDebug( "LoginForm::exemptFromAccountCreationThrottle: a hook " .
-                               "allowed account creation w/o throttle\n" );
-               } else {
-                       if ( ( $wgAccountCreationThrottle && $currentUser->isPingLimitable() ) ) {
-                               $key = wfGlobalCacheKey( 'acctcreate', 'ip', $ip );
-                               $value = $cache->get( $key );
-                               if ( !$value ) {
-                                       $cache->set( $key, 0, $cache::TTL_DAY );
-                               }
-                               if ( $value >= $wgAccountCreationThrottle ) {
-                                       return Status::newFatal( 'acct_creation_throttle_hit', $wgAccountCreationThrottle );
-                               }
-                               $cache->incr( $key );
-                       }
-               }
-
-               if ( !$wgAuth->addUser( $u, $this->mPassword, $this->mEmail, $this->mRealName ) ) {
-                       return Status::newFatal( 'externaldberror' );
-               }
-
-               self::clearCreateaccountToken();
-
-               return $this->initUser( $u, false );
-       }
-
-       /**
-        * Actually add a user to the database.
-        * Give it a User object that has been initialised with a name.
-        *
-        * @param User $u
-        * @param bool $autocreate True if this is an autocreation via auth plugin
-        * @return Status Status object, with the User object in the value member on success
-        * @private
-        */
-       function initUser( $u, $autocreate ) {
-               global $wgAuth;
-
-               $status = $u->addToDatabase();
-               if ( !$status->isOK() ) {
-                       return $status;
-               }
-
-               if ( $wgAuth->allowPasswordChange() ) {
-                       $u->setPassword( $this->mPassword );
-               }
-
-               $u->setEmail( $this->mEmail );
-               $u->setRealName( $this->mRealName );
-               $u->setToken();
-
-               Hooks::run( 'LocalUserCreated', [ $u, $autocreate ] );
-               $oldUser = $u;
-               $wgAuth->initUser( $u, $autocreate );
-               if ( $oldUser !== $u ) {
-                       wfWarn( get_class( $wgAuth ) . '::initUser() replaced the user object' );
-               }
-
-               $u->saveSettings();
-
-               // Update user count
-               DeferredUpdates::addUpdate( new SiteStatsUpdate( 0, 0, 0, 0, 1 ) );
-
-               // Watch user's userpage and talk page
-               $u->addWatch( $u->getUserPage(), User::IGNORE_USER_RIGHTS );
-
-               return Status::newGood( $u );
-       }
-
-       /**
-        * Internally authenticate the login request.
-        *
-        * This may create a local account as a side effect if the
-        * authentication plugin allows transparent local account
-        * creation.
-        * @return int
-        */
-       public function authenticateUserData() {
-               global $wgUser, $wgAuth;
-
-               $this->load();
-
-               if ( $this->mUsername == '' ) {
-                       return self::NO_NAME;
-               }
-
-               // We require a login token to prevent login CSRF
-               // Handle part of this before incrementing the throttle so
-               // token-less login attempts don't count towards the throttle
-               // but wrong-token attempts do.
-
-               // If the user doesn't have a login token yet, set one.
-               $token = self::getLoginToken();
-               if ( $token->wasNew() ) {
-                       return self::NEED_TOKEN;
-               }
-               // If the user didn't pass a login token, tell them we need one
-               if ( !$this->mToken ) {
-                       return self::NEED_TOKEN;
-               }
-
-               $throttleCount = self::incrementLoginThrottle( $this->mUsername );
-               if ( $throttleCount ) {
-                       $this->mThrottleWait = $throttleCount['wait'];
-                       return self::THROTTLED;
-               }
-
-               // Validate the login token
-               if ( !$token->match( $this->mToken ) ) {
-                       return self::WRONG_TOKEN;
-               }
-
-               // Load the current user now, and check to see if we're logging in as
-               // the same name. This is necessary because loading the current user
-               // (say by calling getName()) calls the UserLoadFromSession hook, which
-               // potentially creates the user in the database. Until we load $wgUser,
-               // checking for user existence using User::newFromName($name)->getId() below
-               // will effectively be using stale data.
-               if ( $this->getUser()->getName() === $this->mUsername ) {
-                       wfDebug( __METHOD__ . ": already logged in as {$this->mUsername}\n" );
-
-                       return self::SUCCESS;
-               }
-
-               $u = User::newFromName( $this->mUsername );
-               if ( $u === false ) {
-                       return self::ILLEGAL;
-               }
-
-               $msg = null;
-               // Give extensions a way to indicate the username has been updated,
-               // rather than telling the user the account doesn't exist.
-               if ( !Hooks::run( 'LoginUserMigrated', [ $u, &$msg ] ) ) {
-                       $this->mAbortLoginErrorMsg = $msg;
-                       return self::USER_MIGRATED;
-               }
-
-               if ( !User::isUsableName( $u->getName() ) ) {
-                       return self::ILLEGAL;
-               }
-
-               $isAutoCreated = false;
-               if ( $u->getId() == 0 ) {
-                       $status = $this->attemptAutoCreate( $u );
-                       if ( $status !== self::SUCCESS ) {
-                               return $status;
-                       } else {
-                               $isAutoCreated = true;
-                       }
-               } else {
-                       $u->load();
-               }
-
-               // Give general extensions, such as a captcha, a chance to abort logins
-               $abort = self::ABORTED;
-               if ( !Hooks::run( 'AbortLogin', [ $u, $this->mPassword, &$abort, &$msg ] ) ) {
-                       if ( !in_array( $abort, array_keys( self::$statusCodes ), true ) ) {
-                               throw new Exception( 'Invalid status code returned from AbortLogin hook: ' . $abort );
-                       }
-                       $this->mAbortLoginErrorMsg = $msg;
-                       return $abort;
-               }
-
-               global $wgBlockDisablesLogin;
-               if ( !$u->checkPassword( $this->mPassword ) ) {
-                       if ( $u->checkTemporaryPassword( $this->mPassword ) ) {
-                               /**
-                                * The e-mailed temporary password should not be used for actu-
-                                * al logins; that's a very sloppy habit, and insecure if an
-                                * attacker has a few seconds to click "search" on someone's
-                                * open mail reader.
-                                *
-                                * Allow it to be used only to reset the password a single time
-                                * to a new value, which won't be in the user's e-mail ar-
-                                * chives.
-                                *
-                                * For backwards compatibility, we'll still recognize it at the
-                                * login form to minimize surprises for people who have been
-                                * logging in with a temporary password for some time.
-                                *
-                                * As a side-effect, we can authenticate the user's e-mail ad-
-                                * dress if it's not already done, since the temporary password
-                                * was sent via e-mail.
-                                */
-                               if ( !$u->isEmailConfirmed() && !wfReadOnly() ) {
-                                       $u->confirmEmail();
-                                       $u->saveSettings();
-                               }
-
-                               // At this point we just return an appropriate code/ indicating
-                               // that the UI should show a password reset form; bot inter-
-                               // faces etc will probably just fail cleanly here.
-                               $this->mAbortLoginErrorMsg = 'resetpass-temp-emailed';
-                               $this->mTempPasswordUsed = true;
-                               $retval = self::RESET_PASS;
-                       } else {
-                               $retval = ( $this->mPassword == '' ) ? self::EMPTY_PASS : self::WRONG_PASS;
-                       }
-               } elseif ( $wgBlockDisablesLogin && $u->isBlocked() ) {
-                       // If we've enabled it, make it so that a blocked user cannot login
-                       $retval = self::USER_BLOCKED;
-               } elseif ( $this->checkUserPasswordExpired( $u ) == 'hard' ) {
-                       // Force reset now, without logging in
-                       $retval = self::RESET_PASS;
-                       $this->mAbortLoginErrorMsg = 'resetpass-expired';
-               } else {
-                       Hooks::run( 'UserLoggedIn', [ $u ] );
-                       $oldUser = $u;
-                       $wgAuth->updateUser( $u );
-                       if ( $oldUser !== $u ) {
-                               wfWarn( get_class( $wgAuth ) . '::updateUser() replaced the user object' );
-                       }
-                       $wgUser = $u;
-                       // This should set it for OutputPage and the Skin
-                       // which is needed or the personal links will be
-                       // wrong.
-                       $this->getContext()->setUser( $u );
-
-                       // Please reset throttle for successful logins, thanks!
-                       self::clearLoginThrottle( $this->mUsername );
-
-                       if ( $isAutoCreated ) {
-                               // Must be run after $wgUser is set, for correct new user log
-                               Hooks::run( 'AuthPluginAutoCreate', [ $u ] );
-                       }
-
-                       $retval = self::SUCCESS;
-               }
-               Hooks::run( 'LoginAuthenticateAudit', [ $u, $this->mPassword, $retval ] );
-
-               return $retval;
-       }
-
-       /**
-        * Increment the login attempt throttle hit count for the (username,current IP)
-        * tuple unless the throttle was already reached.
-        *
-        * @since 1.27 Return value changed.
-        * @param string $username The user name
-        * @return bool|array false if below limit or an array if above limit
-        *   Array contains keys wait, count, and throttleIndex
-        */
-       public static function incrementLoginThrottle( $username ) {
-               global $wgPasswordAttemptThrottle, $wgRequest;
-               $canUsername = User::getCanonicalName( $username, 'usable' );
-               $username = $canUsername !== false ? $canUsername : $username;
-
-               $throttleCount = 0;
-               if ( is_array( $wgPasswordAttemptThrottle ) ) {
-                       $throttleConfig = $wgPasswordAttemptThrottle;
-                       if ( isset( $wgPasswordAttemptThrottle['count'] ) ) {
-                               // old style. Convert for backwards compat.
-                               $throttleConfig = [ $wgPasswordAttemptThrottle ];
-                       }
-                       foreach ( $throttleConfig as $index => $specificThrottle ) {
-                               if ( isset( $specificThrottle['allIPs'] ) ) {
-                                       $ip = 'All';
-                               } else {
-                                       $ip = $wgRequest->getIP();
-                               }
-                               $throttleKey = wfGlobalCacheKey( 'password-throttle',
-                                       $index, $ip, md5( $username )
-                               );
-                               $count = $specificThrottle['count'];
-                               $period = $specificThrottle['seconds'];
-
-                               $cache = ObjectCache::getLocalClusterInstance();
-                               $throttleCount = $cache->get( $throttleKey );
-                               if ( !$throttleCount ) {
-                                       $cache->add( $throttleKey, 1, $period ); // start counter
-                               } elseif ( $throttleCount < $count ) {
-                                       $cache->incr( $throttleKey );
-                               } elseif ( $throttleCount >= $count ) {
-                                       $logMsg = 'Login attempt rejected because logins to '
-                                               . '{acct} from IP {ip} have been throttled for '
-                                               . '{period} seconds due to {count} failed attempts';
-                                       // If we are hitting a throttle for >= 50 attempts,
-                                       // it is much more likely to be an attack than someone
-                                       // simply forgetting their password, so log it at a
-                                       // higher level.
-                                       $level = $count >= 50 ? LogLevel::WARNING : LogLevel::INFO;
-                                       // It should be noted that once the throttle is hit,
-                                       // every attempt to login will generate the log message
-                                       // until the throttle expires, not just the attempt that
-                                       // puts the throttle over the top.
-                                       LoggerFactory::getInstance( 'password-throttle' )->log(
-                                               $level,
-                                               $logMsg,
-                                               [
-                                                       'ip' => $ip,
-                                                       'period' => $period,
-                                                       'acct' => $username,
-                                                       'count' => $count,
-                                                       'throttleIdentifier' => $index,
-                                                       'method' => __METHOD__
-                                               ]
-                                       );
-
-                                       return [
-                                               'throttleIndex' => $index,
-                                               'wait' => $period,
-                                               'count' => $count
-                                       ];
-                               }
-                       }
-               }
-               return false;
-       }
-
-       /**
-        * Increment the login attempt throttle hit count for the (username,current IP)
-        * tuple unless the throttle was already reached.
-        *
-        * @deprecated Use LoginForm::incrementLoginThrottle instead
-        * @param string $username The user name
-        * @return bool|int true if above throttle, or 0 (prior to 1.27, returned current count)
-        */
-       public static function incLoginThrottle( $username ) {
-               wfDeprecated( __METHOD__, "1.27" );
-               $res = self::incrementLoginThrottle( $username );
-               return is_array( $res ) ? true : 0;
-       }
-
-       /**
-        * Clear the login attempt throttle hit count for the (username,current IP) tuple.
-        * @param string $username The user name
-        * @return void
-        */
-       public static function clearLoginThrottle( $username ) {
-               global $wgRequest, $wgPasswordAttemptThrottle;
-               $canUsername = User::getCanonicalName( $username, 'usable' );
-               $username = $canUsername !== false ? $canUsername : $username;
-
-               if ( is_array( $wgPasswordAttemptThrottle ) ) {
-                       $throttleConfig = $wgPasswordAttemptThrottle;
-                       if ( isset( $wgPasswordAttemptThrottle['count'] ) ) {
-                               // old style. Convert for backwards compat.
-                               $throttleConfig = [ $wgPasswordAttemptThrottle ];
-                       }
-                       foreach ( $throttleConfig as $index => $specificThrottle ) {
-                               if ( isset( $specificThrottle['allIPs'] ) ) {
-                                       $ip = 'All';
-                               } else {
-                                       $ip = $wgRequest->getIP();
-                               }
-                               $throttleKey = wfGlobalCacheKey( 'password-throttle', $index,
-                                       $ip, md5( $username )
-                               );
-                               ObjectCache::getLocalClusterInstance()->delete( $throttleKey );
-                       }
-               }
-       }
-
-       /**
-        * Attempt to automatically create a user on login. Only succeeds if there
-        * is an external authentication method which allows it.
-        *
-        * @param User $user
-        *
-        * @return int Status code
-        */
-       function attemptAutoCreate( $user ) {
-               global $wgAuth;
-
-               if ( $this->getUser()->isBlockedFromCreateAccount() ) {
-                       wfDebug( __METHOD__ . ": user is blocked from account creation\n" );
-
-                       return self::CREATE_BLOCKED;
-               }
-
-               if ( !$wgAuth->autoCreate() ) {
-                       return self::NOT_EXISTS;
-               }
-
-               if ( !$wgAuth->userExists( $user->getName() ) ) {
-                       wfDebug( __METHOD__ . ": user does not exist\n" );
-
-                       return self::NOT_EXISTS;
-               }
-
-               if ( !$wgAuth->authenticate( $user->getName(), $this->mPassword ) ) {
-                       wfDebug( __METHOD__ . ": \$wgAuth->authenticate() returned false, aborting\n" );
-
-                       return self::WRONG_PLUGIN_PASS;
-               }
-
-               $abortError = '';
-               if ( !Hooks::run( 'AbortAutoAccount', [ $user, &$abortError ] ) ) {
-                       // Hook point to add extra creation throttles and blocks
-                       wfDebug( "LoginForm::attemptAutoCreate: a hook blocked creation: $abortError\n" );
-                       $this->mAbortLoginErrorMsg = $abortError;
-
-                       return self::ABORTED;
-               }
-
-               wfDebug( __METHOD__ . ": creating account\n" );
-               $status = $this->initUser( $user, true );
-
-               if ( !$status->isOK() ) {
-                       $errors = $status->getErrorsByType( 'error' );
-                       $this->mAbortLoginErrorMsg = $errors[0]['message'];
-
-                       return self::ABORTED;
-               }
-
-               return self::SUCCESS;
-       }
-
-       function processLogin() {
-               global $wgLang, $wgSecureLogin, $wgInvalidPasswordReset;
-
-               $authRes = $this->authenticateUserData();
-               switch ( $authRes ) {
-                       case self::SUCCESS:
-                               # We've verified now, update the real record
-                               $user = $this->getUser();
-                               $user->touch();
-
-                               if ( $user->requiresHTTPS() ) {
-                                       $this->mStickHTTPS = true;
-                               }
-
-                               if ( $wgSecureLogin && !$this->mStickHTTPS ) {
-                                       $user->setCookies( $this->mRequest, false, $this->mRemember );
-                               } else {
-                                       $user->setCookies( $this->mRequest, null, $this->mRemember );
-                               }
-                               self::clearLoginToken();
-
-                               // Reset the throttle
-                               self::clearLoginThrottle( $this->mUsername );
-
-                               $request = $this->getRequest();
-                               if ( $this->hasSessionCookie() || $this->mSkipCookieCheck ) {
-                                       /* Replace the language object to provide user interface in
-                                        * correct language immediately on this first page load.
-                                        */
-                                       $code = $request->getVal( 'uselang', $user->getOption( 'language' ) );
-                                       $userLang = Language::factory( $code );
-                                       $wgLang = $userLang;
-                                       RequestContext::getMain()->setLanguage( $userLang );
-                                       $this->getContext()->setLanguage( $userLang );
-                                       // Reset SessionID on Successful login (bug 40995)
-                                       $this->renewSessionId();
-                                       if ( $this->checkUserPasswordExpired( $this->getUser() ) == 'soft' ) {
-                                               $this->resetLoginForm( $this->msg( 'resetpass-expired-soft' ) );
-                                       } elseif ( $wgInvalidPasswordReset
-                                               && !$user->isValidPassword( $this->mPassword )
-                                       ) {
-                                               $status = $user->checkPasswordValidity(
-                                                       $this->mPassword,
-                                                       'login'
-                                               );
-                                               $this->resetLoginForm(
-                                                       $status->getMessage( 'resetpass-validity-soft' )
-                                               );
-                                       } else {
-                                               $this->successfulLogin();
-                                       }
-                               } else {
-                                       $this->cookieRedirectCheck( 'login' );
-                               }
-                               break;
-
-                       case self::NEED_TOKEN:
-                               $error = $this->mAbortLoginErrorMsg ?: 'nocookiesforlogin';
-                               $this->mainLoginForm( $this->msg( $error )->parse() );
-                               break;
-                       case self::WRONG_TOKEN:
-                               $error = $this->mAbortLoginErrorMsg ?: 'sessionfailure';
-                               $this->mainLoginForm( $this->msg( $error )->text() );
-                               break;
-                       case self::NO_NAME:
-                       case self::ILLEGAL:
-                               $error = $this->mAbortLoginErrorMsg ?: 'noname';
-                               $this->mainLoginForm( $this->msg( $error )->text() );
-                               break;
-                       case self::WRONG_PLUGIN_PASS:
-                               $error = $this->mAbortLoginErrorMsg ?: 'wrongpassword';
-                               $this->mainLoginForm( $this->msg( $error )->text() );
-                               break;
-                       case self::NOT_EXISTS:
-                               if ( $this->getUser()->isAllowed( 'createaccount' ) ) {
-                                       $error = $this->mAbortLoginErrorMsg ?: 'nosuchuser';
-                                       $this->mainLoginForm( $this->msg( $error,
-                                               wfEscapeWikiText( $this->mUsername ) )->parse() );
-                               } else {
-                                       $error = $this->mAbortLoginErrorMsg ?: 'nosuchusershort';
-                                       $this->mainLoginForm( $this->msg( $error,
-                                               wfEscapeWikiText( $this->mUsername ) )->text() );
-                               }
-                               break;
-                       case self::WRONG_PASS:
-                               $error = $this->mAbortLoginErrorMsg ?: 'wrongpassword';
-                               $this->mainLoginForm( $this->msg( $error )->text() );
-                               break;
-                       case self::EMPTY_PASS:
-                               $error = $this->mAbortLoginErrorMsg ?: 'wrongpasswordempty';
-                               $this->mainLoginForm( $this->msg( $error )->text() );
-                               break;
-                       case self::RESET_PASS:
-                               $error = $this->mAbortLoginErrorMsg ?: 'resetpass_announce';
-                               $this->resetLoginForm( $this->msg( $error ) );
-                               break;
-                       case self::CREATE_BLOCKED:
-                               $this->userBlockedMessage( $this->getUser()->isBlockedFromCreateAccount() );
-                               break;
-                       case self::THROTTLED:
-                               $error = $this->mAbortLoginErrorMsg ?: 'login-throttled';
-                               $this->mainLoginForm( $this->msg( $error )
-                                       ->durationParams( $this->mThrottleWait )->text()
-                               );
-                               break;
-                       case self::USER_BLOCKED:
-                               $error = $this->mAbortLoginErrorMsg ?: 'login-userblocked';
-                               $this->mainLoginForm( $this->msg( $error, $this->mUsername )->escaped() );
-                               break;
-                       case self::ABORTED:
-                               $error = $this->mAbortLoginErrorMsg ?: 'login-abort-generic';
-                               $this->mainLoginForm( $this->msg( $error,
-                                               wfEscapeWikiText( $this->mUsername ) )->text() );
-                               break;
-                       case self::USER_MIGRATED:
-                               $error = $this->mAbortLoginErrorMsg ?: 'login-migrated-generic';
-                               $params = [];
-                               if ( is_array( $error ) ) {
-                                       $error = array_shift( $this->mAbortLoginErrorMsg );
-                                       $params = $this->mAbortLoginErrorMsg;
-                               }
-                               $this->mainLoginForm( $this->msg( $error, $params )->text() );
-                               break;
-                       default:
-                               throw new MWException( 'Unhandled case value' );
-               }
-
-               LoggerFactory::getInstance( 'authmanager' )->info( 'Login attempt', [
-                       'event' => 'login',
-                       'successful' => $authRes === self::SUCCESS,
-                       'status' => LoginForm::$statusCodes[$authRes],
-               ] );
-       }
-
-       /**
-        * Show the Special:ChangePassword form, with custom message
-        * @param Message $msg
-        */
-       protected function resetLoginForm( Message $msg ) {
-               // Allow hooks to explain this password reset in more detail
-               Hooks::run( 'LoginPasswordResetMessage', [ &$msg, $this->mUsername ] );
-               $reset = new SpecialChangePasswordPreAuthManager();
-               $derivative = new DerivativeContext( $this->getContext() );
-               $derivative->setTitle( $reset->getPageTitle() );
-               $reset->setContext( $derivative );
-               if ( !$this->mTempPasswordUsed ) {
-                       $reset->setOldPasswordMessage( 'oldpassword' );
-               }
-               $reset->setChangeMessage( $msg );
-               $reset->execute( null );
-       }
-
-       /**
-        * @param User $u
-        * @param bool $throttle
-        * @param string $emailTitle Message name of email title
-        * @param string $emailText Message name of email text
-        * @return Status
-        */
-       function mailPasswordInternal( $u, $throttle = true, $emailTitle = 'passwordremindertitle',
-               $emailText = 'passwordremindertext'
-       ) {
-               global $wgNewPasswordExpiry, $wgMinimalPasswordLength;
-
-               if ( $u->getEmail() == '' ) {
-                       return Status::newFatal( 'noemail', $u->getName() );
-               }
-               $ip = $this->getRequest()->getIP();
-               if ( !$ip ) {
-                       return Status::newFatal( 'badipaddress' );
-               }
-
-               $currentUser = $this->getUser();
-               Hooks::run( 'User::mailPasswordInternal', [ &$currentUser, &$ip, &$u ] );
-
-               $np = PasswordFactory::generateRandomPasswordString( $wgMinimalPasswordLength );
-               $u->setNewpassword( $np, $throttle );
-               $u->saveSettings();
-               $userLanguage = $u->getOption( 'language' );
-
-               $mainPage = Title::newMainPage();
-               $mainPageUrl = $mainPage->getCanonicalURL();
-
-               $m = $this->msg( $emailText, $ip, $u->getName(), $np, '<' . $mainPageUrl . '>',
-                       round( $wgNewPasswordExpiry / 86400 ) )->inLanguage( $userLanguage )->text();
-               $result = $u->sendMail( $this->msg( $emailTitle )->inLanguage( $userLanguage )->text(), $m );
-
-               return $result;
-       }
-
-       /**
-        * Run any hooks registered for logins, then HTTP redirect to
-        * $this->mReturnTo (or Main Page if that's undefined).  Formerly we had a
-        * nice message here, but that's really not as useful as just being sent to
-        * wherever you logged in from.  It should be clear that the action was
-        * successful, given the lack of error messages plus the appearance of your
-        * name in the upper right.
-        *
-        * @private
-        */
-       function successfulLogin() {
-               # Run any hooks; display injected HTML if any, else redirect
-               $currentUser = $this->getUser();
-               $injected_html = '';
-               $direct = RequestContext::getMain()->getRequest()->wasPosted();
-               Hooks::run( 'UserLoginComplete', [ &$currentUser, &$injected_html, $direct ] );
-
-               if ( $injected_html !== '' ) {
-                       $this->displaySuccessfulAction( 'success', $this->msg( 'loginsuccesstitle' ),
-                               'loginsuccess', $injected_html );
-               } else {
-                       $this->executeReturnTo( 'successredirect' );
-               }
-       }
-
-       /**
-        * Run any hooks registered for logins, then display a message welcoming
-        * the user.
-        *
-        * @private
-        */
-       function successfulCreation() {
-               # Run any hooks; display injected HTML
-               $currentUser = $this->getUser();
-               $injected_html = '';
-               $welcome_creation_msg = 'welcomecreation-msg';
-               $direct = RequestContext::getMain()->getRequest()->wasPosted();
-
-               Hooks::run( 'UserLoginComplete', [ &$currentUser, &$injected_html, $direct ] );
-
-               /**
-                * Let any extensions change what message is shown.
-                * @see https://www.mediawiki.org/wiki/Manual:Hooks/BeforeWelcomeCreation
-                * @since 1.18
-                */
-               Hooks::run( 'BeforeWelcomeCreation', [ &$welcome_creation_msg, &$injected_html ] );
-
-               $this->displaySuccessfulAction(
-                       'signup',
-                       $this->msg( 'welcomeuser', $this->getUser()->getName() ),
-                       $welcome_creation_msg, $injected_html
-               );
-       }
-
-       /**
-        * Display a "successful action" page.
-        *
-        * @param string $type Condition of return to; see `executeReturnTo`
-        * @param string|Message $title Page's title
-        * @param string $msgname
-        * @param string $injected_html
-        */
-       private function displaySuccessfulAction( $type, $title, $msgname, $injected_html ) {
-               $out = $this->getOutput();
-               $out->setPageTitle( $title );
-               if ( $msgname ) {
-                       $out->addWikiMsg( $msgname, wfEscapeWikiText( $this->getUser()->getName() ) );
-               }
-
-               $out->addHTML( $injected_html );
-
-               $this->executeReturnTo( $type );
-       }
-
-       /**
-        * Output a message that informs the user that they cannot create an account because
-        * there is a block on them or their IP which prevents account creation.  Note that
-        * User::isBlockedFromCreateAccount(), which gets this block, ignores the 'hardblock'
-        * setting on blocks (bug 13611).
-        * @param Block $block The block causing this error
-        * @throws ErrorPageError
-        */
-       function userBlockedMessage( Block $block ) {
-               # Let's be nice about this, it's likely that this feature will be used
-               # for blocking large numbers of innocent people, e.g. range blocks on
-               # schools. Don't blame it on the user. There's a small chance that it
-               # really is the user's fault, i.e. the username is blocked and they
-               # haven't bothered to log out before trying to create an account to
-               # evade it, but we'll leave that to their guilty conscience to figure
-               # out.
-               $errorParams = [
-                       $block->getTarget(),
-                       $block->mReason ? $block->mReason : $this->msg( 'blockednoreason' )->text(),
-                       $block->getByName()
-               ];
-
-               if ( $block->getType() === Block::TYPE_RANGE ) {
-                       $errorMessage = 'cantcreateaccount-range-text';
-                       $errorParams[] = $this->getRequest()->getIP();
-               } else {
-                       $errorMessage = 'cantcreateaccount-text';
-               }
-
-               throw new ErrorPageError(
-                       'cantcreateaccounttitle',
-                       $errorMessage,
-                       $errorParams
-               );
-       }
-
-       /**
-        * Add a "return to" link or redirect to it.
-        * Extensions can use this to reuse the "return to" logic after
-        * inject steps (such as redirection) into the login process.
-        *
-        * @param string $type One of the following:
-        *    - error: display a return to link ignoring $wgRedirectOnLogin
-        *    - signup: display a return to link using $wgRedirectOnLogin if needed
-        *    - success: display a return to link using $wgRedirectOnLogin if needed
-        *    - successredirect: send an HTTP redirect using $wgRedirectOnLogin if needed
-        * @param string $returnTo
-        * @param array|string $returnToQuery
-        * @param bool $stickHTTPs Keep redirect link on HTTPs
-        * @since 1.22
-        */
-       public function showReturnToPage(
-               $type, $returnTo = '', $returnToQuery = '', $stickHTTPs = false
-       ) {
-               $this->mReturnTo = $returnTo;
-               $this->mReturnToQuery = $returnToQuery;
-               $this->mStickHTTPS = $stickHTTPs;
-               $this->executeReturnTo( $type );
-       }
-
-       /**
-        * Add a "return to" link or redirect to it.
-        *
-        * @param string $type One of the following:
-        *    - error: display a return to link ignoring $wgRedirectOnLogin
-        *    - signup: display a return to link using $wgRedirectOnLogin if needed
-        *    - success: display a return to link using $wgRedirectOnLogin if needed
-        *    - successredirect: send an HTTP redirect using $wgRedirectOnLogin if needed
-        */
-       private function executeReturnTo( $type ) {
-               global $wgRedirectOnLogin, $wgSecureLogin;
-
-               if ( $type != 'error' && $wgRedirectOnLogin !== null ) {
-                       $returnTo = $wgRedirectOnLogin;
-                       $returnToQuery = [];
-               } else {
-                       $returnTo = $this->mReturnTo;
-                       $returnToQuery = wfCgiToArray( $this->mReturnToQuery );
-               }
-
-               // Allow modification of redirect behavior
-               Hooks::run( 'PostLoginRedirect', [ &$returnTo, &$returnToQuery, &$type ] );
-
-               $returnToTitle = Title::newFromText( $returnTo );
-               if ( !$returnToTitle ) {
-                       $returnToTitle = Title::newMainPage();
-               }
-
-               if ( $wgSecureLogin && !$this->mStickHTTPS ) {
-                       $options = [ 'http' ];
-                       $proto = PROTO_HTTP;
-               } elseif ( $wgSecureLogin ) {
-                       $options = [ 'https' ];
-                       $proto = PROTO_HTTPS;
-               } else {
-                       $options = [];
-                       $proto = PROTO_RELATIVE;
-               }
-
-               if ( $type == 'successredirect' ) {
-                       $redirectUrl = $returnToTitle->getFullURL( $returnToQuery, false, $proto );
-                       $this->getOutput()->redirect( $redirectUrl );
-               } else {
-                       $this->getOutput()->addReturnTo( $returnToTitle, $returnToQuery, null, $options );
-               }
-       }
-
-       /**
-        * @param string $msg
-        * @param string $msgtype
-        * @throws ErrorPageError
-        * @throws Exception
-        * @throws FatalError
-        * @throws MWException
-        * @throws PermissionsError
-        * @throws ReadOnlyError
-        * @private
-        */
-       function mainLoginForm( $msg, $msgtype = 'error' ) {
-               global $wgEnableEmail, $wgEnableUserEmail;
-               global $wgHiddenPrefs, $wgLoginLanguageSelector;
-               global $wgAuth, $wgEmailConfirmToEdit;
-               global $wgSecureLogin, $wgPasswordResetRoutes;
-               global $wgExtendedLoginCookieExpiration, $wgCookieExpiration;
-
-               $titleObj = $this->getPageTitle();
-               $user = $this->getUser();
-               $out = $this->getOutput();
-
-               if ( $this->mType == 'signup' ) {
-                       // Block signup here if in readonly. Keeps user from
-                       // going through the process (filling out data, etc)
-                       // and being informed later.
-                       $permErrors = $titleObj->getUserPermissionsErrors( 'createaccount', $user, true );
-                       if ( count( $permErrors ) ) {
-                               throw new PermissionsError( 'createaccount', $permErrors );
-                       } elseif ( $user->isBlockedFromCreateAccount() ) {
-                               $this->userBlockedMessage( $user->isBlockedFromCreateAccount() );
-
-                               return;
-                       } elseif ( wfReadOnly() ) {
-                               throw new ReadOnlyError;
-                       }
-               }
-
-               // Pre-fill username (if not creating an account, bug 44775).
-               if ( $this->mUsername == '' && $this->mType != 'signup' ) {
-                       if ( $user->isLoggedIn() ) {
-                               $this->mUsername = $user->getName();
-                       } else {
-                               $this->mUsername = $this->getRequest()->getSession()->suggestLoginUsername();
-                       }
-               }
-
-               // Generic styles and scripts for both login and signup form
-               $out->addModuleStyles( [
-                       'mediawiki.ui',
-                       'mediawiki.ui.button',
-                       'mediawiki.ui.checkbox',
-                       'mediawiki.ui.input',
-                       'mediawiki.special.userlogin.common.styles'
-               ] );
-
-               if ( $this->mType == 'signup' ) {
-                       // Additional styles and scripts for signup form
-                       $out->addModules( [
-                               'mediawiki.special.userlogin.signup.js'
-                       ] );
-                       $out->addModuleStyles( [
-                               'mediawiki.special.userlogin.signup.styles'
-                       ] );
-
-                       $template = new UsercreateTemplate( $this->getConfig() );
-
-                       // Must match number of benefits defined in messages
-                       $template->set( 'benefitCount', 3 );
-
-                       $q = 'action=submitlogin&type=signup';
-                       $linkq = 'type=login';
-               } else {
-                       // Additional styles for login form
-                       $out->addModuleStyles( [
-                               'mediawiki.special.userlogin.login.styles'
-                       ] );
-
-                       $template = new UserloginTemplate( $this->getConfig() );
-
-                       $q = 'action=submitlogin&type=login';
-                       $linkq = 'type=signup';
-               }
-
-               if ( $this->mReturnTo !== '' ) {
-                       $returnto = '&returnto=' . wfUrlencode( $this->mReturnTo );
-                       if ( $this->mReturnToQuery !== '' ) {
-                               $returnto .= '&returntoquery=' .
-                                       wfUrlencode( $this->mReturnToQuery );
-                       }
-                       $q .= $returnto;
-                       $linkq .= $returnto;
-               }
-
-               # Don't show a "create account" link if the user can't.
-               if ( $this->showCreateOrLoginLink( $user ) ) {
-                       # Pass any language selection on to the mode switch link
-                       if ( $wgLoginLanguageSelector && $this->mLanguage ) {
-                               $linkq .= '&uselang=' . $this->mLanguage;
-                       }
-                       // Supply URL, login template creates the button.
-                       $template->set( 'createOrLoginHref', $titleObj->getLocalURL( $linkq ) );
-               } else {
-                       $template->set( 'link', '' );
-               }
-
-               $resetLink = $this->mType == 'signup'
-                       ? null
-                       : is_array( $wgPasswordResetRoutes ) && in_array( true, array_values( $wgPasswordResetRoutes ) );
-
-               $template->set( 'header', '' );
-               $template->set( 'formheader', '' );
-               $template->set( 'skin', $this->getSkin() );
-               $template->set( 'name', $this->mUsername );
-               $template->set( 'password', $this->mPassword );
-               $template->set( 'retype', $this->mRetype );
-               $template->set( 'createemailset', $this->mCreateaccountMail );
-               $template->set( 'email', $this->mEmail );
-               $template->set( 'realname', $this->mRealName );
-               $template->set( 'domain', $this->mDomain );
-               $template->set( 'reason', $this->mReason );
-
-               $template->set( 'action', $titleObj->getLocalURL( $q ) );
-               $template->set( 'message', $msg );
-               $template->set( 'messagetype', $msgtype );
-               $template->set( 'createemail', $wgEnableEmail && $user->isLoggedIn() );
-               $template->set( 'userealname', !in_array( 'realname', $wgHiddenPrefs ) );
-               $template->set( 'useemail', $wgEnableEmail );
-               $template->set( 'emailrequired', $wgEmailConfirmToEdit );
-               $template->set( 'emailothers', $wgEnableUserEmail );
-               $template->set( 'canreset', $wgAuth->allowPasswordChange() );
-               $template->set( 'resetlink', $resetLink );
-               $template->set( 'canremember', $wgExtendedLoginCookieExpiration === null ?
-                       ( $wgCookieExpiration > 0 ) :
-                       ( $wgExtendedLoginCookieExpiration > 0 ) );
-               $template->set( 'usereason', $user->isLoggedIn() );
-               $template->set( 'remember', $this->mRemember );
-               $template->set( 'cansecurelogin', ( $wgSecureLogin === true ) );
-               $template->set( 'stickhttps', (int)$this->mStickHTTPS );
-               $template->set( 'loggedin', $user->isLoggedIn() );
-               $template->set( 'loggedinuser', $user->getName() );
-
-               if ( $this->mType == 'signup' ) {
-                       $template->set( 'token', self::getCreateaccountToken()->toString() );
-               } else {
-                       $template->set( 'token', self::getLoginToken()->toString() );
-               }
-
-               # Prepare language selection links as needed
-               if ( $wgLoginLanguageSelector ) {
-                       $template->set( 'languages', $this->makeLanguageSelector() );
-                       if ( $this->mLanguage ) {
-                               $template->set( 'uselang', $this->mLanguage );
-                       }
-               }
-
-               $template->set( 'secureLoginUrl', $this->mSecureLoginUrl );
-               // Use signupend-https for HTTPS requests if it's not blank, signupend otherwise
-               $usingHTTPS = $this->mRequest->getProtocol() == 'https';
-               $signupendHTTPS = $this->msg( 'signupend-https' );
-               if ( $usingHTTPS && !$signupendHTTPS->isBlank() ) {
-                       $template->set( 'signupend', $signupendHTTPS->parse() );
-               } else {
-                       $template->set( 'signupend', $this->msg( 'signupend' )->parse() );
-               }
-
-               // If using HTTPS coming from HTTP, then the 'fromhttp' parameter must be preserved
-               if ( $usingHTTPS ) {
-                       $template->set( 'fromhttp', $this->mFromHTTP );
-               }
-
-               // Give authentication and captcha plugins a chance to modify the form
-               $wgAuth->modifyUITemplate( $template, $this->mType );
-               if ( $this->mType == 'signup' ) {
-                       Hooks::run( 'UserCreateForm', [ &$template ] );
-               } else {
-                       Hooks::run( 'UserLoginForm', [ &$template ] );
-               }
-
-               $out->disallowUserJs(); // just in case...
-               $out->addTemplate( $template );
-       }
-
-       /**
-        * Whether the login/create account form should display a link to the
-        * other form (in addition to whatever the skin provides).
-        *
-        * @param User $user
-        * @return bool
-        */
-       private function showCreateOrLoginLink( &$user ) {
-               if ( $this->mType == 'signup' ) {
-                       return true;
-               } elseif ( $user->isAllowed( 'createaccount' ) ) {
-                       return true;
-               } else {
-                       return false;
-               }
-       }
-
-       /**
-        * Check if a session cookie is present.
-        *
-        * This will not pick up a cookie set during _this_ request, but is meant
-        * to ensure that the client is returning the cookie which was set on a
-        * previous pass through the system.
-        *
-        * @private
-        * @return bool
-        */
-       function hasSessionCookie() {
-               global $wgDisableCookieCheck, $wgInitialSessionId;
-
-               return $wgDisableCookieCheck || (
-                       $wgInitialSessionId &&
-                       $this->getRequest()->getSession()->getId() === (string)$wgInitialSessionId
-               );
-       }
-
-       /**
-        * Get the login token from the current session
-        * @since 1.27 returns a MediaWiki\Session\Token instead of a string
-        * @return MediaWiki\Session\Token
-        */
-       public static function getLoginToken() {
-               global $wgRequest;
-               return $wgRequest->getSession()->getToken( '', 'login' );
-       }
-
-       /**
-        * 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() {
-               wfDeprecated( __METHOD__, '1.27' );
-       }
-
-       /**
-        * Remove any login token attached to the current session
-        */
-       public static function clearLoginToken() {
-               global $wgRequest;
-               $wgRequest->getSession()->resetToken( 'login' );
-       }
-
-       /**
-        * Get the createaccount token from the current session
-        * @since 1.27 returns a MediaWiki\Session\Token instead of a string
-        * @return MediaWiki\Session\Token
-        */
-       public static function getCreateaccountToken() {
-               global $wgRequest;
-               return $wgRequest->getSession()->getToken( '', 'createaccount' );
-       }
-
-       /**
-        * 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() {
-               wfDeprecated( __METHOD__, '1.27' );
-       }
-
-       /**
-        * Remove any createaccount token attached to the current session
-        */
-       public static function clearCreateaccountToken() {
-               global $wgRequest;
-               $wgRequest->getSession()->resetToken( 'createaccount' );
-       }
-
-       /**
-        * Renew the user's session id, using strong entropy
-        */
-       private function renewSessionId() {
-               global $wgSecureLogin, $wgCookieSecure;
-               if ( $wgSecureLogin && !$this->mStickHTTPS ) {
-                       $wgCookieSecure = false;
-               }
-
-               SessionManager::getGlobalSession()->resetId();
-               SessionManager::getGlobalSession()->resetAllTokens();
-       }
-
-       /**
-        * @param string $type
-        * @private
-        */
-       function cookieRedirectCheck( $type ) {
-               $titleObj = SpecialPage::getTitleFor( 'Userlogin' );
-               $query = [ 'wpCookieCheck' => $type ];
-               if ( $this->mReturnTo !== '' ) {
-                       $query['returnto'] = $this->mReturnTo;
-                       $query['returntoquery'] = $this->mReturnToQuery;
-               }
-               $check = $titleObj->getFullURL( $query );
-
-               $this->getOutput()->redirect( $check );
-       }
-
-       /**
-        * @param string $type
-        * @private
-        */
-       function onCookieRedirectCheck( $type ) {
-               if ( !$this->hasSessionCookie() ) {
-                       if ( $type == 'new' ) {
-                               $this->mainLoginForm( $this->msg( 'nocookiesnew' )->parse() );
-                       } elseif ( $type == 'login' ) {
-                               $this->mainLoginForm( $this->msg( 'nocookieslogin' )->parse() );
-                       } else {
-                               # shouldn't happen
-                               $this->mainLoginForm( $this->msg( 'error' )->text() );
-                       }
-               } else {
-                       $this->successfulLogin();
-               }
-       }
-
-       /**
-        * Produce a bar of links which allow the user to select another language
-        * during login/registration but retain "returnto"
-        *
-        * @return string
-        */
-       function makeLanguageSelector() {
-               $msg = $this->msg( 'loginlanguagelinks' )->inContentLanguage();
-               if ( $msg->isBlank() ) {
-                       return '';
-               }
-               $langs = explode( "\n", $msg->text() );
-               $links = [];
-               foreach ( $langs as $lang ) {
-                       $lang = trim( $lang, '* ' );
-                       $parts = explode( '|', $lang );
-                       if ( count( $parts ) >= 2 ) {
-                               $links[] = $this->makeLanguageSelectorLink( $parts[0], trim( $parts[1] ) );
-                       }
-               }
-
-               return count( $links ) > 0 ? $this->msg( 'loginlanguagelabel' )->rawParams(
-                       $this->getLanguage()->pipeList( $links ) )->escaped() : '';
-       }
-
-       /**
-        * Create a language selector link for a particular language
-        * Links back to this page preserving type and returnto
-        *
-        * @param string $text Link text
-        * @param string $lang Language code
-        * @return string
-        */
-       function makeLanguageSelectorLink( $text, $lang ) {
-               if ( $this->getLanguage()->getCode() == $lang ) {
-                       // no link for currently used language
-                       return htmlspecialchars( $text );
-               }
-               $query = [ 'uselang' => $lang ];
-               if ( $this->mType == 'signup' ) {
-                       $query['type'] = 'signup';
-               }
-               if ( $this->mReturnTo !== '' ) {
-                       $query['returnto'] = $this->mReturnTo;
-                       $query['returntoquery'] = $this->mReturnToQuery;
-               }
-
-               $attr = [];
-               $targetLanguage = Language::factory( $lang );
-               $attr['lang'] = $attr['hreflang'] = $targetLanguage->getHtmlCode();
-
-               return Linker::linkKnown(
-                       $this->getPageTitle(),
-                       htmlspecialchars( $text ),
-                       $attr,
-                       $query
-               );
-       }
-
-       protected function getGroupName() {
-               return 'login';
-       }
-
-       /**
-        * Private function to check password expiration, until AuthManager comes
-        * along to handle that.
-        * @param User $user
-        * @return string|bool
-        */
-       private function checkUserPasswordExpired( User $user ) {
-               global $wgPasswordExpireGrace;
-               $dbr = wfGetDB( DB_SLAVE );
-               $ts = $dbr->selectField( 'user', 'user_password_expires', [ 'user_id' => $user->getId() ] );
-
-               $expired = false;
-               $now = wfTimestamp();
-               $expUnix = wfTimestamp( TS_UNIX, $ts );
-               if ( $ts !== null && $expUnix < $now ) {
-                       $expired = ( $expUnix + $wgPasswordExpireGrace < $now ) ? 'hard' : 'soft';
-               }
-               return $expired;
-       }
-
-       protected function getSubpagesForPrefixSearch() {
-               return [ 'signup' ];
-       }
-}
diff --git a/includes/specials/pre-authmanager/SpecialUserlogout.php b/includes/specials/pre-authmanager/SpecialUserlogout.php
deleted file mode 100644 (file)
index 6d6a714..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-<?php
-/**
- * Implements Special:Userlogout
- *
- * 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 SpecialPage
- */
-
-/**
- * Implements Special:Userlogout
- *
- * @ingroup SpecialPage
- */
-class SpecialUserlogoutPreAuthManager extends UnlistedSpecialPage {
-       function __construct() {
-               parent::__construct( 'Userlogout' );
-       }
-
-       public function doesWrites() {
-               return true;
-       }
-
-       function execute( $par ) {
-               /**
-                * Some satellite ISPs use broken precaching schemes that log people out straight after
-                * they're logged in (bug 17790). Luckily, there's a way to detect such requests.
-                */
-               if ( isset( $_SERVER['REQUEST_URI'] ) && strpos( $_SERVER['REQUEST_URI'], '&amp;' ) !== false ) {
-                       wfDebug( "Special:Userlogout request {$_SERVER['REQUEST_URI']} looks suspicious, denying.\n" );
-                       throw new HttpError( 400, $this->msg( 'suspicious-userlogout' ), $this->msg( 'loginerror' ) );
-               }
-
-               $this->setHeaders();
-               $this->outputHeader();
-
-               // Make sure it's possible to log out
-               $session = MediaWiki\Session\SessionManager::getGlobalSession();
-               if ( !$session->canSetUser() ) {
-                       throw new ErrorPageError(
-                               'cannotlogoutnow-title',
-                               'cannotlogoutnow-text',
-                               [
-                                       $session->getProvider()->describe( RequestContext::getMain()->getLanguage() )
-                               ]
-                       );
-               }
-
-               $user = $this->getUser();
-               $oldName = $user->getName();
-               $user->logout();
-
-               $loginURL = SpecialPage::getTitleFor( 'Userlogin' )->getFullURL(
-                       $this->getRequest()->getValues( 'returnto', 'returntoquery' ) );
-
-               $out = $this->getOutput();
-               $out->addWikiMsg( 'logouttext', $loginURL );
-
-               // Hook.
-               $injected_html = '';
-               Hooks::run( 'UserLogoutComplete', [ &$user, &$injected_html, $oldName ] );
-               $out->addHTML( $injected_html );
-
-               $out->returnToMain();
-       }
-
-       protected function getGroupName() {
-               return 'login';
-       }
-}
diff --git a/includes/templates/Usercreate.php b/includes/templates/Usercreate.php
deleted file mode 100644 (file)
index 0a5aa61..0000000
+++ /dev/null
@@ -1,308 +0,0 @@
-<?php
-// @codingStandardsIgnoreFile
-/**
- * Html form for account creation (since 1.22 with VForm appearance).
- *
- * 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 Templates
- * @deprecated Will be removed when AuthManager lands.
- *   The signup form will be generated via HTMLForm.
- */
-
-class UsercreateTemplate extends BaseTemplate {
-       /**
-        * Extensions (AntiSpoof and TitleBlacklist) call this in response to
-        * UserCreateForm hook to add checkboxes to the create account form.
-        */
-       function addInputItem( $name, $value, $type, $msg, $helptext = false ) {
-               $this->data['extraInput'][] = [
-                       'name' => $name,
-                       'value' => $value,
-                       'type' => $type,
-                       'msg' => $msg,
-                       'helptext' => $helptext,
-               ];
-       }
-
-       function execute() {
-?>
-<div class="mw-ui-container">
-       <?php if ( $this->haveData( 'languages' ) ) { ?>
-               <div id="languagelinks">
-                       <p><?php $this->html( 'languages' ); ?></p>
-               </div>
-       <?php }
-             if ( !wfMessage( 'signupstart' )->isDisabled() ) { ?>
-               <div id="signupstart"><?php $this->msgWiki( 'signupstart' ); ?></div>
-       <?php } ?>
-       <div id="userloginForm">
-               <form name="userlogin2" id="userlogin2" class="mw-ui-vform" method="post" action="<?php $this->text( 'action' ); ?>">
-                       <section class="mw-form-header">
-                               <?php $this->html( 'header' ); ?>
-                       </section>
-                       <!-- This element is used by the mediawiki.special.userlogin.signup.js module. -->
-                       <div
-                               id="mw-createacct-status-area"
-                               <?php if ( $this->data['message'] ) { ?>
-                                       class="<?php echo $this->data['messagetype']; ?>box"
-                               <?php } else { ?>
-                                       style="display: none;"
-                               <?php } ?>
-                       >
-                       <?php if ( $this->data['message'] ) { ?>
-                                       <?php if ( $this->data['messagetype'] == 'error' ) { ?>
-                                               <strong><?php $this->msg( 'createacct-error' ); ?></strong>
-                                               <br />
-                                       <?php } ?>
-                                       <?php $this->html( 'message' ); ?>
-                       <?php } ?>
-                       </div>
-
-                       <?php if ( $this->data['formheader'] ) { ?>
-                               <div class="mw-form-formheader">
-                                       <?php $this->html( 'formheader' ); /* extensions such as MobileFrontend add html here */ ?>
-                               </div>
-                       <?php } ?>
-
-                       <div class="mw-ui-vform-field">
-                               <label for='wpName2'>
-                                       <?php $this->msg( 'userlogin-yourname' ); ?>
-
-                                       <span class="mw-ui-flush-right"><?php echo $this->getMsg( 'createacct-helpusername' )->parse(); ?></span>
-                               </label>
-                               <?php
-                               echo Html::input( 'wpName', $this->data['name'], 'text', [
-                                       'class' => 'mw-ui-input loginText',
-                                       'id' => 'wpName2',
-                                       'tabindex' => '1',
-                                       'size' => '20',
-                                       'required',
-                                       'placeholder' => $this->getMsg( $this->data['loggedin'] ?
-                                               'createacct-another-username-ph' : 'userlogin-yourname-ph' )->text(),
-                               ] );
-                               ?>
-                       </div>
-
-                       <div class="mw-ui-vform-field">
-                               <?php if ( $this->data['createemail'] ) { ?>
-                                       <div class="mw-ui-checkbox">
-                                               <input name="wpCreateaccountMail" type="checkbox" value="1" id="wpCreateaccountMail" tabindex="2"
-                                                       <?php if ( $this->data['createemailset'] ) {
-                                                               echo 'checked="checked"';
-                                                       } ?>
-                                               ><label for="wpCreateaccountMail">
-                                                       <?php $this->msg( 'createaccountmail' ); ?>
-                                               </label>
-                                       </div>
-                               <?php } ?>
-                       </div>
-
-                       <div class="mw-ui-vform-field mw-row-password">
-                               <label for='wpPassword2'><?php $this->msg( 'userlogin-yourpassword' ); ?></label>
-                               <?php
-                               echo Html::input( 'wpPassword', null, 'password', [
-                                       'class' => 'mw-ui-input loginPassword',
-                                       'id' => 'wpPassword2',
-                                       'tabindex' => '3',
-                                       'size' => '20',
-                                       'required',
-                                       'placeholder' => $this->getMsg( 'createacct-yourpassword-ph' )->text()
-                               ] + User::passwordChangeInputAttribs() );
-                               ?>
-                       </div>
-
-                       <?php
-                       if ( $this->data['usedomain'] ) {
-                               $select = new XmlSelect( 'wpDomain', false, $this->data['domain'] );
-                               $select->setAttribute( 'tabindex', 4 );
-                               foreach ( $this->data['domainnames'] as $dom ) {
-                                       $select->addOption( $dom );
-                               }
-                       ?>
-                               <div class="mw-ui-vform-field" id="mw-user-domain-section">
-                                       <label for="wpDomain"><?php $this->msg( 'yourdomainname' ); ?></label>
-                                       <div>
-                                               <?php echo $select->getHTML(); ?>
-                                       </div>
-                               </div>
-                       <?php } ?>
-
-                       <div class="mw-ui-vform-field mw-row-password">
-                               <label for='wpRetype'><?php $this->msg( 'createacct-yourpasswordagain' ); ?></label>
-                               <?php
-                               echo Html::input( 'wpRetype', null, 'password', [
-                                       'class' => 'mw-ui-input loginPassword',
-                                       'id' => 'wpRetype',
-                                       'tabindex' => '5',
-                                       'size' => '20',
-                                       'required',
-                                       'placeholder' => $this->getMsg( 'createacct-yourpasswordagain-ph' )->text()
-                               ] + User::passwordChangeInputAttribs() );
-                               ?>
-                       </div>
-
-                       <div class="mw-ui-vform-field">
-                               <?php if ( $this->data['useemail'] ) { ?>
-                                       <label for='wpEmail'>
-                                               <?php
-                                                       $this->msg( $this->data['emailrequired'] ?
-                                                               'createacct-emailrequired' :
-                                                               'createacct-emailoptional'
-                                                       );
-                                               ?>
-                                       </label>
-                                       <?php
-                                               echo Html::input( 'wpEmail', $this->data['email'], 'email', [
-                                                       'class' => 'mw-ui-input loginText',
-                                                       'id' => 'wpEmail',
-                                                       'tabindex' => '6',
-                                                       'size' => '20',
-                                                       'required' => $this->data['emailrequired'],
-                                                       'placeholder' => $this->getMsg( $this->data['loggedin'] ?
-                                                               'createacct-another-email-ph' : 'createacct-email-ph' )->text()
-                                               ] );
-                                       ?>
-                               <?php } ?>
-                       </div>
-
-                       <?php if ( $this->data['userealname'] ) { ?>
-                               <div class="mw-ui-vform-field">
-                                       <label for='wpRealName'><?php $this->msg( 'createacct-realname' ); ?></label>
-                                       <input type='text' class='mw-ui-input loginText' name="wpRealName" id="wpRealName"
-                                               tabindex="7"
-                                               value="<?php $this->text( 'realname' ); ?>" size='20' />
-                                       <div class="prefsectiontip">
-                                               <?php $this->msgWiki( $this->data['loggedin'] ? 'createacct-another-realname-tip' : 'prefs-help-realname' ); ?>
-                                       </div>
-                               </div>
-                       <?php } ?>
-
-                       <?php if ( $this->data['usereason'] ) { ?>
-                               <div class="mw-ui-vform-field">
-                                       <label for='wpReason'><?php $this->msg( 'createacct-reason' ); ?></label>
-                                       <?php echo Html::input( 'wpReason', $this->data['reason'], 'text', [
-                                               'class' => 'mw-ui-input loginText',
-                                               'id' => 'wpReason',
-                                               'tabindex' => '8',
-                                               'size' => '20',
-                                               'placeholder' => $this->getMsg( 'createacct-reason-ph' )->text()
-                                       ] ); ?>
-                               </div>
-                       <?php } ?>
-
-                       <?php
-                       $tabIndex = 9;
-                       if ( isset( $this->data['extraInput'] ) && is_array( $this->data['extraInput'] ) ) {
-                               foreach ( $this->data['extraInput'] as $inputItem ) { ?>
-                                       <div class="mw-ui-vform-field">
-                                               <?php
-                                               // If it's a checkbox, output the whole thing (assume it has a msg).
-                                               if ( $inputItem['type'] == 'checkbox' ) {
-                                               ?>
-                                                       <div class="mw-ui-checkbox">
-                                                               <input
-                                                                       name="<?php echo htmlspecialchars( $inputItem['name'] ); ?>"
-                                                                       id="<?php echo htmlspecialchars( $inputItem['name'] ); ?>"
-                                                                       type="checkbox" value="1"
-                                                                       tabindex="<?php echo $tabIndex++; ?>"
-                                                                       <?php if ( !empty( $inputItem['value'] ) ) {
-                                                                               echo 'checked="checked"';
-                                                                       } ?>
-                                                               ><label for="<?php echo htmlspecialchars( $inputItem['name'] ); ?>">
-                                                                       <?php $this->msg( $inputItem['msg'] ); ?>
-                                                               </label>
-                                                       </div>
-                                               <?php
-                                               } else {
-                                                       // Not a checkbox.
-                                                       // TODO (bug 31909) support other input types, e.g. select boxes.
-                                               ?>
-                                                       <?php if ( !empty( $inputItem['msg'] ) ) { ?>
-                                                               <label for="<?php echo htmlspecialchars( $inputItem['name'] ); ?>">
-                                                                       <?php $this->msgWiki( $inputItem['msg'] ); ?>
-                                                               </label>
-                                                       <?php } ?>
-                                                       <input
-                                                               type="<?php echo htmlspecialchars( $inputItem['type'] ); ?>"
-                                                               class="mw-ui-input"
-                                                               name="<?php echo htmlspecialchars( $inputItem['name'] ); ?>"
-                                                               tabindex="<?php echo $tabIndex++; ?>"
-                                                               value="<?php echo htmlspecialchars( $inputItem['value'] ); ?>"
-                                                               id="<?php echo htmlspecialchars( $inputItem['name'] ); ?>"
-                                                       />
-                                               <?php } ?>
-                                               <?php if ( $inputItem['helptext'] !== false ) { ?>
-                                                       <div class="prefsectiontip">
-                                                               <?php $this->msgWiki( $inputItem['helptext'] ); ?>
-                                                       </div>
-                                               <?php } ?>
-                                       </div>
-                               <?php
-                               }
-                       }
-
-                       // A separate placeholder for any inserting any extrafields, e.g used by ConfirmEdit extension
-                       if ( $this->haveData( 'extrafields' ) ) {
-                               echo $this->data['extrafields'];
-                       }
-                       // skip one index.
-                       $tabIndex++;
-                       ?>
-                       <div class="mw-ui-vform-field mw-submit">
-                               <?php
-                               echo Html::submitButton(
-                                       $this->getMsg( $this->data['loggedin'] ? 'createacct-another-submit' : 'createacct-submit' ),
-                                       [
-                                               'id' => 'wpCreateaccount',
-                                               'name' => 'wpCreateaccount',
-                                               'tabindex' => $tabIndex++
-                                       ],
-                                       [
-                                               'mw-ui-block',
-                                               'mw-ui-constructive',
-                                       ]
-                               );
-                               ?>
-                       </div>
-                       <?php if ( $this->haveData( 'uselang' ) ) { ?><input type="hidden" name="uselang" value="<?php $this->text( 'uselang' ); ?>" /><?php } ?>
-                       <?php if ( $this->haveData( 'token' ) ) { ?><input type="hidden" name="wpCreateaccountToken" value="<?php $this->text( 'token' ); ?>" /><?php } ?>
-               </form>
-               <?php if ( !wfMessage( 'signupend' )->isDisabled() ) { ?>
-                       <div id="signupend"><?php $this->html( 'signupend' ); ?></div>
-               <?php } ?>
-       </div>
-       <div class="mw-createacct-benefits-container">
-               <h2><?php $this->msg( 'createacct-benefit-heading' ); ?></h2>
-               <div class="mw-createacct-benefits-list">
-                       <?php
-                       for ( $benefitIdx = 1; $benefitIdx <= $this->data['benefitCount']; $benefitIdx++ ) {
-                               // Pass each benefit's head text (by default a number) as a parameter to the body's message for PLURAL handling.
-                               $headUnescaped = $this->getMsg( "createacct-benefit-head$benefitIdx" )->text();
-                       ?>
-                               <div class="mw-number-text <?php $this->msg( "createacct-benefit-icon$benefitIdx" ); ?>">
-                                       <h3><?php $this->msg( "createacct-benefit-head$benefitIdx" ); ?></h3>
-                                       <p><?php echo $this->getMsg( "createacct-benefit-body$benefitIdx" )->params( $headUnescaped )->escaped(); ?></p>
-                               </div>
-                       <?php } ?>
-               </div>
-       </div>
-</div>
-<?php
-
-       }
-}
diff --git a/includes/templates/Userlogin.php b/includes/templates/Userlogin.php
deleted file mode 100644 (file)
index e816b62..0000000
+++ /dev/null
@@ -1,223 +0,0 @@
-<?php
-// @codingStandardsIgnoreFile
-/**
- * HTML form for user login (since 1.22 with VForm appearance).
- *
- * 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 Templates
- * @deprecated Will be removed when AuthManager lands.
- *   The login form will be generated via HTMLForm.
- */
-
-class UserloginTemplate extends BaseTemplate {
-
-       function execute() {
-               global $wgCookieExpiration;
-               $expirationDays = ceil( $wgCookieExpiration / ( 3600 * 24 ) );
-?>
-<div class="mw-ui-container">
-       <div id="userloginprompt"><?php $this->msgWiki('loginprompt') ?></div>
-       <?php if ( $this->haveData( 'languages' ) ) { ?>
-               <div id="languagelinks">
-                       <p><?php $this->html( 'languages' ); ?></p>
-               </div>
-       <?php } ?>
-       <div id="userloginForm">
-               <form name="userlogin" class="mw-ui-vform" method="post" action="<?php $this->text( 'action' ); ?>">
-                       <?php if ( $this->data['loggedin'] ) { ?>
-                               <div class="warningbox">
-                                       <?php echo $this->getMsg( 'userlogin-loggedin' )->params( $this->data['loggedinuser'] )->parse(); ?>
-                               </div>
-                       <?php } ?>
-                       <section class="mw-form-header">
-                               <?php $this->html( 'header' ); /* extensions such as ConfirmEdit add form HTML here */ ?>
-                       </section>
-
-                       <?php if ( $this->data['message'] ) { ?>
-                               <div class="<?php $this->text( 'messagetype' ); ?>box">
-                                       <?php if ( $this->data['messagetype'] == 'error' ) { ?>
-                                               <strong><?php $this->msg( 'loginerror' ); ?></strong>
-                                               <br />
-                                       <?php } ?>
-                                       <?php $this->html( 'message' ); ?>
-                               </div>
-                       <?php } ?>
-
-                       <?php if ( $this->data['formheader'] ) { ?>
-                               <div class="mw-form-formheader">
-                                       <?php $this->html( 'formheader' ); /* extensions such as MobileFrontend add HTML here */ ?>
-                               </div>
-                       <?php } ?>
-                       <div class="mw-ui-vform-field">
-                               <label for="wpName1">
-                                       <?php
-                                       $this->msg( 'userlogin-yourname' );
-
-                                       if ( $this->data['secureLoginUrl'] ) {
-                                               echo Html::element( 'a', [
-                                                       'href' => $this->data['secureLoginUrl'],
-                                                       'class' => 'mw-ui-flush-right mw-secure',
-                                               ], $this->getMsg( 'userlogin-signwithsecure' )->text() );
-                                       }
-                                       ?>
-                               </label>
-                               <?php
-                               echo Html::input( 'wpName', $this->data['name'], 'text', [
-                                       'class' => 'loginText mw-ui-input',
-                                       'id' => 'wpName1',
-                                       'tabindex' => '1',
-                                       // 'required' is blacklisted for now in Html.php due to browser issues.
-                                       // Keeping here in case that changes.
-                                       'required' => true,
-                                       // Set focus to this field if it's blank.
-                                       'autofocus' => !$this->data['name'],
-                                       'placeholder' => $this->getMsg( 'userlogin-yourname-ph' )->text()
-                               ] );
-                               ?>
-                       </div>
-
-                       <div class="mw-ui-vform-field">
-                               <label for="wpPassword1">
-                                       <?php
-                                       $this->msg( 'userlogin-yourpassword' );
-                                       ?>
-                               </label>
-                               <?php
-                               echo Html::input( 'wpPassword', null, 'password', [
-                                       'class' => 'loginPassword mw-ui-input',
-                                       'id' => 'wpPassword1',
-                                       'tabindex' => '2',
-                                       // Set focus to this field if username is filled in.
-                                       'autofocus' => (bool)$this->data['name'],
-                                       'placeholder' => $this->getMsg( 'userlogin-yourpassword-ph' )->text()
-                               ] );
-                               ?>
-                       </div>
-
-                       <?php
-                       if ( isset( $this->data['usedomain'] ) && $this->data['usedomain'] ) {
-                               $select = new XmlSelect( 'wpDomain', false, $this->data['domain'] );
-                               $select->setAttribute( 'tabindex', 3 );
-                               foreach ( $this->data['domainnames'] as $dom ) {
-                                       $select->addOption( $dom );
-                               }
-                       ?>
-                               <div class="mw-ui-vform-field" id="mw-user-domain-section">
-                                       <label for="wpDomain"><?php $this->msg( 'yourdomainname' ); ?></label>
-                                       <?php echo $select->getHTML(); ?>
-                               </div>
-                       <?php } ?>
-
-                       <?php
-                       if ( $this->haveData( 'extrafields' ) ) {
-                               echo $this->data['extrafields'];
-                       }
-                       ?>
-
-                       <div class="mw-ui-vform-field">
-                               <?php if ( $this->data['canremember'] ) { ?>
-                                       <div class="mw-ui-checkbox">
-                                               <input name="wpRemember" type="checkbox" value="1" id="wpRemember" tabindex="4"
-                                                       <?php if ( $this->data['remember'] ) {
-                                                               echo 'checked="checked"';
-                                                       } ?>
-                                               ><label for="wpRemember">
-                                                       <?php echo $this->getMsg( 'userlogin-remembermypassword' )->numParams( $expirationDays )->escaped(); ?></label>
-                                       </div>
-                               <?php } ?>
-                       </div>
-
-                       <div class="mw-ui-vform-field">
-                               <?php
-                               $attrs = [
-                                       'id' => 'wpLoginAttempt',
-                                       'name' => 'wpLoginAttempt',
-                                       'tabindex' => '6',
-                               ];
-                               $modifiers = [
-                                       'mw-ui-progressive',
-                               ];
-                               echo Html::submitButton( $this->getMsg( 'pt-login-button' )->text(), $attrs, $modifiers );
-                               ?>
-                       </div>
-
-                       <div class="mw-ui-vform-field mw-form-related-link-container" id="mw-userlogin-help">
-                               <?php
-                               echo Html::element(
-                                       'a',
-                                       [
-                                               'href' => Skin::makeInternalOrExternalUrl(
-                                                       wfMessage( 'helplogin-url' )->inContentLanguage()->text()
-                                               ),
-                                       ],
-                                       $this->getMsg( 'userlogin-helplink2' )->text()
-                               );
-                               ?>
-                       </div>
-                       <?php
-
-                       if ( $this->data['useemail'] && $this->data['canreset'] && $this->data['resetlink'] === true ) {
-                               echo Html::rawElement(
-                                       'div',
-                                       [
-                                               'class' => 'mw-ui-vform-field mw-form-related-link-container',
-                                       ],
-                                       Linker::link(
-                                               SpecialPage::getTitleFor( 'PasswordReset' ),
-                                               $this->getMsg( 'userlogin-resetpassword-link' )->escaped()
-                                       )
-                               );
-                       }
-
-                       if ( $this->haveData( 'createOrLoginHref' ) ) {
-                               if ( $this->data['loggedin'] ) { ?>
-                                       <div class="mw-form-related-link-container mw-ui-vform-field">
-                                               <a href="<?php $this->text( 'createOrLoginHref' ); ?>" id="mw-createaccount-join" tabindex="7"><?php $this->msg( 'userlogin-createanother' ); ?></a>
-                                       </div>
-                               <?php } else { ?>
-                                       <div id="mw-createaccount-cta" class="mw-ui-vform-field">
-                                               <?php $this->msg( 'userlogin-noaccount' ); ?><a href="<?php $this->text( 'createOrLoginHref' ); ?>" id="mw-createaccount-join" tabindex="7" class="mw-ui-button"><?php $this->msg( 'userlogin-joinproject' ); ?></a>
-                                       </div>
-                               <?php
-                               }
-                       }
-
-                       // Hidden fields
-                       $fields = '';
-                       if ( $this->haveData( 'uselang' ) ) {
-                               $fields .= Html::hidden( 'uselang', $this->data['uselang'] );
-                       }
-                       if ( $this->haveData( 'token' ) ) {
-                               $fields .= Html::hidden( 'wpLoginToken', $this->data['token'] );
-                       }
-                       if ( $this->data['cansecurelogin'] ) {
-                               $fields .= Html::hidden( 'wpForceHttps', $this->data['stickhttps'] );
-                       }
-                       if ( $this->data['cansecurelogin'] && $this->haveData( 'fromhttp' ) ) {
-                               $fields .= Html::hidden( 'wpFromhttp', $this->data['fromhttp'] );
-                       }
-                       echo $fields;
-
-                       ?>
-               </form>
-       </div>
-</div>
-<?php
-
-       }
-}
index b620132..03c864a 100644 (file)
@@ -944,6 +944,33 @@ abstract class UploadBase {
                return $this->mLocalFile;
        }
 
+       /**
+        * Like stashFile(), but respects extensions' wishes to prevent the stashing.
+        *
+        * Upload stash exceptions are also caught and converted to an error status.
+        *
+        * @since 1.28
+        * @param User $user
+        * @return Status If successful, value is an UploadStashFile instance
+        */
+       public function tryStashFile( User $user ) {
+               $props = $this->mFileProps;
+               $error = null;
+               Hooks::run( 'UploadStashFile', [ $this, $user, $props, &$error ] );
+               if ( $error ) {
+                       if ( !is_array( $error ) ) {
+                               $error = [ $error ];
+                       }
+                       return call_user_func_array( 'Status::newFatal', $error );
+               }
+               try {
+                       $file = $this->doStashFile( $user );
+                       return Status::newGood( $file );
+               } catch ( UploadStashException $e ) {
+                       return Status::newFatal( 'uploadstash-exception', get_class( $e ), $e->getMessage() );
+               }
+       }
+
        /**
         * If the user does not supply all necessary information in the first upload
         * form submission (either by accident or by design) then we may want to
@@ -956,6 +983,7 @@ abstract class UploadBase {
         * which can be passed through a form or API request to find this stashed
         * file again.
         *
+        * @deprecated since 1.28 Use tryStashFile() instead
         * @param User $user
         * @return UploadStashFile Stashed file
         * @throws UploadStashBadPathException
@@ -963,6 +991,16 @@ abstract class UploadBase {
         * @throws UploadStashNotLoggedInException
         */
        public function stashFile( User $user = null ) {
+               return $this->doStashFile( $user );
+       }
+
+       /**
+        * Implementation for stashFile() and tryStashFile().
+        *
+        * @param User $user
+        * @return UploadStashFile Stashed file
+        */
+       protected function doStashFile( User $user = null ) {
                $stash = RepoGroup::singleton()->getLocalRepo()->getUploadStash( $user );
                $file = $stash->stashFile( $this->mTempPath, $this->getSourceType() );
                $this->mLocalFile = $file;
@@ -979,7 +1017,7 @@ abstract class UploadBase {
         */
        public function stashFileGetKey() {
                wfDeprecated( __METHOD__, '1.28' );
-               return $this->stashFile()->getFileKey();
+               return $this->doStashFile()->getFileKey();
        }
 
        /**
@@ -990,7 +1028,7 @@ abstract class UploadBase {
         */
        public function stashSession() {
                wfDeprecated( __METHOD__, '1.28' );
-               return $this->stashFile()->getFileKey();
+               return $this->doStashFile()->getFileKey();
        }
 
        /**
index 0323b68..cc1d698 100644 (file)
@@ -65,19 +65,19 @@ class UploadFromChunks extends UploadFromFile {
        }
 
        /**
-        * Calls the parent stashFile and updates the uploadsession table to handle "chunks"
+        * Calls the parent doStashFile and updates the uploadsession table to handle "chunks"
         *
         * @param User|null $user
         * @return UploadStashFile Stashed file
         */
-       public function stashFile( User $user = null ) {
+       protected function doStashFile( User $user = null ) {
                // Stash file is the called on creating a new chunk session:
                $this->mChunkIndex = 0;
                $this->mOffset = 0;
 
                $this->verifyChunk();
                // Create a local stash target
-               $this->mLocalFile = parent::stashFile( $user );
+               $this->mLocalFile = parent::doStashFile( $user );
                // Update the initial file offset (based on file size)
                $this->mOffset = $this->mLocalFile->getSize();
                $this->mFileKey = $this->mLocalFile->getFileKey();
@@ -162,7 +162,7 @@ class UploadFromChunks extends UploadFromFile {
                // Update the mTempPath and mLocalFile
                // (for FileUpload or normal Stash to take over)
                $tStart = microtime( true );
-               $this->mLocalFile = parent::stashFile( $this->user );
+               $this->mLocalFile = parent::doStashFile( $this->user );
                $tAmount = microtime( true ) - $tStart;
                $this->mLocalFile->setLocalReference( $tmpFile ); // reuse (e.g. for getImageInfo())
                wfDebugLog( 'fileconcatenate', "Stashed combined file ($i chunks) in $tAmount seconds." );
index 908c8aa..50bcbc4 100644 (file)
@@ -153,10 +153,10 @@ class UploadFromStash extends UploadBase {
         * @param User $user
         * @return UploadStashFile
         */
-       public function stashFile( User $user = null ) {
+       protected function doStashFile( User $user = null ) {
                // replace mLocalFile with an instance of UploadStashFile, which adds some methods
                // that are useful for stashed files.
-               $this->mLocalFile = parent::stashFile( $user );
+               $this->mLocalFile = parent::doStashFile( $user );
 
                return $this->mLocalFile;
        }
index 181ff46..36526d7 100644 (file)
@@ -648,8 +648,6 @@ class User implements IDBAccessObject {
         * @since 1.27
         */
        public static function newSystemUser( $name, $options = [] ) {
-               global $wgDisableAuthManager;
-
                $options += [
                        'validate' => 'valid',
                        'create' => true,
@@ -662,9 +660,6 @@ class User implements IDBAccessObject {
                }
 
                $fields = self::selectFields();
-               if ( $wgDisableAuthManager ) {
-                       $fields = array_merge( $fields, [ 'user_password', 'user_newpassword' ] );
-               }
 
                $dbw = wfGetDB( DB_MASTER );
                $row = $dbw->selectRow(
@@ -681,49 +676,15 @@ class User implements IDBAccessObject {
 
                // A user is considered to exist as a non-system user if it can
                // authenticate, or has an email set, or has a non-invalid token.
-               if ( !$user->mEmail && $user->mToken === self::INVALID_TOKEN ) {
-                       if ( $wgDisableAuthManager ) {
-                               $passwordFactory = new PasswordFactory();
-                               $passwordFactory->init( RequestContext::getMain()->getConfig() );
-                               try {
-                                       $password = $passwordFactory->newFromCiphertext( $row->user_password );
-                               } catch ( PasswordError $e ) {
-                                       wfDebug( 'Invalid password hash found in database.' );
-                                       $password = PasswordFactory::newInvalidPassword();
-                               }
-                               try {
-                                       $newpassword = $passwordFactory->newFromCiphertext( $row->user_newpassword );
-                               } catch ( PasswordError $e ) {
-                                       wfDebug( 'Invalid password hash found in database.' );
-                                       $newpassword = PasswordFactory::newInvalidPassword();
-                               }
-                               $canAuthenticate = !$password instanceof InvalidPassword ||
-                                       !$newpassword instanceof InvalidPassword;
-                       } else {
-                               $canAuthenticate = AuthManager::singleton()->userCanAuthenticate( $name );
-                       }
-               }
-               if ( $user->mEmail || $user->mToken !== self::INVALID_TOKEN || $canAuthenticate ) {
+               if ( $user->mEmail || $user->mToken !== self::INVALID_TOKEN ||
+                       AuthManager::singleton()->userCanAuthenticate( $name )
+               ) {
                        // User exists. Steal it?
                        if ( !$options['steal'] ) {
                                return null;
                        }
 
-                       if ( $wgDisableAuthManager ) {
-                               $nopass = PasswordFactory::newInvalidPassword()->toString();
-                               $dbw->update(
-                                       'user',
-                                       [
-                                               'user_password' => $nopass,
-                                               'user_newpassword' => $nopass,
-                                               'user_newpass_time' => null,
-                                       ],
-                                       [ 'user_id' => $user->getId() ],
-                                       __METHOD__
-                               );
-                       } else {
-                               AuthManager::singleton()->revokeAccessForUser( $name );
-                       }
+                       AuthManager::singleton()->revokeAccessForUser( $name );
 
                        $user->invalidateEmail();
                        $user->mToken = self::INVALID_TOKEN;
@@ -2508,31 +2469,7 @@ class User implements IDBAccessObject {
         * @return bool
         */
        public function setPassword( $str ) {
-               global $wgAuth, $wgDisableAuthManager;
-
-               if ( !$wgDisableAuthManager ) {
-                       return $this->setPasswordInternal( $str );
-               }
-
-               if ( $str !== null ) {
-                       if ( !$wgAuth->allowPasswordChange() ) {
-                               throw new PasswordError( wfMessage( 'password-change-forbidden' )->text() );
-                       }
-
-                       $status = $this->checkPasswordValidity( $str );
-                       if ( !$status->isGood() ) {
-                               throw new PasswordError( $status->getMessage()->text() );
-                       }
-               }
-
-               if ( !$wgAuth->setPassword( $this, $str ) ) {
-                       throw new PasswordError( wfMessage( 'externaldberror' )->text() );
-               }
-
-               $this->setOption( 'watchlisttoken', false );
-               $this->setPasswordInternal( $str );
-
-               return true;
+               return $this->setPasswordInternal( $str );
        }
 
        /**
@@ -2544,16 +2481,7 @@ class User implements IDBAccessObject {
         *  through the web interface.
         */
        public function setInternalPassword( $str ) {
-               global $wgAuth, $wgDisableAuthManager;
-
-               if ( !$wgDisableAuthManager ) {
-                       $this->setPasswordInternal( $str );
-               }
-
-               if ( $wgAuth->allowSetLocalPassword() ) {
-                       $this->setOption( 'watchlisttoken', false );
-                       $this->setPasswordInternal( $str );
-               }
+               $this->setPasswordInternal( $str );
        }
 
        /**
@@ -2565,55 +2493,26 @@ class User implements IDBAccessObject {
         * @return bool Success
         */
        private function setPasswordInternal( $str ) {
-               global $wgDisableAuthManager;
-
-               if ( $wgDisableAuthManager ) {
-                       $id = self::idFromName( $this->getName(), self::READ_LATEST );
-                       if ( $id == 0 ) {
-                               throw new LogicException( 'Cannot set a password for a user that is not in the database.' );
-                       }
-
-                       $passwordFactory = new PasswordFactory();
-                       $passwordFactory->init( RequestContext::getMain()->getConfig() );
-                       $dbw = wfGetDB( DB_MASTER );
-                       $dbw->update(
-                               'user',
-                               [
-                                       'user_password' => $passwordFactory->newFromPlaintext( $str )->toString(),
-                                       'user_newpassword' => PasswordFactory::newInvalidPassword()->toString(),
-                                       'user_newpass_time' => $dbw->timestampOrNull( null ),
-                               ],
-                               [
-                                       'user_id' => $id,
-                               ],
-                               __METHOD__
-                       );
-
-                       // When the main password is changed, invalidate all bot passwords too
-                       BotPassword::invalidateAllPasswordsForUser( $this->getName() );
-               } else {
-                       $manager = AuthManager::singleton();
-
-                       // If the user doesn't exist yet, fail
-                       if ( !$manager->userExists( $this->getName() ) ) {
-                               throw new LogicException( 'Cannot set a password for a user that is not in the database.' );
-                       }
+               $manager = AuthManager::singleton();
 
-                       $status = $this->changeAuthenticationData( [
-                               'username' => $this->getName(),
-                               'password' => $str,
-                               'retype' => $str,
-                       ] );
-                       if ( !$status->isGood() ) {
-                               \MediaWiki\Logger\LoggerFactory::getInstance( 'authentication' )
-                                       ->info( __METHOD__ . ': Password change rejected: '
-                                               . $status->getWikiText( null, null, 'en' ) );
-                               return false;
-                       }
+               // If the user doesn't exist yet, fail
+               if ( !$manager->userExists( $this->getName() ) ) {
+                       throw new LogicException( 'Cannot set a password for a user that is not in the database.' );
+               }
 
-                       $this->setOption( 'watchlisttoken', false );
+               $status = $this->changeAuthenticationData( [
+                       'username' => $this->getName(),
+                       'password' => $str,
+                       'retype' => $str,
+               ] );
+               if ( !$status->isGood() ) {
+                       \MediaWiki\Logger\LoggerFactory::getInstance( 'authentication' )
+                               ->info( __METHOD__ . ': Password change rejected: '
+                                       . $status->getWikiText( null, null, 'en' ) );
+                       return false;
                }
 
+               $this->setOption( 'watchlisttoken', false );
                SessionManager::singleton()->invalidateSessionsForUser( $this );
 
                return true;
@@ -2632,12 +2531,6 @@ class User implements IDBAccessObject {
         * @since 1.27
         */
        public function changeAuthenticationData( array $data ) {
-               global $wgDisableAuthManager;
-               if ( $wgDisableAuthManager ) {
-                       throw new LogicException( __METHOD__ . ' cannot be called when $wgDisableAuthManager '
-                               . 'is true' );
-               }
-
                $manager = AuthManager::singleton();
                $reqs = $manager->getAuthenticationRequests( AuthManager::ACTION_CHANGE, $this );
                $reqs = AuthenticationRequest::loadRequestsFromSubmission( $reqs, $data );
@@ -2723,32 +2616,7 @@ class User implements IDBAccessObject {
         * @param bool $throttle If true, reset the throttle timestamp to the present
         */
        public function setNewpassword( $str, $throttle = true ) {
-               global $wgDisableAuthManager;
-
-               if ( $wgDisableAuthManager ) {
-                       $id = $this->getId();
-                       if ( $id == 0 ) {
-                               throw new LogicException( 'Cannot set new password for a user that is not in the database.' );
-                       }
-
-                       $dbw = wfGetDB( DB_MASTER );
-
-                       $passwordFactory = new PasswordFactory();
-                       $passwordFactory->init( RequestContext::getMain()->getConfig() );
-                       $update = [
-                               'user_newpassword' => $passwordFactory->newFromPlaintext( $str )->toString(),
-                       ];
-
-                       if ( $str === null ) {
-                               $update['user_newpass_time'] = null;
-                       } elseif ( $throttle ) {
-                               $update['user_newpass_time'] = $dbw->timestamp();
-                       }
-
-                       $dbw->update( 'user', $update, [ 'user_id' => $id ], __METHOD__ );
-               } else {
-                       throw new BadMethodCallException( __METHOD__ . ' has been removed in 1.27' );
-               }
+               throw new BadMethodCallException( __METHOD__ . ' has been removed in 1.27' );
        }
 
        /**
@@ -2758,33 +2626,7 @@ class User implements IDBAccessObject {
         * @return bool
         */
        public function isPasswordReminderThrottled() {
-               global $wgPasswordReminderResendTime, $wgDisableAuthManager;
-
-               if ( $wgDisableAuthManager ) {
-                       if ( !$wgPasswordReminderResendTime ) {
-                               return false;
-                       }
-
-                       $this->load();
-
-                       $db = ( $this->queryFlagsUsed & self::READ_LATEST )
-                               ? wfGetDB( DB_MASTER )
-                               : wfGetDB( DB_SLAVE );
-                       $newpassTime = $db->selectField(
-                               'user',
-                               'user_newpass_time',
-                               [ 'user_id' => $this->getId() ],
-                               __METHOD__
-                       );
-
-                       if ( $newpassTime === null ) {
-                               return false;
-                       }
-                       $expiry = wfTimestamp( TS_UNIX, $newpassTime ) + $wgPasswordReminderResendTime * 3600;
-                       return time() < $expiry;
-               } else {
-                       throw new BadMethodCallException( __METHOD__ . ' has been removed in 1.27' );
-               }
+               throw new BadMethodCallException( __METHOD__ . ' has been removed in 1.27' );
        }
 
        /**
@@ -4280,87 +4122,27 @@ class User implements IDBAccessObject {
         * @return bool True if the given password is correct, otherwise False
         */
        public function checkPassword( $password ) {
-               global $wgAuth, $wgLegacyEncoding, $wgDisableAuthManager;
-
-               if ( $wgDisableAuthManager ) {
-                       $this->load();
-
-                       // Some passwords will give a fatal Status, which means there is
-                       // some sort of technical or security reason for this password to
-                       // be completely invalid and should never be checked (e.g., T64685)
-                       if ( !$this->checkPasswordValidity( $password )->isOK() ) {
-                               return false;
-                       }
-
-                       // Certain authentication plugins do NOT want to save
-                       // domain passwords in a mysql database, so we should
-                       // check this (in case $wgAuth->strict() is false).
-                       if ( $wgAuth->authenticate( $this->getName(), $password ) ) {
+               $manager = AuthManager::singleton();
+               $reqs = AuthenticationRequest::loadRequestsFromSubmission(
+                       $manager->getAuthenticationRequests( AuthManager::ACTION_LOGIN ),
+                       [
+                               'username' => $this->getName(),
+                               'password' => $password,
+                       ]
+               );
+               $res = AuthManager::singleton()->beginAuthentication( $reqs, 'null:' );
+               switch ( $res->status ) {
+                       case AuthenticationResponse::PASS:
                                return true;
-                       } elseif ( $wgAuth->strict() ) {
-                               // Auth plugin doesn't allow local authentication
-                               return false;
-                       } elseif ( $wgAuth->strictUserAuth( $this->getName() ) ) {
-                               // Auth plugin doesn't allow local authentication for this user name
+                       case AuthenticationResponse::FAIL:
+                               // Hope it's not a PreAuthenticationProvider that failed...
+                               \MediaWiki\Logger\LoggerFactory::getInstance( 'authentication' )
+                                       ->info( __METHOD__ . ': Authentication failed: ' . $res->message->plain() );
                                return false;
-                       }
-
-                       $passwordFactory = new PasswordFactory();
-                       $passwordFactory->init( RequestContext::getMain()->getConfig() );
-                       $db = ( $this->queryFlagsUsed & self::READ_LATEST )
-                               ? wfGetDB( DB_MASTER )
-                               : wfGetDB( DB_SLAVE );
-
-                       try {
-                               $mPassword = $passwordFactory->newFromCiphertext( $db->selectField(
-                                       'user', 'user_password', [ 'user_id' => $this->getId() ], __METHOD__
-                               ) );
-                       } catch ( PasswordError $e ) {
-                               wfDebug( 'Invalid password hash found in database.' );
-                               $mPassword = PasswordFactory::newInvalidPassword();
-                       }
-
-                       if ( !$mPassword->equals( $password ) ) {
-                               if ( $wgLegacyEncoding ) {
-                                       // Some wikis were converted from ISO 8859-1 to UTF-8, the passwords can't be converted
-                                       // Check for this with iconv
-                                       $cp1252Password = iconv( 'UTF-8', 'WINDOWS-1252//TRANSLIT', $password );
-                                       if ( $cp1252Password === $password || !$mPassword->equals( $cp1252Password ) ) {
-                                               return false;
-                                       }
-                               } else {
-                                       return false;
-                               }
-                       }
-
-                       if ( $passwordFactory->needsUpdate( $mPassword ) && !wfReadOnly() ) {
-                               $this->setPasswordInternal( $password );
-                       }
-
-                       return true;
-               } else {
-                       $manager = AuthManager::singleton();
-                       $reqs = AuthenticationRequest::loadRequestsFromSubmission(
-                               $manager->getAuthenticationRequests( AuthManager::ACTION_LOGIN ),
-                               [
-                                       'username' => $this->getName(),
-                                       'password' => $password,
-                               ]
-                       );
-                       $res = AuthManager::singleton()->beginAuthentication( $reqs, 'null:' );
-                       switch ( $res->status ) {
-                               case AuthenticationResponse::PASS:
-                                       return true;
-                               case AuthenticationResponse::FAIL:
-                                       // Hope it's not a PreAuthenticationProvider that failed...
-                                       \MediaWiki\Logger\LoggerFactory::getInstance( 'authentication' )
-                                               ->info( __METHOD__ . ': Authentication failed: ' . $res->message->plain() );
-                                       return false;
-                               default:
-                                       throw new BadMethodCallException(
-                                               'AuthManager returned a response unsupported by ' . __METHOD__
-                                       );
-                       }
+                       default:
+                               throw new BadMethodCallException(
+                                       'AuthManager returned a response unsupported by ' . __METHOD__
+                               );
                }
        }
 
@@ -4373,43 +4155,8 @@ class User implements IDBAccessObject {
         * @return bool True if matches, false otherwise
         */
        public function checkTemporaryPassword( $plaintext ) {
-               global $wgNewPasswordExpiry, $wgDisableAuthManager;
-
-               if ( $wgDisableAuthManager ) {
-                       $this->load();
-
-                       $passwordFactory = new PasswordFactory();
-                       $passwordFactory->init( RequestContext::getMain()->getConfig() );
-                       $db = ( $this->queryFlagsUsed & self::READ_LATEST )
-                               ? wfGetDB( DB_MASTER )
-                               : wfGetDB( DB_SLAVE );
-
-                       $row = $db->selectRow(
-                               'user',
-                               [ 'user_newpassword', 'user_newpass_time' ],
-                               [ 'user_id' => $this->getId() ],
-                               __METHOD__
-                       );
-                       try {
-                               $newPassword = $passwordFactory->newFromCiphertext( $row->user_newpassword );
-                       } catch ( PasswordError $e ) {
-                               wfDebug( 'Invalid password hash found in database.' );
-                               $newPassword = PasswordFactory::newInvalidPassword();
-                       }
-
-                       if ( $newPassword->equals( $plaintext ) ) {
-                               if ( is_null( $row->user_newpass_time ) ) {
-                                       return true;
-                               }
-                               $expiry = wfTimestamp( TS_UNIX, $row->user_newpass_time ) + $wgNewPasswordExpiry;
-                               return ( time() < $expiry );
-                       } else {
-                               return false;
-                       }
-               } else {
-                       // Can't check the temporary password individually.
-                       return $this->checkPassword( $plaintext );
-               }
+               // Can't check the temporary password individually.
+               return $this->checkPassword( $plaintext );
        }
 
        /**
@@ -5286,45 +5033,10 @@ class User implements IDBAccessObject {
         *     - false will be converted to 'create' if this object is the same as
         *       $wgUser and to 'create2' otherwise
         * @param string $reason User supplied reason
-        * @return int|bool True if not $wgNewUserLog or not $wgDisableAuthManager;
-        *   otherwise ID of log item or 0 on failure
+        * @return bool true
         */
        public function addNewUserLogEntry( $action = false, $reason = '' ) {
-               global $wgUser, $wgNewUserLog, $wgDisableAuthManager;
-               if ( !$wgDisableAuthManager || empty( $wgNewUserLog ) ) {
-                       return true; // disabled
-               }
-
-               if ( $action === true ) {
-                       $action = 'byemail';
-               } elseif ( $action === false ) {
-                       if ( $this->equals( $wgUser ) ) {
-                               $action = 'create';
-                       } else {
-                               $action = 'create2';
-                       }
-               }
-
-               if ( $action === 'create' || $action === 'autocreate' ) {
-                       $performer = $this;
-               } else {
-                       $performer = $wgUser;
-               }
-
-               $logEntry = new ManualLogEntry( 'newusers', $action );
-               $logEntry->setPerformer( $performer );
-               $logEntry->setTarget( $this->getUserPage() );
-               $logEntry->setComment( $reason );
-               $logEntry->setParameters( [
-                       '4::userid' => $this->getId(),
-               ] );
-               $logid = $logEntry->insert();
-
-               if ( $action !== 'autocreate' ) {
-                       $logEntry->publish( $logid );
-               }
-
-               return (int)$logid;
+               return true; // disabled
        }
 
        /**
index 2ebc9ed..395ce37 100644 (file)
@@ -11,7 +11,7 @@
  *     $gen = new AutoloadGenerator( __DIR__ );
  *     $gen->readDir( __DIR__ . '/includes' );
  *     $gen->readFile( __DIR__ . '/foo.php' )
- *     $gen->generateAutoload();
+ *     $gen->getAutoload();
  */
 class AutoloadGenerator {
        const FILETYPE_JSON = 'json';
index 62946bb..80df33f 100644 (file)
        "passwordreset-emailelement": "اسم {{GENDER:$1\n|المستخدم|المستخدمة}}: \n$1\n\nكلمة السر المؤقتة: \n$2",
        "passwordreset-emailsentemail": "إذا كان هذا العنوان البريد مرتبط بحسابك، من ثم سيتم إرسال بريد إلكتروني لإعادة تعيين كلمة السر.",
        "passwordreset-emailsentusername": "إذا كان هناك عنوان بريد إلكتروني مرتبط بهذا المستخدم، ثم سيتم إرسال بريد إلكتروني لإعادة تعيين كلمة السر.",
-       "passwordreset-emailsent-capture": "أُرسل بريد إلكتروني لإعادة ضبط كلمة السر، وهو معروض بالأسفل.",
-       "passwordreset-emailerror-capture": "تم توليد رسالة بريد إلكتروني لتصفير كلمة السر نصّه التالي، إلا أنه تعذّر إرسال الرّسالة إلى {{GENDER:$2|المستخدم|المستخدمة}}: $1",
        "passwordreset-invalideamil": "عنوان بريد إلكتروني غير صالح",
        "changeemail": "تغيير أو إزالة عنوان البريد الإلكتروني",
        "changeemail-header": "إكمال هذا النموذج لتغيير عنوان البريد الإلكتروني الخاص بك. إذا كنت ترغب في إزالة جمعية أي عنوان البريد الإلكتروني من حسابك، وترك الفراغ عنوان البريد الإلكتروني الجديد عند تقديم النموذج",
-       "changeemail-passwordrequired": "تحتاج إلى إدخال كلمة السر الخاصة بك لتأكيد هذا التغيير.",
        "changeemail-no-info": "يجب تسجيل الدخول للوصول إلى هذه الصفحة مباشرة.",
        "changeemail-oldemail": "عنوان البريد الإلكتروني الحالي:",
        "changeemail-newemail": "عنوان البريد الإلكتروني الجديد:",
        "undo-nochange": "التعديل يبدو أنه قد تم الترجع عنه بالفعل.",
        "undo-summary": "الرجوع عن التعديل $1 بواسطة [[Special:Contributions/$2|$2]] ([[User talk:$2|نقاش]])",
        "undo-summary-username-hidden": "الرجوع عن المراجعة $1 التي أجراها مستخدمي مخفي",
-       "cantcreateaccounttitle": "لا يمكن إنشاء حساب",
        "cantcreateaccount-text": "إنشاء الحسابات من عنوان الأيبي هذا ('''$1''') تم منعه بواسطة [[User:$3|$3]].\n\nالسبب المعطى بواسطة $3 هو ''$2''",
        "cantcreateaccount-range-text": "إنشاء الحسابات من عناوين الآيبي في النطاق <strong>$1</strong>، التي تحتوي على الآيبي الخاص بك (<strong>$4</strong>)، قد منعها [[User:$3|$3]].\n\nالسبب المعطى بواسطة $3 هو <em>$2</em>",
        "viewpagelogs": "اعرض سجلات هذه الصفحة",
index 8f881e0..0e51642 100644 (file)
        "undo-failure": "الرجوع فى التعديل ما نفعش علشان فى تعديلات متعاكسة حصلت فى الصفحة.",
        "undo-norev": "الرجوع فى التعديل ما نفعش علشان هو يا إما مش موجود أو انه إتمسح.",
        "undo-summary": "الرجوع فى التعديل $1 بتاع [[Special:Contributions/$2|$2]] ([[User talk:$2|نقاش]])",
-       "cantcreateaccounttitle": "مش ممكن فتح حساب",
        "cantcreateaccount-text": "فتح الحسابات من عنوان الأيبى دا ('''$1''') منعه [[User:$3|$3]].\n\nالسبب إللى إداه $3 هو ''$2''",
        "viewpagelogs": "عرض السجلات للصفحه دى",
        "nohistory": "الصفحة دى ما لهاش تاريخ تعديل.",
index 7325d39..4c8c6d0 100644 (file)
        "passwordreset-emailelement": "Nome d'usuariu: \n$1\n\nContraseña temporal: \n$2",
        "passwordreset-emailsentemail": "Si esta direición de corréu electrónicu ta asociada cola to cuenta, unviaráse un corréu pa reaniciar la contraseña.",
        "passwordreset-emailsentusername": "Si hai una direición de corréu electrónicu asociada con esti nome d'usuariu, unviaráse un corréu electrónicu pa reaniciar la contraseña.",
-       "passwordreset-emailsent-capture": "Unvióse un corréu electrónicu pa reaniciar la contraseña, que s'amuesa abaxo.",
-       "passwordreset-emailerror-capture": "Unvióse un corréu electrónicu pa reaniciar la contraseña, que s'amuesa abaxo, pero falló l'unviu {{GENDER:$2|al usuariu|a la usuaria}}: $1",
        "passwordreset-emailsent-capture2": "{{PLURAL:$1|Unvióse'l corréu|Unviáronse los correos}} de reaniciu de contraseña. {{PLURAL:$1|El nome d'usuariu y la contraseña|La llista de nomes d'usuarios y contraseñes}} amuésase de siguío.",
        "passwordreset-emailerror-capture2": "Nun foi posible mandar un corréu electrónicu {{Gender:$2|al usuariu|a la usuaria}}: $1 {{PLURAL:$3|El nome d'usuariu y la contraseña|La llista de nomes d'usuarios y contraseñes}} amuésase de siguío.",
        "passwordreset-nocaller": "Tien d'apurrise un llamador",
        "passwordreset-nodata": "Nun s'apurrió nin un nome d'usuariu nin una dirección de corréu electrónicu",
        "changeemail": "Camudar o desaniciar la dirección de corréu electrónicu",
        "changeemail-header": "Completa esti formulariu pa camudar la dirección de corréu electrónicu. Si quies desaniciar l'asociación de cualquier dirección de corréu electrónicu de la to cuenta, dexa en blancu la nueva dirección de corréu electrónicu cuando unvies el formulariu.",
-       "changeemail-passwordrequired": "Vas tener qu'escribir la contraseña pa confirmar esti cambéu.",
        "changeemail-no-info": "Tien d'aniciar sesión pa entrar direutamente a esta páxina.",
        "changeemail-oldemail": "Direición de corréu electrónicu actual:",
        "changeemail-newemail": "Direición de corréu electrónicu nueva:",
        "undo-nochange": "Paez que la edición yá ta desfecha.",
        "undo-summary": "Esfacer la revisión $1 de [[Special:Contributions/$2|$2]] ([[User talk:$2|alderique]])",
        "undo-summary-username-hidden": "Desfacer la revisión $1 d'un usuariu tapecíu",
-       "cantcreateaccounttitle": "Nun pue crease la cuenta",
        "cantcreateaccount-text": "[[User:$3|$3]] bloquió la creación de cuentes dende esta direición IP (<strong>$1</strong>).\n\nEl motivu dau por $3 ye <em>$2</em>",
        "cantcreateaccount-range-text": "La creación de cuentes dende direiciones IP del rangu <strong>$1</strong>, qu'incluye la so direición IP (<strong>$4</strong>), ta bloquiada pol usuariu [[User:$3|$3]].\n\nLa razón dada por $3 ye <em>$2</em>.",
        "viewpagelogs": "Ver los rexistros d'esta páxina",
index 8554e0b..dfa4e2a 100644 (file)
        "undo-failure": "Dəyişikliklərin toqquşması nəticəsində geriyə qaytarma işi uğursuz oldu.",
        "undo-norev": "Düzəlişlər geri qaytarıla bilinmir, çünki onlar ya mövcüd deyil, ya da silinib.",
        "undo-summary": "$1 dəyişikliyi [[Special:Contributions/$2|$2]] ([[User talk:$2|Müzakirə]]) tərəfindən geri alındı.",
-       "cantcreateaccounttitle": "Hesab açılmır.",
        "cantcreateaccount-text": "Bu IP ünvanından ('''$1''') istifadəçi hesabı yaradılması [[User:$3|$3]] tərəfindən əngəllənmişdir.\n\n$3 tərəfindən verilən səbəb ''$2''",
        "viewpagelogs": "Bu səhifə ilə bağlı qeydlərə bax",
        "nohistory": "Bu səhifənin dəyişikliklər tarixçəsi mövcud deyil.",
index abdc239..c6a1dba 100644 (file)
        "passwordreset-emailtext-user": "{{SITENAME}} سایتیندا، $1 ایستیفاده‌چی، سیزین اوردا ($4) حسابینیزین رمزینی یئنیله‌مک ایستگی وئریب‌دیر. آشاغیداکی {{PLURAL:$3|ایستیفاده‌چی|ایستیفاده‌چیلر}} بو ایمیل ایله ایلگیلیدیرلر:\n\n$2\n\nبو گئچیجی {{PLURAL:$3|رمز|رمزلر}}، {{PLURAL:$5|بیر|$5گون}} سونرا واختلاری قورتاراجاق‌دیر. \nسیز گرک ایندی گیریب و بیر یئنی رمز سئچه‌سینیز. باشقا آدام بو ایستَگی وئرمیش‌سه، یوخسا سیز اسکی رمزینیزی یادا گتیرمیشسینیزسه، و داها اونو چئویرمک ایسته‌میرسینیزسه، بو مئساژی سایماییب و اسکی رمزینیزی ایشلدمگه داوام ائده بیلرسینیز.",
        "passwordreset-emailelement": "ایشلدن آدی: \n$1\n\nگئچیجی رمز: \n$2",
        "passwordreset-emailsentemail": "بۇ ایمئیل آدرسی حسابینیزا ثبت اوْلونموشسا٬ بیر رمز یئنیله‌مه ایمئیلی گؤندریله‌جکدیر.",
-       "passwordreset-emailsent-capture": "آشاغیدا گؤستریلن کیمی بیر رمز یئنیله‌مه ایمیلی گؤندریلیب‌دیر.",
-       "passwordreset-emailerror-capture": "آشاغیدا گؤستریلن کیمی بیر رمز یئنیله‌مه ایمیلی یارادیلیب‌دیر، اما {{GENDER:$2ایستیفاده‌چی}}‌یه گؤندرمگی باشاریلی اولمادی: $1",
        "changeemail": "ایمیل آدرسینی دَییشدیر یا سیل",
        "changeemail-header": "ایمیل آدرسیزی دَییشدیرمک اوچون بو فورمو دولدورون. حسابیزا بوتون ایمیل‌لرین ارتباطینی کسمک اوچون، یئنی ایمیل آدرسینی بوش ساخلایین.",
-       "changeemail-passwordrequired": "بو دَییشمه‌نی دوغرولاماق اوچون، رمزینیزی یازمالیسیز.",
        "changeemail-no-info": "بو صحیفه‌نی دوغرو گؤردوگونوز اوچون سیستمه گیرمه‌لیسینیز.",
        "changeemail-oldemail": "ایندیکی ایمیل آدرس:",
        "changeemail-newemail": "یئنی ایمیل آدرسی:",
        "watchthis": "بو صفحه‌نی ایزله",
        "savearticle": "صفحه‌نی ذخیره ائت",
        "savechanges": "دَییشیکلیکلری ذخیره ائت",
-       "publishchanges": "دَییشیکلیکلری یای",
+       "publishpage": "صفحه‌نی یاییملا",
+       "publishchanges": "دَییشیک‌لیک‌لری یاییملا",
        "preview": "اؤن‌گؤستریش",
        "showpreview": "سیناق گؤستریش",
        "showdiff": "دَییشیکلیکلری گؤستر",
        "undo-nochange": "نظره گلیر دَییشدیرمه قاباغجادان قایتاریلیب.",
        "undo-summary": "$1 دییشیک‌لیک [[Special:Contributions/$2|$2]] ([[User talk:$2|دانیشیق]]) طرفین‌دن قایتاریلدی.",
        "undo-summary-username-hidden": "گیزلی ایستیفاده‌چی ایله ائدیلمیش $1 نوسخه‌سینی قایتارماق",
-       "cantcreateaccounttitle": "حساب یارادماق اولمور",
        "cantcreateaccount-text": "بو ای پی عنوانین‌دان ('$1) ایستیفاده‌چی حسابی یارادیلماسی [[User:$3|$3]] طرفین‌دن انگللنمیش‌دیر.\n\n$3 طرفین‌دن وئریلن سبب '$2",
        "cantcreateaccount-range-text": "<strong>$1</strong> آی‌پی آدرس آرالیغیندان حساب یارانماق، [[User:$3|$3]] ایشلدنی طرفیندن یاساقلانیب‌دیر. سیزین‌ده آی‌پی آدرسیز (<strong>$4</strong>) بو آرادادیر.\n\n$3 طرفین‌دن وئریلن سبب بودور: «$2»",
        "viewpagelogs": "بۇ صفحه‌نین قئیدلرینه باخ",
index 84abebd..0980639 100644 (file)
        "passwordreset-emailelement": "Ҡулланыусы исеме: \n$1\n\nВаҡытлыса серһүҙ: \n$2",
        "passwordreset-emailsentemail": "Серһүҙҙе ташлау тураһындағы мәғлүмәт менән электрон почта аша хат ебәрелде.",
        "passwordreset-emailsentusername": "Әгәр был ҡатнашыусының исеменә бәйле  электрон почтаһының адресы булһа, ул саҡта  серһүҙҙе тергеҙеү өсөн  хат ебәреләсәк.",
-       "passwordreset-emailsent-capture": "Серһүҙҙе ташлау тураһындағы мәғлүмәт менән электрон хат ебәрелде, уның тексы түбәндә бирелә:",
-       "passwordreset-emailerror-capture": "Серһүҙҙе ташлау тураһында хәбәр итеүсе электрон хат булдырылғайны, ләкин уны  {{GENDER:$2|kullanıcıya}} түбәндәге сәбәп арҡаһында ебәреп булманы: $1",
        "passwordreset-invalideamil": "Электрон почта адресы ҡабул ителмәй",
        "changeemail": "Электрон почта адресын үҙгәртергә",
        "changeemail-header": "Электрон почта адресын үҙгәртеү",
-       "changeemail-passwordrequired": "Әлеге үҙгәрештәрҙе раҫлау өсөн, Һеҙгә ҡулланыусының серһүҙен яҙырға кәрәк",
        "changeemail-no-info": "Был биткә туранан ирешеү өсөн һеҙгә системала танылыу кәрәк.",
        "changeemail-oldemail": "Хәҙерге электрон почта адресы:",
        "changeemail-newemail": "Яңы электрон почта адресы:",
        "undo-nochange": "Төҙәтеү кире ҡайтарылған.",
        "undo-summary": "[[Special:Contributions/$2|$2]] ҡулланыусыһының ([[User talk:$2|фекер алышыу]]) $1 үҙгәртеүенән баш тартыу",
        "undo-summary-username-hidden": "Исеме йәшерелгән ҡатнашыусының төҙәтеүен  $1 кире ҡағыу",
-       "cantcreateaccounttitle": "Иҫәп яҙыуын яһап булмай",
        "cantcreateaccount-text": "Был IP-адрестан (<b>$1</b>) иҫәп яҙыуҙары булдырыу [[User:$3|$3]] тарафынан тыйылған.\n\n$3 белдергән сәбәп: ''$2''",
        "cantcreateaccount-range-text": "{{GENDER:$3|Ҡатнашыусы}} [[User:$3|$3]] һеҙҙең IP-адрес ингән (<strong>$4</strong>) <strong>$1</strong> диапозонында иҫәп яҙмаһын булдырмаҫҡа {{GENDER:$3|тыйыу}} ҡуйҙы.\n\nОшо сәбәп күһәтелгән: $2.",
        "viewpagelogs": "Был биттең яҙмаларын ҡарарға",
index 2396035..fceddbc 100644 (file)
        "post-expand-template-argument-warning": "'''Obocht:''' De Seitn enthoit mindastns oa Argument in da Vorlog, wo expandiat z grouss is. \nDe Parameta wean ignoriad.",
        "post-expand-template-argument-category": "Seitn mid ignoriadn Voalognparametan",
        "undo-summary": "Änderrung $1 voh [[Special:Contributions/$2|$2]] ([[User talk:$2|Diskussión]]) ryckgängig gmocht.",
-       "cantcreateaccounttitle": "Benutzerkonto kå ned erstöd wern",
        "viewpagelogs": "Logbiacha fia de Datei ozoagn",
        "currentrev": "Aktuelle Versión",
        "currentrev-asof": "Letzte Version vo $1",
index b3d7e8c..abacb5a 100644 (file)
        "passwordreset-emailtext-user": "Paragamit $1 sa {{SITENAME}} naghahagad nin sarong pagiromdom kan detalye nin saimong panindog para sa {{SITENAME}}\n($4). An minasunod na paragamit {{PLURAL:$3|panindog iyo an|mga panindog iyo an}} na asosyado kaining e-koreong address:\n\n$2\n\n\n{{PLURAL:$3|Ining temporaryong sekretong panlaog|Ining mga temporaryong panlaog}} mapapaso sa {{PLURAL:$5|sarong aldaw|$5 mga aldaw}}.\nIka dapat na maglaog asin magpili nin sarong bagong sekretong panlaog ngunyan. Kun ibang tawo an naghimo kaining kahagadan, o kun saimo nang nagiromdoman an saimong orihinal na sekretong panlaog, asin habo mo nang ribayan ini, ipasapara mo na sana an mensaheng ini asin ipadagos mo nang gamiton an saimong lumang sekretong panlaog.",
        "passwordreset-emailelement": "Paragamit-ngaran: \n$1\n\nTemporaryong sekretong panlaog: \n$2",
        "passwordreset-emailsentemail": "Sarong e-surat sa pagliliwat kan sekretong panlaog an ipinadara na.",
-       "passwordreset-emailsent-capture": "Sarong e-surat sa pagliliwat kan sekretong panlaog an ipinadara na, yaon ipinapahiling sa ibaba.",
-       "passwordreset-emailerror-capture": "Sarong e-surat sa pagliliwat kan sekretong panlaog an pinagpuyos na, yaon ipinapahiling sa ibaba, alagad sa pagpapadara kaini sa {{GENDER:$2|paragamit}} nagpalya: $1",
        "changeemail": "Ribayan an e-koreong address",
        "changeemail-header": "Ribayan an panindog na e-koreong address",
        "changeemail-no-info": "Ika dapat nakalaog na tanganing direktang makagamit kaining pahina.",
        "undo-norev": "An pagliwat dae tabi magigibo nin huli ta ini bakong eksistido o pinagpura na.",
        "undo-summary": "Dae idagos an rebisyon $1 sa [[Special:Contributions/$2|$2]] ([[User talk:$2|olay]])",
        "undo-summary-username-hidden": "Dae idagos an rebisyon sa $1 nin sarong nakatago na paragamit",
-       "cantcreateaccounttitle": "Dai makagibo nin account",
        "cantcreateaccount-text": "An pagbukas nin account halì sa IP na ('''$1''') binágat ni [[User:$3|$3]].\n\n''$2'' an rason na pigtao ni $3",
        "viewpagelogs": "\nHilingon an mga katalaanan para sa pahinang ini",
        "nohistory": "Mayong paghirá nin uusipón sa pahinang ini.",
index fd87b0f..e5a0f8d 100644 (file)
        "passwordreset-emailelement": "Імя ўдзельніка: \n$1\n\nЧасовы пароль: \n$2",
        "passwordreset-emailsentemail": "Калі гэты адрас электроннай пошты далучаны да вашага рахунку, тады будзе дасланы ліст пра скідваньне паролю.",
        "passwordreset-emailsentusername": "Калі ёсьць адрас электроннай пошты, злучаны з гэтым імем удзельніка, тады будзе дасланы ліст пра скідваньне паролю.",
-       "passwordreset-emailsent-capture": "Ліст пра скіданьне паролю быў дасланы, што паказана ніжэй.",
-       "passwordreset-emailerror-capture": "Ліст пра скіданьне паролю быў створаны і паказаны ніжэй, але не ўдалося адправіць яго {{GENDER:$2|ўдзельніку|ўдзельніцы}}: $1",
        "passwordreset-emailsent-capture2": "{{PLURAL:$1|Электронны ліст|Электронныя лісты}} скіданьня паролю {{PLURAL:$1|быў дасланы|былі дасланыя}}. {{PLURAL:$1|Імя ўдзельніка і пароль|Сьпіс імёнаў удзельнікаў і паролі}} паказаныя ніжэй.",
        "passwordreset-emailerror-capture2": "Не атрымалася даслаць {{GENDER:$2|удзельніку|удзельніцы}} ліст электроннай поштай: $1 {{PLURAL:$3|Імя ўдзельніка і пароль|Сьпіс імёнаў удзельнікаў і паролі}} паказаныя ніжэй.",
        "passwordreset-nocaller": "Мусіць быць пададзены той, хто робіць выклік",
        "passwordreset-nodata": "Не былі пададзеныя ні імя ўдзельніка, ні адрас электроннай пошты",
        "changeemail": "Зьмяніць або выдаліць адрас электроннай пошты",
        "changeemail-header": "Запоўніце гэтую форму, каб зьмяніць ваш адрас электроннай пошты. Калі вы жадаеце выдаліць адрас электроннай пошты, далучаны да вашага рахунку, пакіньце поле новага адрасу электроннай пошты пустым пры запаўненьні формы.",
-       "changeemail-passwordrequired": "Вам трэба будзе ўвесьці ваш пароль, каб пацьвердзіць гэтую зьмену.",
        "changeemail-no-info": "Для непасрэднага доступу да гэтай старонкі Вам неабходна ўвайсьці ў сыстэму.",
        "changeemail-oldemail": "Цяперашні адрас электроннай пошты:",
        "changeemail-newemail": "Новы адрас электроннай пошты:",
        "undo-nochange": "Выглядае, што праўка ўжо была адмененая.",
        "undo-summary": "Скасаваньне праўкі $1 {{GENDER:$2|удзельніка|удзельніцы}} [[Special:Contributions/$2|$2]] ([[User talk:$2|гутаркі]])",
        "undo-summary-username-hidden": "Вэрсія $1 скасаваная схаваным удзельнікам",
-       "cantcreateaccounttitle": "Немагчыма стварыць рахунак",
        "cantcreateaccount-text": "Стварэньне рахункаў з гэтага IP-адрасу ('''$1''') было заблякаванае [[User:$3|$3]].\n\nПрычына блякаваньня пададзеная $3: ''$2''",
        "cantcreateaccount-range-text": "Стварэньне рахункаў з IP-адрасоў у дыяпазоне <strong>$1</strong>, у які ўваходзіць ваш IP-адрас (<strong>$4</strong>), было забароненае {{GENDER:$3|ўдзельнікам|ўдзельніцай}} [[User:$3|$3]].\n\n{{GENDER:$3|Удзельнікам|Удзельніцай}} $3 была пададзеная наступная прычына: <em>$2</em>.",
        "viewpagelogs": "Паказаць журналы падзеяў для гэтай старонкі",
index a5a984b..42ecee9 100644 (file)
@@ -35,7 +35,8 @@
                        "Miroslav35232",
                        "Ket",
                        "Ricordo.tenerissimo",
-                       "Plamen"
+                       "Plamen",
+                       "Iliev"
                ]
        },
        "tog-underline": "Подчертаване на препратките:",
@@ -77,7 +78,7 @@
        "tog-ccmeonemails": "Получаване на копия на писмата, които пращам на другите потребители",
        "tog-diffonly": "Без показване на съдържанието на страницата при преглед на разлики",
        "tog-showhiddencats": "Показване на скритите категории",
-       "tog-norollbackdiff": "Ð\9fÑ\80опÑ\83Ñ\81кане Ð½Ð° Ñ\80азликоваÑ\82а Ð²Ñ\80Ñ\8aзка Ñ\81лед Ð¸Ð·Ð²Ñ\8aÑ\80Ñ\88ване Ð½Ð° отмяна на редакции",
+       "tog-norollbackdiff": "Ð\9dе Ð¿Ð¾ÐºÐ°Ð·Ð²Ð°Ð¹ Ñ\80азликаÑ\82а Ð¼ÐµÐ¶Ð´Ñ\83 Ñ\80едакÑ\86ииÑ\82е Ñ\81лед отмяна на редакции",
        "tog-useeditwarning": "Предупреждаване при опит за напускане на страница, отворена в режим на редактиране, без да са запазени промените",
        "tog-prefershttps": "Да се използва винаги защитена връзка след влизане",
        "underline-always": "Винаги",
        "protectedinterface": "Тази страница съдържа текст, нужен за работата на системата. Тя е защитена против редактиране, за да се предотвратят възможни злоупотреби.\nЗа извършване на промяна за всички уикита, посетете [https://translatewiki.net/ translatewiki.net], проектът за локализация на MediaWiki.",
        "editinginterface": "<strong>Внимание:</strong> Редактирате страница, която се използва за текстовия интерфейс на софтуера. Промяната й ще повлияе на външния вид на уикито.",
        "translateinterface": "За да добавите или промените преводи за всички уикита, моля, използвайте [https://translatewiki.net/ translatewiki.net], локализиращия проект на МедияУики.",
-       "cascadeprotected": "Тази страница е защитена против редактиране, защото е включена в {{PLURAL:$1|следната страница, която от своя страна има|следните страници, които от своя страна имат}} каскадна защита:\n$2",
+       "cascadeprotected": "Тази страница е защитена против редактиране, защото е включена в {{PLURAL:$1|следната страница, която от своя страна има|следните страници, които от своя страна имат}} „каскадна“ защита:\n$2",
        "namespaceprotected": "Нямате права за редактиране на страници в именно пространство '''$1'''.",
        "customcssprotected": "Нямате права за редактиране на тази CSS страница, защото тя съдържа чужди потребителски настройки.",
        "customjsprotected": "Нямате права за редактиране на тази JavaScript страница, защото тя съдържа чужди потребителски настройки.",
        "password-change-forbidden": "Не можете да променяте пароли в това уики.",
        "externaldberror": "Или е станала грешка в базата от данни при външното удостоверяване, или не ви е позволено да обновявате външната си сметка.",
        "login": "Влизане",
+       "login-security": "Потвърдете идентичността си",
        "nav-login-createaccount": "Регистриране или влизане",
        "userlogin": "Влизане / създаване на сметка",
        "userloginnocreate": "Влизане",
        "createacct-reason-ph": "Защо създавате друга сметка",
        "createacct-submit": "Създаване на сметката",
        "createacct-another-submit": "Създаване на сметка",
+       "createacct-continue-submit": "Продължаване създаването на акаунт",
+       "createacct-another-continue-submit": "Продължаване създаването на акаунт",
        "createacct-benefit-heading": "{{SITENAME}} се създава от хора като вас.",
        "createacct-benefit-body1": "{{PLURAL:$1|редакция|редакции}}",
        "createacct-benefit-body2": "{{PLURAL:$1|страница|страници}}",
        "noname": "Не указахте валидно потребителско име.",
        "loginsuccesstitle": "Успешно влизане",
        "loginsuccess": "'''Влязохте в {{SITENAME}} като „$1“.'''",
-       "nosuchuser": "Ð\9dе Ñ\81Ñ\8aÑ\89еÑ\81Ñ\82вÑ\83ва Ð¿Ð¾Ñ\82Ñ\80ебиÑ\82ел Ñ\81 Ð¸Ð¼Ðµ â\80\9e$1â\80\9c.\nÐ\9fоÑ\82Ñ\80ебиÑ\82елÑ\81киÑ\82е Ð¸Ð¼ÐµÐ½Ð° Ñ\81а Ñ\87Ñ\83вÑ\81Ñ\82виÑ\82елни Ð½Ð° Ð¼Ð°Ð»ÐºÐ¸ Ð¸ Ð³Ð»Ð°Ð²Ð½Ð¸ Ð±Ñ\83кви.\nПроверете изписването или [[Special:CreateAccount|създайте нова сметка]].",
+       "nosuchuser": "Ð\9dе Ñ\81Ñ\8aÑ\89еÑ\81Ñ\82вÑ\83ва Ð¿Ð¾Ñ\82Ñ\80ебиÑ\82ел Ñ\81 Ð¸Ð¼Ðµ â\80\9e$1â\80\9c.\nÐ\9fоÑ\82Ñ\80ебиÑ\82елÑ\81киÑ\82е Ð¸Ð¼ÐµÐ½Ð° Ñ\81а Ñ\87Ñ\83вÑ\81Ñ\82виÑ\82елни ÐºÑ\8aм Ñ\80егиÑ\81Ñ\82Ñ\8aÑ\80а Ð½Ð° Ð±Ñ\83квиÑ\82е.\nПроверете изписването или [[Special:CreateAccount|създайте нова сметка]].",
        "nosuchusershort": "Не съществува потребител с името „$1“. Проверете изписването.",
        "nouserspecified": "Необходимо е да се посочи потребителско име.",
        "login-userblocked": "Този потребител е блокиран. Влизането в системата не е позволено.",
        "resetpass-no-info": "За да достъпвате тази страница директно, необходимо е да влезете в системата.",
        "resetpass-submit-loggedin": "Промяна на паролата",
        "resetpass-submit-cancel": "Отказ",
-       "resetpass-wrong-oldpass": "Невалидна временна или текуща парола.\nВъзможно е вече успешно да сте сменили паролата си или да сте поискали нова временна парола.",
+       "resetpass-wrong-oldpass": "Невалидна временна или текуща парола.\nВъзможно е вече да сте сменили паролата си или да сте поискали нова временна парола.",
        "resetpass-recycled": "Моля, променете паролата си с такава, различна от текущата.",
        "resetpass-temp-emailed": "Вие сте влезли в системата с помощта на временен код, който е изпратен чрез електронна поща.\nЗа да завършите влизането в системата, трябва да въведете нова парола тук:",
        "resetpass-temp-password": "Временна парола:",
        "resetpass-abort-generic": "Промяната на паролата беше прекъсната от използвано разширение.",
        "resetpass-expired": "Срокът на валидност на паролата е изтекъл. Изберете нова парола за влизане.",
        "resetpass-expired-soft": "Вашата парола е изтекла и трябва да бъде променена. Моля, въведете нова парола сега или натиснете бутона \"{{int:authprovider-resetpass-skip-label}}\" за да я промените по-късно.",
-       "resetpass-validity-soft": "Ð\9cолÑ\8f, Ð²Ñ\8aведеÑ\82е Ð½Ð¾Ð²Ð° Ð¿Ð°Ñ\80ола Ñ\81ега Ð¸Ð»Ð¸ Ð½Ð°Ñ\82иÑ\81неÑ\82е Ð±Ñ\83Ñ\82она \"{{int:authprovider-resetpass-skip-label}}\" за да я промените по-късно.",
+       "resetpass-validity-soft": "Ð\92аÑ\88аÑ\82а Ð¿Ð°Ñ\80ола Ðµ Ð½ÐµÐ²Ð°Ð»Ð¸Ð´Ð½Ð°: $1\n\nÐ\9cолÑ\8f, Ð²Ñ\8aведеÑ\82е Ð½Ð¾Ð²Ð° Ð¿Ð°Ñ\80ола Ð¸Ð»Ð¸ Ð½Ð°Ñ\82иÑ\81неÑ\82е Ð±Ñ\83Ñ\82она â\80\9e{{int:authprovider-resetpass-skip-label}}â\80\9c за да я промените по-късно.",
        "passwordreset": "Възстановяване на парола",
        "passwordreset-text-one": "Попълването на формуляра ще доведе до възстановяване на паролата.",
        "passwordreset-text-many": "{{PLURAL:$1|За получаване на временна парола по електронна поща е необходимо да попълните едно от полетата.}}",
        "passwordreset-emailelement": "Потребителско име: \n$1\n\nВременна парола: \n$2",
        "passwordreset-emailsentemail": "Ако електронната Ви поща е свързана със сметката Ви, на нея е изпратено писмо за възстановяване на паролата.",
        "passwordreset-emailsentusername": "Ако това потребителско име е свързано с електронна поща, е изпратено писмо за възстановяване на паролата.",
-       "passwordreset-emailsent-capture": "По-долу е показано електронното писмо за възстановяване на паролата, което беше изпратено.",
-       "passwordreset-emailerror-capture": "По-долу е показано създадено електронно писмо за възстановяване на паролата, което не беше изпратено на {{GENDER:$2|потребителя}}: $1",
        "passwordreset-invalideamil": "Неправилен email адрес",
        "changeemail": "Промяна или премахване на адреса за е-поща",
        "changeemail-header": "Промяна на адреса за е-поща на сметката",
-       "changeemail-passwordrequired": "Трябва да въведете паролата си, за да потвърдите тази промяна.",
        "changeemail-no-info": "За да достъпвате тази страница директно, необходимо е да влезете в системата.",
        "changeemail-oldemail": "Текущ адрес за е-поща:",
        "changeemail-newemail": "Нов адрес за е-поща:",
        "minoredit": "Това е малка промяна",
        "watchthis": "Наблюдаване на страницата",
        "savearticle": "Съхраняване",
+       "savechanges": "Съхраняване на промените",
        "publishpage": "Публикуване на страницата",
+       "publishchanges": "Публикуване на промените",
        "preview": "Предварителен преглед",
        "showpreview": "Предварителен преглед",
        "showdiff": "Показване на промените",
        "undo-failure": "Редакцията не може да бъде върната поради конфликтни междинни редакции.",
        "undo-norev": "Редакцията не може да бъде върната, тъй като не съществува или е била изтрита.",
        "undo-summary": "Премахната редакция $1 на [[Special:Contributions/$2|$2]] ([[User talk:$2|беседа]])",
-       "cantcreateaccounttitle": "Невъзможно е да бъде създадена потребителска сметка.",
        "cantcreateaccount-text": "[[User:$3|Потребител:$3]] е блокирал(а) създаването на сметки от този IP-адрес ('''$1''').\n\nПричината, изложена от $3, е ''$2''",
        "viewpagelogs": "Преглед на извършените административни действия по страницата",
        "nohistory": "Няма редакционна история за тази страница.",
        "revdelete-submit": "Прилагане към {{PLURAL:$1|избраната версия|избраните версии}}",
        "revdelete-success": "'''Видимостта на версията беше променена успешно.'''",
        "revdelete-failure": "'''Видимостта на редакцията не може да бъде обновена:'''\n$1",
-       "logdelete-success": "Видимостта на събитието беше променена.",
+       "logdelete-success": "Видимостта на дневника е установена.",
        "logdelete-failure": "'''Видимостта на дневника не може да бъде променяна:'''\n$1",
        "revdel-restore": "промяна на видимостта",
        "pagehist": "История на страницата",
        "grouppage-sysop": "{{ns:project}}:Администратори",
        "grouppage-bureaucrat": "{{ns:project}}:Бюрократи",
        "grouppage-suppress": "{{ns:project}}:Ревизори",
-       "right-read": "четене на страници",
+       "right-read": "Четене на страници",
        "right-edit": "редактиране на страници",
        "right-createpage": "Създаване на страници (които не са беседи)",
        "right-createtalk": "Създаване на дискусионни страници",
        "right-move-rootuserpages": "Преместване на основни потребителски страници",
        "right-move-categorypages": "Преместване на категорийни страници",
        "right-movefile": "Преместване на файлове",
-       "right-suppressredirect": "без създаване на пренасочване от старото име при преместване на страница",
+       "right-suppressredirect": "Ð\91ез създаване на пренасочване от старото име при преместване на страница",
        "right-upload": "Качване на файлове",
        "right-reupload": "Презаписване на съществуващ файл",
        "right-reupload-own": "Презаписване на съществуващ файл, качен от същия потребител",
        "right-reupload-shared": "Предефиниране на едноименните файлове от общото мултимедийно хранилище с локални",
        "right-upload_by_url": "качване на файл от URL адрес",
        "right-purge": "изчистване на складираното съдържание на страниците без показване на страница за потвърждение",
-       "right-autoconfirmed": "редактиране на полузащитени страници",
-       "right-bot": "третиране като автоматизиран процес",
+       "right-autoconfirmed": "Редактиране на полузащитени страници",
+       "right-bot": "Третиране като автоматизиран процес",
        "right-nominornewtalk": "Малките промени по дискусионните страници не предизвикват известието за ново съобщение",
-       "right-apihighlimits": "използване на крайните предели в API заявките",
+       "right-apihighlimits": "Ð\98зползване на крайните предели в API заявките",
        "right-writeapi": "Употреба на API за писане",
-       "right-delete": "изтриване на страници",
+       "right-delete": "Ð\98зтриване на страници",
        "right-bigdelete": "изтриване на страници с големи редакционни истории",
-       "right-deleterevision": "изтриване и възстановяване на отделни версии на страниците",
+       "right-deletelogentry": "Изтриване и възстановяване на отделни записи в дневника",
+       "right-deleterevision": "Изтриване и възстановяване на отделни версии на страниците",
        "right-deletedhistory": "преглеждане на записи от изтрити редакционни истории без асоциирания към тях текст",
        "right-deletedtext": "Преглед на изтрития текст и промените между изтритите версии",
        "right-browsearchive": "търсене на изтрити страници",
-       "right-undelete": "възстановяване на страници",
-       "right-suppressrevision": "преглед и възстановяване на версии, скрити от администраторите",
+       "right-undelete": "Ð\92ъзстановяване на страници",
+       "right-suppressrevision": "Ð\9fреглед и възстановяване на версии, скрити от администраторите",
        "right-viewsuppressed": "Преглеждане на версии, скрити от който и да е потребител",
-       "right-suppressionlog": "преглеждане на тайните дневници",
+       "right-suppressionlog": "Ð\9fреглеждане на тайните дневници",
        "right-block": "спиране на достъпа до редактиране",
-       "right-blockemail": "блокиране на потребители да изпращат писма по е-поща",
+       "right-blockemail": "Ð\91локиране на потребители да изпращат писма по е-поща",
        "right-hideuser": "блокиране и скриване на потребителско име",
        "right-ipblock-exempt": "пренебрегване на блокирания по IP blocks, автоматични блокирания и блокирани IP интервали",
        "right-unblockself": "Собствено отблокиране",
        "right-protect": "променяне на нивото на защита и редактиране на защитени страници",
        "right-editprotected": "редактиране на защитени страници (без каскадна защита)",
-       "right-editinterface": "редактиране на потребителския интерфейс",
+       "right-editinterface": "Редактиране на потребителския интерфейс",
        "right-editusercssjs": "редактиране на CSS и JS файловете на други потребители",
        "right-editusercss": "редактиране на CSS файловете на други потребители",
        "right-edituserjs": "редактиране на JS файловете на други потребители",
        "right-import": "внасяне на страници от други уикита",
        "right-importupload": "внасяне на страници от качен файл",
        "right-patrol": "отбелязване на редакциите като проверени",
-       "right-autopatrol": "автоматично отбелязване на редакции като проверени",
+       "right-autopatrol": "Ð\90втоматично отбелязване на редакции като проверени",
        "right-patrolmarks": "Показване на отбелязаните като патрулирани последни промени",
        "right-unwatchedpages": "преглеждане на списъка с ненаблюдаваните страници",
        "right-mergehistory": "сливане на редакционни истории на страници",
        "activeusers-hidesysops": "Скриване на администраторите",
        "activeusers-noresult": "Няма намерени потребители.",
        "listgrouprights": "Права по потребителски групи",
-       "listgrouprights-summary": "По-долу на тази страница е показан списък на групите потребители в това уики с асоциираните им права за достъп. Допълнителна информация за отделните права може да бъде намерена [[{{MediaWiki:Listgrouprights-helppage}}|тук]].",
+       "listgrouprights-summary": "По-долу на тази страница е показан списък на групите потребители в това уики и права им за достъп. Допълнителна информация за отделните права може да бъде намерена [[{{MediaWiki:Listgrouprights-helppage}}|тук]].",
        "listgrouprights-key": "Легенда:\n* <span class=\"listgrouprights-granted\">Поверено право</span>\n* <span class=\"listgrouprights-revoked\">Отнето право</span>",
        "listgrouprights-group": "Група",
        "listgrouprights-rights": "Права",
        "sessionfailure": "Изглежда има проблем със сесията ви; действието беше отказано като предпазна мярка срещу крадене на сесията. Натиснете бутона за връщане на браузъра, презаредете страницата, от която сте дошли, и опитайте отново.",
        "changecontentmodel-title-label": "Заглавие на страницата",
        "changecontentmodel-reason-label": "Причина:",
+       "changecontentmodel-success-text": "Типът на съдържанието на [[:$1]] е успешно променен.",
        "protectlogpage": "Дневник на защитата",
        "protectlogtext": "Списък на промените в защитата за страницата.\nМожете да прегледате и [[Special:ProtectedPages|списъка на текущо защитените страници]].",
        "protectedarticle": "защити „[[$1]]“",
        "exif-dc-contributor": "Сътрудници",
        "exif-dc-date": "Дата(и)",
        "exif-dc-rights": "Права",
+       "exif-dc-type": "Вид медия",
        "exif-isospeedratings-overflow": "По-голяма от 65535",
        "exif-iimcategory-ace": "Изкуствa, култура и забавление",
        "exif-iimcategory-clj": "Престъпност и право",
        "mw-widgets-titleinput-description-new-page": "страницата все още не съществува",
        "mw-widgets-titleinput-description-redirect": "пренасочване към $1",
        "randomrootpage": "Случайна начална страница",
+       "log-action-filter-block": "Вид на блокирането:",
+       "log-action-filter-delete": "Вид на изтриването:",
+       "log-action-filter-newusers": "Вид на създаването на акаунт:",
        "log-action-filter-protect": "Тип защита:",
+       "log-action-filter-rights": "Вид на промяната на правата за достъп:",
        "log-action-filter-upload": "Тип качване:",
        "log-action-filter-all": "Всички",
        "log-action-filter-block-block": "Блокиране",
index a5c5a14..97596c4 100644 (file)
        "passwordreset-emailelement": "ব্যবহারকারী নাম: \n$1\n\nঅস্থায়ী পাসওয়ার্ড: \n$2",
        "passwordreset-emailsentemail": "যদি এই ই-মেইল ঠিকানা আপনার অ্যাকাউন্টের সাথে সংযুক্ত করা থাকে, তাহলে একটি পাসওয়ার্ড বদলের ইমেইল পাঠানো হবে।",
        "passwordreset-emailsentusername": "যদি এই ব্যবহারকারী নামের সাথে ই-মেইল ঠিকানা সংযুক্ত করা থাকে, তাহলে একটি পাসওয়ার্ড বদলের ইমেইল পাঠানো হবে।",
-       "passwordreset-emailsent-capture": "স্মরণ করিয়ে দেয়ার জন্য একটি ইমেইল করা হয়েছে, যা নিচে দেখানো হচ্ছে।",
-       "passwordreset-emailerror-capture": "স্মরণ করিয়ে দেয়ার জন্য একটি ইমেইল তৈরী করা হয়েছিল, যা নিচে দেখানো হচ্ছে, তবে $1 {{GENDER:$2|ব্যবহারকারীকে}} এটি পাঠানো যায়নি!",
        "passwordreset-nocaller": "একটি আহ্বানকারী প্রদান করা আবশ্যক",
        "passwordreset-nosuchcaller": "আহ্বানকারীর অস্তিত্ব নেই: $1",
        "passwordreset-invalideamil": "ভুল ইমেইল ঠিকানা",
        "passwordreset-nodata": "একটি ব্যবহারকারীর নাম বা একটি ইমেল ঠিকানা দুটির একটিও সরবরা দেয়া হয়নি",
        "changeemail": "ই-মেইল ঠিকানা পরিবর্তন বা বাতিল",
        "changeemail-header": "আপনার ইমেল ঠিকানা পরিবর্তন করতে এই ফরমটি পূরণ করুন। আপনি যদি আপনার একাউন্ট থেকে যে কোন ইমেল ঠিকানার এসোসিয়েশন অপসারণ করতে চান, তাহলে ফরমটি জমা দেওয়ার সময় নতুন ইমেইল ঠিকানা খালি রাখুন।",
-       "changeemail-passwordrequired": "এই পরিবর্তন নিশ্চিত করতে আপনাকে আপনার পাসওয়ার্ড লিখতে হবে।",
        "changeemail-no-info": "এই পাতাটিতে সরাসরি প্রবেশাধিকার পেতে আপনাকে অবশ্যই প্রবেশ করতে হবে।",
        "changeemail-oldemail": "বর্তমান ই-মেইল ঠিকানা:",
        "changeemail-newemail": "নতুন ই-মেইল ঠিকানা:",
        "undo-nochange": "সম্পাদনাটি পূর্বেই বাতিল করা হয়েছে।",
        "undo-summary": "[[Special:Contributions/$2|$2]] ([[User talk:$2|আলাপ]])-এর সম্পাদিত $1 নম্বর সংশোধনটি বাতিল করা হয়েছে",
        "undo-summary-username-hidden": "একজন লুকানো ব্যবহারকারী $1 সংশোধন পুনরায় ফিরিয়ে এনেছেন",
-       "cantcreateaccounttitle": "অ্যাকাউন্ট তৈরি করা যাবে না",
        "cantcreateaccount-text": "[[User:$3|$3]] এই আইপি ঠিকানা('''$1''') থেকে অ্যাকাউন্ট সৃষ্টিতে বাধা দিয়েছেন।\n\n$3-এর দেয়া কারণ হল ''$2''",
        "cantcreateaccount-range-text": "[[User:$3|$3]] কর্তৃক আইপি ঠিকানার ব্যাপ্তি <strong>$1</strong>-এর মধ্যে অ্যাকাউন্ট তৈরি করা অবরুদ্ধ করা হয়েছে। যাতে আপনার আইপি ঠিকানাও (<strong>$4</strong>) রয়েছে। \n\n$3 কর্তৃক <em>$2</em> কারণ দেখানো হয়েছে।",
        "viewpagelogs": "এই পাতার জন্য লগগুলো দেখুন",
index 82c9d61..ee07df4 100644 (file)
        "passwordreset-emailtext-user": "Korisnik $1 na {{SITENAME}} je zatražio podsjetnik o detaljima Vašeg računa za {{SITENAME}} ($4). Sljedeći {{PLURAL:$3|korisnički račun je|korisnički računi su}} povezani s ovom e-mail adresom:\n\n$2\n\n{{PLURAL:$3|Ova privremena šifra|Ove privremene šifre}} će isteći za {{PLURAL:$5|jedan dan|$5 dana}}.\nTrebate se prijaviti i odabrati novu šifru. Ako je neko drugi napravio ovaj zahtjev, ili ako ste se sjetili Vaše originalne šifre, a ne želite je više promijeniti, možete zanemariti ovu poruku i nastaviti koristiti staru šifru.",
        "passwordreset-emailelement": "Korisničko ime: \n$1\n\nPrivremena šifra: \n$2",
        "passwordreset-emailsentemail": "Ako je ovo adresa e-pošte s kojom ste registrirali ovaj račun, podsjetnik šifre će vam biti poslan na vašu adresu e-pošte.",
-       "passwordreset-emailsent-capture": "Poslan je podsjetnik preko e-pošte (prikazano ispod).",
-       "passwordreset-emailerror-capture": "E-poruka za resetiranje lozinke, prikazano ispod, poslana je, ali slanje {{GENDER:$2|korisniku|korisnici}} nije uspjelo: $1",
        "changeemail": "Promjena ili uklanjanje e-adrese",
        "changeemail-header": "Ispunite sljedeći formular da biste promijenili adresu e-pošte. Ako želite ukloniti postojeću adresu e-pošte s vašeg korisničkog računa, pri ispunjavanju formulara, polje nove adrese e-pošte ostavite prazno.",
-       "changeemail-passwordrequired": "Morat ćete unijeti šifru da biste potvrdili ovu izmjenu.",
        "changeemail-no-info": "Morate biti prijavljeni za direktan pristup ovoj stranici.",
        "changeemail-oldemail": "Trenutna adresa e-pošte:",
        "changeemail-newemail": "Nova adresa e-pošte:",
        "undo-nochange": "Izgleda da je izmjena već vraćena.",
        "undo-summary": "Poništena izmjena $1 {{GENDER:$2|korisnika|korisnice}} [[Special:Contributions/$2|$2]] ([[User talk:$2|razgovor]])",
        "undo-summary-username-hidden": "Poništi izmjenu $1 od skrivenog korisnika",
-       "cantcreateaccounttitle": "Nije moguće napraviti korisnički račun",
        "cantcreateaccount-text": "Pravljenje korisničkog računa sa ove IP adrese ('''$1''') je blokirano od strane [[User:$3|$3]].\n\nRazlog koji je naveo $3 je ''$2''",
        "cantcreateaccount-range-text": "Pravljenje računa sa IP adresa u rasponu <strong>$1</strong>, koji uključuje i vašu IP adresu (<strong>$4</strong>), je blokirao korisnik [[User:$3|$3]].\n\nNavedeni razlog korisnika $3 je <em>$2</em>",
        "viewpagelogs": "Pogledaj zapisnike ove stranice",
index 965b9b3..8a05f0f 100644 (file)
        "passwordreset-emailelement": "Nom d'usuari: \n$1\n\nContrasenya temporal: \n$2",
        "passwordreset-emailsentemail": "Si aquesta adreça electrònica està associada al vostre compte, s’enviarà un missatge de restabliment de contrasenya.",
        "passwordreset-emailsentusername": "Si existeix una adreça electrònica associada a aquest nom d'usuari, s’hi enviarà un missatge de reestabliment de contrasenya.",
-       "passwordreset-emailsent-capture": "S'ha enviat un correu electrònic de reinicialització de contrasenya, tal com es mostra a continuació.",
-       "passwordreset-emailerror-capture": "S'ha generat un correu electrònic de renovació de contrasenya, que es mostra a continuació, però ha fallat l'enviament a {{GENDER:$2:l'usuari|la usuària}}: $1",
        "passwordreset-emailsent-capture2": "{{PLURAL:$1|S'ha enviat el correu|S'han enviat els correus}} de restabliment de {{PLURAL:$1|contrasenya|contrasenyes}}. A continuació es mostra {{PLURAL:$1|l'usuari i contrasenya|la llista d'usuaris i contrasenyes}}.",
        "passwordreset-invalideamil": "Adreça de correu electrònic no vàlida",
        "passwordreset-nodata": "No s'ha proporcionat cap nom d'usuari ni adreça electrònica",
        "changeemail": "Canvia o elimina l’adreça electrònica",
        "changeemail-header": "Empleneu aquest formulari per canviar la vostra adreça electrònica. Si voleu eliminar qualssevol associacions d’adreces electròniques del vostre compte, deixeu en blanc el camp i envieu el formulari.",
-       "changeemail-passwordrequired": "Cal que introduïu la vostra contrasenya per confirmar el canvi.",
        "changeemail-no-info": "Heu d'entrar en un compte d'usuari per accedir directament a aquesta pàgina.",
        "changeemail-oldemail": "Adreça electrònica actual:",
        "changeemail-newemail": "Adreça electrònica nova:",
        "undo-nochange": "Sembla que ja s'ha desfet la modificació.",
        "undo-summary": "Es desfà la revisió $1 de [[Special:Contributions/$2|$2]] ([[User talk:$2|Discussió]])",
        "undo-summary-username-hidden": "Desfés la revisió $1 d'un usuari ocult",
-       "cantcreateaccounttitle": "No es pot crear el compte",
        "cantcreateaccount-text": "[[User:$3|$3]] ha bloquejat la creació de comptes des d'aquesta adreça IP ('''$1''').\n\nEl motiu donat per $3 és ''$2''",
        "cantcreateaccount-range-text": "La creació de comptes des de les adreces IP en el rang <strong>$1</strong>, que inclou la vostra adreça IP (<strong>$4</strong>), ha estat blocada per [[User:$3|$3]].\n\nEl motiu donat per $3 és <em>$2</em>",
        "viewpagelogs": "Visualitza els registres d'aquesta pàgina",
index 86a7951..1e09490 100644 (file)
        "passwordreset-emailelement": "Uživatelské jméno: \n$1\n\nDočasné heslo: \n$2",
        "passwordreset-emailsentemail": "Pokud je u vašeho účtu nastavena tato e-mailová adresa, bude vám zaslán e-mail pro získání nového hesla.",
        "passwordreset-emailsentusername": "Pokud je u tohoto účtu nastavena e-mailová adresa, bude vám zaslán e-mail pro získání nového hesla.",
-       "passwordreset-emailsent-capture": "Byl odeslán e-mail pro získání nového hesla, který je zobrazen níže.",
-       "passwordreset-emailerror-capture": "Byl vygenerován e-mail pro získání nového hesla, který je zobrazen níže, ale {{GENDER:$2|uživateli|uživatelce}} se ho nepodařilo odeslat: $1",
        "passwordreset-emailsent-capture2": "{{PLURAL:$1|Byl odeslán e-mail|Byly odeslány e-maily}} pro získání nového hesla. {{PLURAL:$1|Uživatelské jméno a heslo jsou zobrazeny|Seznam uživatelských jmen a hesel je zobrazen}} níže.",
        "passwordreset-emailerror-capture2": "{{GENDER:$2|Uživateli|Uživatelce}} se nepodařilo odeslat e-mail: $1 {{PLURAL:$3|Uživatelské jméno a heslo jsou zobrazeny|Seznam uživatelských jmen a hesel je zobrazen}} níže.",
        "passwordreset-nocaller": "Musí být uveden volající",
        "passwordreset-nodata": "Nebylo zadáno uživatelské jméno ani e-mailová adresa",
        "changeemail": "Změna nebo odstranění e-mailové adresy",
        "changeemail-header": "Vyplněním tohoto formuláře můžete změnit svou e-mailovou adresu. Pokud chcete ze svého účtu odstranit vazbu na všechny e-mailové adresy, ponechte při odeslání formuláře novou e-mailovou adresu prázdnou.",
-       "changeemail-passwordrequired": "Pro potvrzení této změny musíte zadat své heslo.",
        "changeemail-no-info": "K této stránce mají přímý přístup jen přihlášení uživatelé.",
        "changeemail-oldemail": "Stávající e-mailová adresa:",
        "changeemail-newemail": "Nová e-mailová adresa:",
        "undo-nochange": "Zdá se, že editace již byla zrušena.",
        "undo-summary": "Zrušena verze $1 od uživatele [[Special:Contributions/$2|$2]] ([[User talk:$2|diskuse]])",
        "undo-summary-username-hidden": "Zrušena verze $1 od skrytého uživatele",
-       "cantcreateaccounttitle": "Nelze vytvořit uživatelský účet",
        "cantcreateaccount-text": "Zakládání nových účtů z této IP adresy (<strong>$1</strong>) bylo zablokováno {{GENDER:$3|uživatelem|uživatelkou}} [[User:$3|$3]].\n\n$3 uvádí toto zdůvodnění: <em>$2</em>",
        "cantcreateaccount-range-text": "Zakládání nových účtů z IP adres v rozsahu <strong>$1</strong>, který obsahuje i vaši IP adresu (<strong>$4</strong>), bylo zablokováno {{GENDER:$3|uživatelem|uživatelkou}} [[User:$3|$3]].\n\n$3 uvádí toto zdůvodnění: <em>$2</em>",
        "viewpagelogs": "Zobrazit protokolovací záznamy k této stránce",
index a1a9953..8079c71 100644 (file)
        "passwordreset-emailtext-user": "Gofynodd y defnyddiwr $1 ar {{SITENAME}} am gael ailosod ei gyfrinair ar {{SITENAME}}\n($4). Mae'r {{PLURAL:$3||cyfrif|cyfrifon}} canlynol ynghlwm wrth y cyfeiriad e-bost hwn:\n\n$2\n\nBydd y {{PLURAL:$3||cyfrinair|cyfrineiriau}} dros dro hyn yn dod i ben ymhen {{PLURAL:$5||diwrnod|deuddydd|tridiau|$5 diwrnod}}.\nDylech fewngofnodi nawr a dewis cyfrinair newydd. Os mai rhywun arall a ofynodd am ailosod y cyfrinair, neu os ydych wedi cofio eich cyfrinair gwreiddiol, neu os nad ydych am ei newid bellach, gallwch anwybyddu'r neges hon a pharhau i ddefnyddio eich hen gyfrinair.",
        "passwordreset-emailelement": "Enw'r defnyddiwr: \n$1\n\nY cyfrinair dros dro: \n$2",
        "passwordreset-emailsentemail": "Anfonwyd e-bost i ailosod eich cyfrinair atoch.",
-       "passwordreset-emailsent-capture": "Anfonwyd e-bost i ailosod cyfrinair, ac fe'i ddangosir isod.",
-       "passwordreset-emailerror-capture": "Lluniwyd e-bost i ailosod cyfrinair fel ag a welir isod, ond ni lwyddwyd i'w anfon at y {{GENDER:$2|defnyddiwr}}: $1",
        "changeemail": "Newid y cyfeiriad e-bost",
        "changeemail-header": "Cwbwlhewch y ffurflen hon i newid cyfeiriad e-bost y cyfrifi. I ddileu pob cysylltiad i bob cyfeiriad ebost, gadewch e'n wag.",
        "changeemail-no-info": "Ni allwch fynd at y dudalen hon heblaw eich bod wedi mewngofnodi.",
        "undo-nochange": "Ymddengys fod y golygiad wedi ei ddadwneud yn barod.",
        "undo-summary": "Dadwneud y golygiad $1 gan [[Special:Contributions/$2|$2]] ([[User talk:$2|Sgwrs]] | [[Special:Contributions/$2|{{MediaWiki:Contribslink}}]])",
        "undo-summary-username-hidden": "Dadwneud y golygiad $1 gan ddefnyddiwr cudd",
-       "cantcreateaccounttitle": "Yn methu creu cyfrif",
        "cantcreateaccount-text": "Rhwystrwyd y gallu i greu cyfrif ar gyfer y cyfeiriad IP hwn, ('''$1'''), gan [[User:$3|$3]].\n\nY rheswm a roddwyd dros y bloc gan $3 yw ''$2''.",
        "cantcreateaccount-range-text": "Gosododd [[User:$3|$3]] floc ar agor cyfrifon o gyfeiriadau IP yn yr ystod <strong>$1</strong>, sy'n cynnwys eich cyfeiriad IP chi (<strong>$4</strong>).\n\nY rheswm a roddwyd gan $3 yw \"$2\"",
        "viewpagelogs": "Dangos logiau'r dudalen hon",
index 9833f1a..747148d 100644 (file)
        "passwordreset-emailelement": "Brugernavn: \n$1\n\nMidlertidig adgangskode: \n$2",
        "passwordreset-emailsentemail": "Hvis denne e-mailadresse er knyttet til din konto, så vil en e-mail om nulstilling af adgangskoden blive sendt.",
        "passwordreset-emailsentusername": "Hvis der er en e-mailadresse forbundet med dette brugernavn, så vil en e-mail om nulstilling af adgangskoden blive sendt.",
-       "passwordreset-emailsent-capture": "En e-mail om nulstilling af adgangskode, som vist nedenfor, er blevet sendt.",
-       "passwordreset-emailerror-capture": "En mail om nulstilling af adgangskode, som vist nedenfor, blev genereret, men det lykkedes ikke at sende den til {{GENDER:$2|bruger}}: $1",
        "changeemail": "Ændr eller fjern e-mailadresse",
        "changeemail-header": "Udfyld denne formular for at ændre din e-mailadresse. Hvis du gerne vil fjerne forbindelsen af en e-mailadresse fra din konto, så lad den nye e-mailadresse være blank, når du sender formularen.",
-       "changeemail-passwordrequired": "Du er nødt til at indtaste din adgangskode for at bekræfte denne ændring.",
        "changeemail-no-info": "Du skal være logget på for at komme direkte til denne side.",
        "changeemail-oldemail": "Nuværende e-mailadresse:",
        "changeemail-newemail": "Ny e-mailadresse:",
        "undo-nochange": "Ændringen ser ud til allerede at være blevet fjernet.",
        "undo-summary": "Fjerner version $1 af [[Special:Contributions/$2|$2]] ([[User talk:$2|diskussion]])",
        "undo-summary-username-hidden": "Fortryde revision $1 af en skjult bruger",
-       "cantcreateaccounttitle": "Brugerkontoen kan ikke oprettes.",
        "cantcreateaccount-text": "Oprettelsen af en brugerkonto fra IP-adressen ('''$1''') er blevet blokeret af [[User:$3|$3]].\n\nÅrsagen til blokeringen er angivet af $3 som ''$2''",
        "cantcreateaccount-range-text": "Oprettelsen af en brugerkonto fra IP-adresser i intervallet <strong>$1</strong>, som omfatter din IP-adresse (<strong>$4</strong>), er blevet blokeret af [[User:$3|$3]].\n\nÅrsagen angivet af $3 er <em>$2</em>",
        "viewpagelogs": "Vis loglister for denne side",
index 60e8456..95afc76 100644 (file)
        "passwordreset-emailelement": "Benutzername: \n$1\n\nTemporäres Passwort: \n$2",
        "passwordreset-emailsentemail": "Falls diese E-Mail-Adresse mit deinem Benutzerkonto verknüpft ist, wird eine Passwort-Zurücksetzungs-E-Mail versandt.",
        "passwordreset-emailsentusername": "Falls es eine E-Mail-Adresse gibt, die mit diesem Benutzernamen verknüpft ist, wird eine Passwort-Zurücksetzungs-E-Mail versandt.",
-       "passwordreset-emailsent-capture": "Eine Passwortzurücksetzungs-E-Mail wurde versandt, die unten angezeigt wird.",
-       "passwordreset-emailerror-capture": "Die unten angezeigte Passwortzurücksetzungs-E-Mail wurde generiert, allerdings ist der Versand an {{GENDER:$2|den Benutzer|die Benutzerin}} gescheitert: $1",
        "passwordreset-emailsent-capture2": "Die Passwort-Zurücksetzungs-{{PLURAL:$1|E-Mail wurde|E-Mails wurden}} versandt. {{PLURAL:$1|Der Benutzername und das Passwort|Die Liste der Benutzernamen und Passwörter}} wird unten angezeigt.",
        "passwordreset-emailerror-capture2": "Das Senden der E-Mail an {{GENDER:$2|den Benutzer|die Benutzerin}} ist fehlgeschlagen: $1 {{PLURAL:$3|Der Benutzername und das Passwort|Die Liste der Benutzernamen und Passwörter}} wird unten angezeigt.",
        "passwordreset-nocaller": "Es muss ein Rufer angegeben werden",
        "passwordreset-nodata": "Weder ein Benutzername noch eine E-Mail-Adresse wurde angegeben",
        "changeemail": "E-Mail-Adresse ändern oder entfernen",
        "changeemail-header": "Fülle dieses Formular vollständig aus, um deine E-Mail-Adresse zu ändern. Falls du die Zuweisung einer E-Mail-Adresse zu deinem Benutzerkonto entfernen möchtest, lasse beim Übermitteln des Formulars das Feld für die neue E-Mail-Adresse leer.",
-       "changeemail-passwordrequired": "Du musst dein Passwort eingeben, um diese Änderung zu bestätigen.",
        "changeemail-no-info": "Du musst angemeldet sein, um direkt auf diese Seite zugreifen zu können.",
        "changeemail-oldemail": "Aktuelle E-Mail-Adresse:",
        "changeemail-newemail": "Neue E-Mail-Adresse:",
        "undo-nochange": "Anscheinend wurde diese Bearbeitung bereits rückgängig gemacht.",
        "undo-summary": "Änderung $1 von [[Special:Contributions/$2|$2]] ([[User talk:$2|Diskussion]]) rückgängig gemacht.",
        "undo-summary-username-hidden": "Änderung $1 eines versteckten Benutzers rückgängig gemacht.",
-       "cantcreateaccounttitle": "Das Benutzerkonto kann nicht erstellt werden",
        "cantcreateaccount-text": "Die Erstellung eines Benutzerkontos von der IP-Adresse '''($1)''' aus wurde durch [[User:$3|$3]] gesperrt.\n\nGrund der Sperre: ''$2''",
        "cantcreateaccount-range-text": "Das Erstellen von Benutzerkonten von IP-Adressen im Bereich <strong>$1</strong>, der deine IP-Adresse (<strong>$4</strong>) enthält, wurde von [[User:$3|$3]] gesperrt.\n\nDer angegebene Grund von $3 lautet: <em>$2</em>",
        "viewpagelogs": "Logbücher dieser Seite anzeigen",
index 11b289a..90d074e 100644 (file)
        "passwordreset-emailtext-user": "$1 enê karberi, {{SITENAME}}  ra ($4) teferuatê hesab dê şıma  va wa biyaro xo viri. Karbero ke cêrdeyo {{PLURAL:$3|hesaba|eno hesaba}} ena e-posta adresiya aleqey cı esto:\n\n$2\n\n{{PLURAL:$3|ena parola idaretena|ena parola idareten}} {{PLURAL:$5|jew roc|$5  roca}}rêya.\nEna parolaya deqewe de u xorê ju parolaya newi bıweçine. Parolaya şıma emaya şıma viri se  yana  ena e-posta şıma nê weştase u şıma qayıl niye parolaya xo bıvurnese, ena mesacer peygoş bıkerê.",
        "passwordreset-emailelement": "Nameyê karberi: \n$1\n\nParolaya vêrdiye: \n$2",
        "passwordreset-emailsentemail": "Eke na seba hesabê şıma yew adresa e-posteyê qeydına, yew e-posteyê parola nênkerdışi rışiyeno.",
-       "passwordreset-emailsent-capture": "Yew e-posteyê esterıtışê parolayo ke rışiya, no cêr mocniyayo.",
-       "passwordreset-emailerror-capture": "Yew e-posteyê esterıtışê parolayo ke rışiya, no cêr mocniyayo, ema {{GENDER:$2|karber}}i rê rıştış de mıwefeq nêbi: $1",
        "passwordreset-invalideamil": "Adresê eposta raşt niya",
        "changeemail": "E-posta adresa xo wedarne",
        "changeemail-header": "E-posya adresta hesabdê xo bıvurnê",
        "undo-norev": "Vurnayiş tepêya nêgeryeno çunke ya vere cû hewna biyo ya zi ca ra çino.",
        "undo-summary": "Vırnayışê $1'i [[Special:Contributions/$2|$2i]] ([[User talk:$2|Werênayış]]) peyser gırot",
        "undo-summary-username-hidden": "Rewizyona veri $1'i hewada",
-       "cantcreateaccounttitle": "Nêşenay hesab rakerê",
        "cantcreateaccount-text": "Hesabvıraştışê na IP adrese ('''$1''') terefê [[User:$3|$3]] kılit biyo.\n\nSebebo ke terefê $3 ra diyao ''$2''",
        "viewpagelogs": "Seba na pele rê qeydan bımocne",
        "nohistory": "Verê vurnayışanê na pele çıniyo.",
index 6d1a32a..cf025f0 100644 (file)
        "passwordreset-emailtext-user": "Wužywaŕ $1 jo anulěrowanje gronidła za {{GRAMMAR:akuzatiw|{{SITENAME}}}} pominał ($4).  {{PLURAL:$3|Slědujuce wužywarske konto jo|Slědujucej wužywarskej konśe stej|Slědujuce wužywarske konta su}} z toś tej e-mailoweju adresu {{PLURAL:$3|zwězane|zwězanej|zwězane}}:\n\n$2\n\n{{PLURAL:$3|Toś to nachylne gronidło spadnjo|Toś tej nachylnej gronidle spadnjotej|Toś te nachylne gronidła spadnu}} za {{PLURAL:$5|jaden źeń|$5 dnja|$5 dny|$5 dnjow}}.\nTy by měł se něnto pśizjawiś a nowe gronidło wustajiś. Jolic něchten drugi jo toś to napšašowanje pósłał, abo jolic sy se zasej na spócetne gronidło spomnjeł a wěcej njocoš jo změniś, móžoš toś to zdźělenje ignorěrowaś a swójo stare gronidło dalej wužywaś.",
        "passwordreset-emailelement": "Wužywarske mě: \n$1\n\nNachylne gronidło: \n$2",
        "passwordreset-emailsentemail": "E-mail za anulěrowanje gronidła jo se pósłała.",
-       "passwordreset-emailsent-capture": "E-mail za anulěrowanje gronidła jo se pósłała, kótaraž pokazujo se dołojce.",
-       "passwordreset-emailerror-capture": "E-mail za anulěrowanje gronidła jo se napórała, kótaraž se dołojce pokazujo, ale słanje {{GENDER:$2|wužywarjeju|wužywarce}} njejo se raźiło: $1",
        "changeemail": "E-mailowu adresu změniś",
        "changeemail-header": "Kontowu e-mailowu adresu změniś",
        "changeemail-no-info": "Dejš pśizjawjony byś, aby direktny pśistup na toś ten bok měł.",
        "undo-nochange": "Zda se, až změna jo se južo anulěrowała.",
        "undo-summary": "Wersija $1 wót [[Special:Contributions/$2|$2]] ([[User talk:$2|Diskusija]]) jo se anulěrowała",
        "undo-summary-username-hidden": "Změna $1 schowanego wužywarja jo se anulěrowała",
-       "cantcreateaccounttitle": "Njejo móžno wužywarske konto wutwóriś",
        "cantcreateaccount-text": "Wutwórjenje wužywarskego konta z toś teje IP adresy ('''$1''') jo blokěrowane pśez [[User:$3|$3]].\n\nPśicyna, kótaruž $3 jo zapódał, jo ''$2''.",
        "cantcreateaccount-range-text": "Napóranje kontow z IP-adresow we wobcerku <strong>$1</strong>, kótaryž wopśimujo twóju IP-adresu (<strong>$4</strong>), jo se wót [[User:$3|$3]] zablokěrowało.\n\nPśicyna pódana wót $3 jo <em>$2</em>",
        "viewpagelogs": "Protokole boka pokazaś",
index 6ebcc19..fd75693 100644 (file)
        "parser-unstrip-loop-warning": "अनस्ट्रिप लुप धेखिन्छ",
        "parser-unstrip-recursion-limit": "अन्स्ट्रिप पुनरावर्तन सिमा पार गरियो ($1)",
        "converter-manual-rule-error": "म्यानुअल भाषा अनुवाद सिध्दान्तमी समस्या धेखियो",
-       "cantcreateaccounttitle": "खाता बनाउन सकिएन",
        "viewpagelogs": "यै पानाका लगहरू हेर",
        "nohistory": "ये पृष्ठका लागी कोइ सम्पादन इतिहास छैन।",
        "currentrev": "अहिलको पुनरावलोकन",
index cddc30e..b55cb76 100644 (file)
        "passwordreset-emailelement": "Username:\n$1\n\nTemporary password:\n$2",
        "passwordreset-emailsentemail": "If this email address is associated with your account, then a password reset email will be sent.",
        "passwordreset-emailsentusername": "If there is an email address associated with this username, then a password reset email will be sent.",
-       "passwordreset-emailsent-capture": "A password reset email has been sent, which is shown below.",
-       "passwordreset-emailerror-capture": "A password reset email was generated, which is shown below, but sending it to the {{GENDER:$2|user}} failed: $1",
        "passwordreset-emailsent-capture2": "The password reset {{PLURAL:$1|email has|emails have}} been sent. The {{PLURAL:$1|username and password|list of usernames and passwords}} is shown below.",
        "passwordreset-emailerror-capture2": "Emailing the {{GENDER:$2|user}} failed: $1 The {{PLURAL:$3|username and password|list of usernames and passwords}} is shown below.",
        "passwordreset-nocaller": "A caller must be provided",
        "changeemail": "Change or remove email address",
        "changeemail-summary": "",
        "changeemail-header": "Complete this form to change your email address. If you would like to remove the association of any email address from your account, leave the new email address blank when submitting the form.",
-       "changeemail-passwordrequired": "You will need to enter your password to confirm this change.",
        "changeemail-no-info": "You must be logged in to access this page directly.",
        "changeemail-oldemail": "Current email address:",
        "changeemail-newemail": "New email address:",
        "undo-nochange": "The edit appears to have already been undone.",
        "undo-summary": "Undo revision $1 by [[Special:Contributions/$2|$2]] ([[User talk:$2|talk]])",
        "undo-summary-username-hidden": "Undo revision $1 by a hidden user",
-       "cantcreateaccounttitle": "Cannot create account",
        "cantcreateaccount-text": "Account creation from this IP address (<strong>$1</strong>) has been blocked by [[User:$3|$3]].\n\nThe reason given by $3 is <em>$2</em>",
        "cantcreateaccount-range-text": "Account creation from IP addresses in the range <strong>$1</strong>, which includes your IP address (<strong>$4</strong>), has been blocked by [[User:$3|$3]].\n\nThe reason given by $3 is <em>$2</em>",
        "createaccount-hook-aborted": "$1",
        "uploadstash-errclear": "Clearing the files failed.",
        "uploadstash-refresh": "Refresh the list of files",
        "uploadstash-thumbnail": "view thumbnail",
+       "uploadstash-exception": "Could not store upload in the stash ($1): \"$2\".",
        "invalid-chunk-offset": "Invalid chunk offset",
        "img-auth-accessdenied": "Access denied",
        "img-auth-nopathinfo": "Missing PATH_INFO.\nYour server is not set up to pass this information.\nIt may be CGI-based and cannot support img_auth.\nSee https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Image_Authorization.",
index e6a2368..1cbfc2f 100644 (file)
        "passwordreset-emailelement": "Salutnomo: \n$1\n\nProvizora pasvorto: \n$2",
        "passwordreset-emailsentemail": "Se tiu ĉu retpoŝta adreso estas kunligita kun via konto, tiam al ĉi tiu adreso estos sendita retpoŝto por renovigi pasvorton.",
        "passwordreset-emailsentusername": "Se estas retpoŝta adreso, kiu estas asociita kun tiu uzantnomo, tiam ni sendos retpoŝtan mesaĝon pri reagordado de la pasvorto.",
-       "passwordreset-emailsent-capture": "Retpoŝto kun renovigita pasvorto estis sendita, kiu estas montrata malsupre.",
-       "passwordreset-emailerror-capture": "Retpoŝto kun renovigita pasvorto estis generita, montrata sube, sed sendado al la {{GENDER:$2|uzanto}} malsukcesis: $1",
        "passwordreset-emailsent-capture2": "La {{PLURAL:$1|retpoŝto|retpoŝtojn}} de pasvorta reensignado estis sendita. La {{PLURAL:$1|salutnomo kaj pasvorto|listo de salutnomoj kaj pasvortoj}} estas vidigita sube.",
        "passwordreset-emailerror-capture2": "Retpoŝtado al la {{GENDER:$2|uzantiĉo|uzantino|uzanto}} malsukcesis: $1 La {{PLURAL:$3|salutnomo kaj pasvorta|listo de salutnomoj kaj pasvortoj}} estas vidigita sube.",
        "passwordreset-nocaller": "Vokanto devas esti provizita",
        "passwordreset-nodata": "Nek salutnomo nek retpoŝta adreso estis provizita",
        "changeemail": "Ŝanĝi aŭ forigi retpoŝtadreson",
        "changeemail-header": "Plenigu ĉi tiun formularon por ŝanĝi vian retpoŝtadreson. Se vi volas forigi la difinon de retpoŝtadreso por via uzantokonto, lasu la kampon por la nova retpoŝtadreso malplena ĉe la transigo.",
-       "changeemail-passwordrequired": "Vi devas entajpi vian pasvorton, por konfirmi ĉi tiun ŝanĝon.",
        "changeemail-no-info": "Vi devas ensaluti por atingi ĉi tiun paĝon rekte.",
        "changeemail-oldemail": "Aktuala retpoŝtadreso:",
        "changeemail-newemail": "Nova retpoŝtadreso:",
        "undo-nochange": "Ŝajne la redakto jam estis malfarita.",
        "undo-summary": "Nuligis version $1 de [[Special:Contributions/$2|$2]] ([[User talk:$2|Diskuto]] | [[Special:Contributions/$2|{{MediaWiki:Contribslink}}]])",
        "undo-summary-username-hidden": "Malfari ŝanĝon $1 de kaŝita uzulo",
-       "cantcreateaccounttitle": "Ne eblas krei konton",
        "cantcreateaccount-text": "Konto-kreado de ĉi tiu IP-adreso ('''$1''') estis forbarita de [[User:$3|$3]].\n\nLa kialo donata de $3 estas ''$2''.",
        "cantcreateaccount-range-text": "La kreado de kontoj de IP-adresoj en la intervalo <strong>$1</strong>, kiu inkludas vian IP-adreson (<strong>$4</strong>), estis blokita de [[User:$3|$3]].\n\nLa donita kialo de $3 estas <em>$2</em>",
        "viewpagelogs": "Vidi la protokolojn por tiu ĉi paĝo",
        "group-bureaucrat": "Burokratoj",
        "group-suppress": "Foriganaro",
        "group-all": "(ĉiuj)",
-       "group-user-member": "{{GENDER:$1|uzanto|uzantino}}",
-       "group-autoconfirmed-member": "{{GENDER:$1|aŭtomate konfirmita uzanto|aŭtomate konfirmita uzantino}}",
+       "group-user-member": "{{GENDER:$1|uzanto}}",
+       "group-autoconfirmed-member": "{{GENDER:$1|aŭtomate konfirmita uzanto}}",
        "group-bot-member": "{{GENDER:$1|roboto}}",
        "group-sysop-member": "{{GENDER:$1|Administranto|Administrantino}}",
        "group-bureaucrat-member": "{{GENDER:$1|Burokrato|Burokratino}}",
        "namespace_association": "Asociita nomspaco",
        "tooltip-namespace_association": "Marku ĉi tiu skatolo por inkluzivi la diskutan aŭ teman nomspacon asocie de la elekta nomspaco",
        "blanknamespace": "(Ĉefa)",
-       "contributions": "Kontribuoj de {{GENDER:$1|uzanto|uzantino}}",
+       "contributions": "Kontribuoj de {{GENDER:$1|uzanto}}",
        "contributions-title": "Kontribuoj de uzanto $1",
        "mycontris": "Kontribuoj",
        "anoncontribs": "Kontribuoj",
        "lastmodifiedatby": "Ĉi paĝo estis laste ŝanĝita je $2, $1 de $3.",
        "othercontribs": "Bazita sur la laboro de $1.",
        "others": "aliaj",
-       "siteusers": "{{GENDER:$2|uzantiĉo|uzantino|uzanto}}{{PLURAL:$2||j}} $1 de {{SITENAME}}",
+       "siteusers": "{{PLURAL:$2|{{GENDER:$1|uzanto}}|uzantoj}} $1 de {{SITENAME}}",
        "anonusers": "{{SITENAME}}-{{PLURAL:$2|anonimulo|anonimuloj}} $1",
        "creditspage": "Atribuoj de paĝo",
        "nocredits": "Ne estas informo pri atribuoj por ĉi paĝo.",
index a9facb7..357b417 100644 (file)
        "passwordreset-emailelement": "Nombre de {{GENDER:$1|usuario|usuaria}}: \n$1\n\nContraseña temporal: \n$2",
        "passwordreset-emailsentemail": "Si esta dirección de correo electrónico está asociada a tu cuenta, entonces se enviará un correo electrónico para restablecer la contraseña.",
        "passwordreset-emailsentusername": "Si existe una dirección de correo electrónico asociada a este nombre de usuario, entonces se enviará un correo para restablecer la contraseña.",
-       "passwordreset-emailsent-capture": "Se ha enviado un correo para el restablecimiento de la contraseña, el cual se muestra a continuación.",
-       "passwordreset-emailerror-capture": "Se ha generado un correo electrónico de restablecimiento de contraseña, que se muestra a continuación, pero ha fallado el envío {{GENDER:$2|al usuario|a la usuaria}}: $1",
        "passwordreset-emailsent-capture2": "{{PLURAL:$1|El e-mail de restablecimiento de contraseña ha sido enviado|Los e-mails de restablecimiento de contraseña han sido enviados}}. {{PLURAL:$1|El nombre de usuario y la contraseña se muestra a continuación|La lista de nombres de usuarios y contraseñas se muestra a continuación}}.",
        "passwordreset-emailerror-capture2": "No fue posible mandar un correo electrónico {{Gender:$2|al usuario|a la usuaria}}: $1 {{PLURAL:$3|El nombre de usuario y la contraseña|La lista de nombres de usuarios y contraseñas}} se muestra a continuación.",
        "passwordreset-nocaller": "Debe de proporcionarse un interlocutor",
        "passwordreset-nodata": "No se ha proporcionado ni un nombre de usuario ni una dirección de correo electrónico",
        "changeemail": "Cambiar o eliminar la dirección de correo electrónico",
        "changeemail-header": "Completa este formulario para cambiar tu dirección de correo electrónico. Si quieres eliminar la asociación de cualquier dirección de correo electrónico con tu cuenta, deja en blanco la nueva dirección de correo electrónico cuando envíes el formulario.",
-       "changeemail-passwordrequired": "Tendrás que escribir tu contraseña para confirmar este cambio.",
        "changeemail-no-info": "Debes iniciar sesión para acceder directamente a esta página.",
        "changeemail-oldemail": "Dirección de correo electrónico actual:",
        "changeemail-newemail": "Dirección de correo electrónico nueva:",
        "undo-nochange": "Parece que ya se había deshecho la edición.",
        "undo-summary": "Se ha deshecho la revisión $1 de [[Special:Contributions/$2|$2]] ([[User talk:$2|disc.]])",
        "undo-summary-username-hidden": "Se ha deshecho la revisión $1 de un usuario oculto",
-       "cantcreateaccounttitle": "No se puede crear la cuenta",
        "cantcreateaccount-text": "[[User:$3|$3]] ha bloqueado la creación de cuentas desde esta dirección IP (<strong>$1</strong>).\n\nEl motivo dado por $3 es <em>$2</em>",
        "cantcreateaccount-range-text": "[[User:$3|$3]] ha bloqueado la creación de cuentas de usuario desde direcciones IP en el rango <strong>$1</strong>, en el que se encuentra tu dirección IP (<strong>$4</strong>).\n\nEl motivo dado por $3 es <em>$2</em>",
        "viewpagelogs": "Ver los registros de esta página",
        "watchnologin": "No has iniciado sesión",
        "addwatch": "Añadir a la lista de seguimiento",
        "addedwatchtext": "Se han añadido «[[:$1]]» y su página de discusión a tu [[Special:Watchlist|lista de seguimiento]].",
+       "addedwatchtext-talk": "Se han añadido «[[:$1]]» y su página asociada a tu [[Special:Watchlist|lista de seguimiento]].",
        "addedwatchtext-short": "La página \"$1\" ha sido añadida a tu lista de seguimiento.",
        "removewatch": "Quitar de la lista de seguimiento",
        "removedwatchtext": "Se han eliminado «[[:$1]]» y su página de discusión de tu [[Special:Watchlist|lista de seguimiento]].",
+       "removedwatchtext-talk": "Se han eliminado «[[:$1]]» y su página asociada de tu [[Special:Watchlist|lista de seguimiento]].",
        "removedwatchtext-short": "La página \"$1\" ha sido eliminada de tu lista de seguimiento.",
        "watch": "Vigilar",
        "watchthispage": "Vigilar esta página",
        "blocklist-timestamp": "Fecha y hora",
        "blocklist-target": "Destino",
        "blocklist-expiry": "Caduca",
-       "blocklist-by": "Administrador que bloqueó",
+       "blocklist-by": "Administrador que realizó el bloqueo",
        "blocklist-params": "Parámetros de bloqueo",
        "blocklist-reason": "Motivo",
        "ipblocklist-submit": "Buscar",
index 1b5d5e7..3b4e14f 100644 (file)
@@ -27,7 +27,8 @@
                        "Postituvi",
                        "Purodha",
                        "Macofe",
-                       "Adeliine"
+                       "Adeliine",
+                       "Metsavend"
                ]
        },
        "tog-underline": "Linkide allakriipsutus:",
        "passwordreset-emailelement": "Kasutajanimi: \n$1\n\nAjutine parool: \n$2",
        "passwordreset-emailsentemail": "Kui oled sidunud konto selle e-posti aadressiga, siis saadetakse sulle parooli lähtestamise e-kiri.",
        "passwordreset-emailsentusername": "Parooli lähtestamise e-kiri saadetakse, kui olemas on kontoga seotud e-posti aadress.",
-       "passwordreset-emailsent-capture": "E-kirjatsi on saadetud allpool näidatav parooli lähtestuskiri.",
-       "passwordreset-emailerror-capture": "Koostati allpool näidatav parooli lähtestuskiri, aga selle e-kirjatsi {{GENDER:$2|kasutajale}} saatmine ebaõnnestus: $1",
        "changeemail": "E-posti aadressi muutmine või eemaldamine",
        "changeemail-header": "Täida see vorm, et muuta oma e-posti aadress. Kui soovid, et konto poleks enam seotud ühegi e-posti aadressiga, siis jäta vormi esitamisel e-posti aadressi väli tühjaks.",
-       "changeemail-passwordrequired": "Et muudatus kinnitada, pead sisestama oma parooli.",
        "changeemail-no-info": "Otselingi kaudu sellele lehele jõudmiseks pead olema sisse loginud.",
        "changeemail-oldemail": "Praegune e-posti aadress:",
        "changeemail-newemail": "Uus e-posti aadress:",
        "minoredit": "See on pisiparandus",
        "watchthis": "Jälgi seda lehekülge",
        "savearticle": "Salvesta",
+       "publishpage": "Avalda lehekülg",
+       "publishchanges": "Avalda muudatused",
        "preview": "Eelvaade",
        "showpreview": "Näita eelvaadet",
        "showdiff": "Näita muudatusi",
        "undo-nochange": "Paistab, et see muudatus on juba eemaldatud.",
        "undo-summary": "Eemaldatud muudatus $1, mille tegi [[Special:Contributions/$2|$2]] ([[User talk:$2|arutelu]])",
        "undo-summary-username-hidden": "Eemaldatud redaktsioon $1, mille tegi peidetud kasutaja",
-       "cantcreateaccounttitle": "Ei saa kontot luua",
        "cantcreateaccount-text": "[[User:$3|$3]] on blokeerinud konto loomise sellelt IP-aadressilt (<strong>$1</strong>).\n\n$3 märkis järgmise põhjuse: <em>$2</em>",
        "cantcreateaccount-range-text": "Kontode loomine IP-aadressidelt vahemikus <strong>$1</strong>, millesse jääb sinu IP-aadress (<strong>$4</strong>), on blokeeritud. Blokeeris kasutaja [[User:$3|$3]].\n\n$3 tõi järgmise põhjuse: <em>$2</em>",
        "viewpagelogs": "Vaata selle lehekülje logisissekandeid",
        "tooltip-ca-nstab-category": "Näita kategooria lehte",
        "tooltip-minoredit": "Märgi see pisiparanduseks",
        "tooltip-save": "Salvesta muudatused",
+       "tooltip-publish": "Avalda oma muudatused",
        "tooltip-preview": "Näita tehtavaid muudatusi. Palun kasutage seda enne salvestamist!",
        "tooltip-diff": "Näita tehtavaid muudatusi.",
        "tooltip-compareselectedversions": "Näita erinevusi selle lehe kahe valitud versiooni vahel.",
index 13085dd..a79df94 100644 (file)
@@ -66,7 +66,7 @@
        "tog-ccmeonemails": "Beste erabiltzaileei bidaltzen dizkiedan mezuen kopiak niri ere bidali",
        "tog-diffonly": "''Diff''-ak agertzen direnean, orrialdearen edukiera ezkutatu",
        "tog-showhiddencats": "Ikusi kategoria ezkutuak",
-       "tog-norollbackdiff": "Rollback bat egin ondoren ezberdintasunak ez hartu aintzat",
+       "tog-norollbackdiff": "Rollback bat egin ondoren ezberdintasunak ez erakutsi",
        "tog-useeditwarning": "Abisa nazazu gorde gabeko aldaketak eginez orrialde bat uzten dudanean",
        "tog-prefershttps": "Erabili beti konexio seguru bat sartzerakoan",
        "underline-always": "Beti",
        "passwordreset-emailtitle": "{{SITENAME}}-rako kontuaren xehetasunak",
        "passwordreset-emailelement": "Erabiltzaile izena: \n$1\n\nBehin-behineko pasahitza: \n$2",
        "passwordreset-emailsentemail": "Hau zure konturako erregistratuta dagoen helbide elektronikoa baldin bada, mezu elektronikoa bidaliko da zure pasahitza berrezartzeko.",
-       "passwordreset-emailsent-capture": "Pasahitza berrezartzeko e-posta bat bidali dizugu, behean erakusten dena.",
        "changeemail": "Aldatu edo kendu e-mail helbidea",
        "changeemail-header": "Bete ezazu inprimaki hau, zure helbide elektronikoa aldatzeko. Zure kontuari helbide elektronikorik elkartuta ez izatea nahi baduzu, utz ezazu hutsik helbide elektroniko berria, inprimakia bidaltzen duzunean.",
        "changeemail-no-info": "Orrialde honetara zuzenean sartzeko izena eman behar duzu.",
        "undo-failure": "Ezin izan da aldaketa desegin tarteko aldaketekin gatazkak direla-eta.",
        "undo-norev": "Aldaketa ezin da desegin ez delako existitzen edo ezabatu zutelako.",
        "undo-summary": "[[Special:Contributions/$2|$2]] ([[User talk:$2|eztabaida]]) wikilariaren $1 berrikuspena desegin da",
-       "cantcreateaccounttitle": "Ezin izan da kontua sortu",
        "cantcreateaccount-text": "IP helbide honetatik ('''$1''') kontu berria sortzeko aukera blokeatu du [[User:$3|$3]](e)k.\n\n$3(e)k emandako arrazoia: ''$2''",
        "viewpagelogs": "Orrialde honen erregistroak ikusi",
        "nohistory": "Orrialde honek ez dauka aldaketa historiarik.",
index 28e2dd8..cd16fd1 100644 (file)
        "passwordreset-emailelement": "نام کاربری: \n$1\n\nگذرواژهٔ موقت: \n$2",
        "passwordreset-emailsentemail": "اگر نشانی پست الکترونیکی که وارد کردید برای حساب کاربریتان ثبت شده باشد، یک نامهٔ بازنشانی گذرواژه به آن فرستاده می‌شود.",
        "passwordreset-emailsentusername": "اگر نشانی پست الکترونیکی مرتبطی موجود باشد، یک نامه برای بازنشانی گذرواژه به آن ارسال خواهد شد.",
-       "passwordreset-emailsent-capture": "یک ایمیل بازنشانی که در پایین نمایش داده شده، فرستاده شده است.",
-       "passwordreset-emailerror-capture": "ایمیل بازنشانی، که در زیر نمایش داده شده، ایجاد شد، ولی ارسال آن به {{GENDER:$2|کاربر}} موفقیت‌آمیز نبود: $1",
        "passwordreset-emailsent-capture2": "{{PLURAL:$1|نامهٔ|نامهٔ}} بازنشانی گذرواژه ارسال شد. در زير $1 نام کاربری و گذرواژه در حال نمایش است.",
        "passwordreset-emailerror-capture2": "ارسال ناموفق نامه به $2: $1\nدر زير $3 نام کاربری و گذرواژه در حال نمایش است",
        "passwordreset-nocaller": "فراخواننده می‌بايست مشخص شده باشد",
        "passwordreset-nodata": "یک نام کاربری و یا یک آدرس ايميل، هيچکدام ارائه نشده",
        "changeemail": "تغییر یا حذف نشانی ایمیل",
        "changeemail-header": "برای تغییر ایمیلتان این فرم را کامل کنید. برای حذف ایملیتان کافی است بخش ایمیل را خالی رها کنید و فرم را ارسال کنید.",
-       "changeemail-passwordrequired": "برای تائید این تغییر باید گذرواژه‌تان را وارد کنید.",
        "changeemail-no-info": "برای دسترسی مستقیم به این صفحه شما باید به سامانه وارد شده باشید.",
        "changeemail-oldemail": "آدرس ایمیل کنونی:",
        "changeemail-newemail": "آدرس ایمیل جدید:",
        "undo-nochange": "به نظر می‌رسد ویرایش از پیش واگردانی شده است.",
        "undo-summary": "خنثی‌سازی ویرایش $1 توسط [[Special:Contributions/$2|$2]] ([[User talk:$2|بحث]])",
        "undo-summary-username-hidden": "خنثی‌سازی نسخهٔ $1 به دست یک کاربر پنهان‌شده",
-       "cantcreateaccounttitle": "نمی‌توان حساب باز کرد",
        "cantcreateaccount-text": "امكان ساختن حساب کاربری از این این نشانی آی‌پی ('''$1''') توسط [[User:$3|$3]] سلب شده است.\n\nدلیل ارائه شده توسط $3 چنین است: $2",
        "cantcreateaccount-range-text": "ایجاد حساب از آدرس آی‌پی در مجموعه‌ی <strong>$1</strong>، که شامل آدرس آی‌پی شما (<strong>$4</strong>) است، توسط [[User:$3|$3]] متوقف شده‌است.\nدلیل ارائه شده توسط $3، $2 است.",
        "viewpagelogs": "نمایش سیاهه‌های این صفحه",
index dda086c..74de0d5 100644 (file)
        "passwordreset-emailelement": "Käyttäjätunnus: \n$1\n\nVäliaikainen salasana: \n$2",
        "passwordreset-emailsentemail": "Jos tämä on sinun tunnuksellesi rekisteröity sähköpostiosoite, salasanan uudistamisesta kertova viesti lähetetään.",
        "passwordreset-emailsentusername": "Jos on olemassa vastaava rekisteröity sähköpostiosoite, salasanan uudistamisesta kertova viesti lähetetään.",
-       "passwordreset-emailsent-capture": "Salasanan uudistamisesta kertova sähköpostiviesti on lähetetty, ja se näkyy myös alla.",
-       "passwordreset-emailerror-capture": "Allaoleva sähköpostiviesti luotiin, mutta sen lähettäminen {{GENDER:$2|käyttäjälle}} epäonnistui: $1",
        "passwordreset-emailsent-capture2": "Salasananpalautus{{PLURAL:$1|sähköposti|sähköpostit}} on lähetetty. {{PLURAL:$1|Käyttäjä ja salasana|Luettelo käyttäjistä ja salasanoista}} näytetään alapuolella.",
        "passwordreset-emailerror-capture2": "Sähköpostin lähettäminen {{GENDER:$2|käyttäjälle}} epäonnistui: $1 {{PLURAL:$3|Käyttäjänimi ja salasana|Luettelo käyttäjänimistä ja salasanoista}} näytetään alla.",
        "passwordreset-invalideamil": "Virheellinen sähköpostiosoite",
        "passwordreset-nodata": "Käyttäjätunnusta ja salasanaa ei annettu",
        "changeemail": "Muuta tai poista sähköpostiosoite",
        "changeemail-header": "Täydennä tämä lomake, jolla voit muuttaa sähköpostiosoitettasi. Jos haluat poistaa sähköpostiosoitteesi kokonaan tunnuksesi yhteydestä, älä kirjoita uudeksi osoitteeksi mitään vaan jätä se tyhjäksi.",
-       "changeemail-passwordrequired": "Sinun on syötettävä salasanasi vahvistaaksesi tämän muutoksen.",
        "changeemail-no-info": "Tämän sivun käyttö edellyttää sisäänkirjautumista.",
        "changeemail-oldemail": "Nykyinen sähköpostiosoite:",
        "changeemail-newemail": "Uusi sähköpostiosoite:",
        "undo-nochange": "Tämä muokkaus näyttää olevan jo kumottu.",
        "undo-summary": "Kumottu muokkaus $1, jonka teki [[Special:Contributions/$2|$2]] ([[User talk:$2|keskustelu]])",
        "undo-summary-username-hidden": "Kumottu muokkaus $1, jonka on tehnyt piilotettu käyttäjä",
-       "cantcreateaccounttitle": "Tunnusta ei voida luoda",
        "cantcreateaccount-text": "Tunnusten luonti tästä IP-osoitteesta ('''$1''') on estetty. Estäjänä on [[User:$3|$3]].\n\nKäyttäjän $3 antama syy on ''$2''",
        "cantcreateaccount-range-text": "Tunnusten luominen IP-osoitteista osoitealueella <strong>$1</strong>, johon kuuluu myös sinun käyttämäsi IP-osoite (<strong>$4</strong>), on estetty. Eston on asettanut [[User:$3|$3]].\n\nSyy estolle on \"$2\".",
        "viewpagelogs": "Näytä tämän sivun lokit",
index 116ae3a..b988fba 100644 (file)
        "passwordreset-emailelement": "Nom d’utilisateur : \n$1\n\nMot de passe temporaire : \n$2",
        "passwordreset-emailsentemail": "Si cette adresse de courriel est associée à votre compte, alors un courriel de réinitialisation de mot de passe sera envoyé.",
        "passwordreset-emailsentusername": "S’il y a une adresse de courriel associée à ce nom d’utilisateur, alors un courriel de réinitialisation de mot de passe sera envoyé.",
-       "passwordreset-emailsent-capture": "Un courriel de réinitialisation de mot de passe a été envoyé, qui est affiché ci-dessous.",
-       "passwordreset-emailerror-capture": "Un courriel de réinitialisation de mot de passe a été généré, qui est affiché ci-dessous, mais l’envoi à l’{{GENDER:$2|utilisateur|utilisatrice}} a échoué : $1",
        "passwordreset-emailsent-capture2": "{{PLURAL:$1|Le courriel de réinitialisation du mot de passe a été envoyé|Les courriels de réinitialisation du mot de passe ont été envoyés}}. {{PLURAL:$1|Le nom d’utilisateur et le mot de passe sont affichés|La liste des noms d’utilisateur et mots de passe est affichée}} ci-dessous.",
        "passwordreset-emailerror-capture2": "L’envoi de courriel à {{GENDER:$2|l’utilisateur|l’utilisatrice}} a échoué : $1 {{PLURAL:$3|Le nom d’utilisateur et le mot de passe sont affichés|La liste des noms d’utilisateur et des mots de passe est affichée}} ci-dessous.",
        "passwordreset-nocaller": "Un appelant doit être fourni",
        "passwordreset-nodata": "Aucun nom d’utilisateur ou adresse de messagerie n’a été fourni",
        "changeemail": "Changer ou supprimer l’adresse de courriel",
        "changeemail-header": "Complétez ce formulaire pour modifier votre adresse de courriel. Si vous voulez supprimer l’association d’une adresse de courriel avec votre compte, laissez la nouvelle adresse de courriel vide lors de la soumission du formulaire.",
-       "changeemail-passwordrequired": "Vous devrez saisir votre mot de passe pour confirmer cette modification.",
        "changeemail-no-info": "Vous devez être connecté pour pouvoir accéder directement à cette page.",
        "changeemail-oldemail": "Adresse de courriel actuelle :",
        "changeemail-newemail": "Nouvelle adresse de courriel :",
        "undo-nochange": "Il semblerait que la modification ait déjà été annulée.",
        "undo-summary": "Annulation des modifications $1 de [[Special:Contributions/$2|$2]] ([[User talk:$2|discussion]])",
        "undo-summary-username-hidden": "Annuler la révision $1 par un utilisateur masqué",
-       "cantcreateaccounttitle": "Vous ne pouvez pas créer de compte.",
        "cantcreateaccount-text": "La création de compte depuis cette adresse IP (<strong>$1</strong>) a été bloquée par [[User:$3|$3]]. \n\nLa raison donnée par $3 était : <em>$2</em>",
        "cantcreateaccount-range-text": "La création de compte depuis les adresses IP de la plage <strong>$1</strong>, où se trouve votre adresse IP (<strong>$4</strong>), a été bloquée par [[User:$3|$3]].\n\nLe motif fourni par $3 est <em>$2</em>",
        "viewpagelogs": "Voir les opérations sur cette page",
        "filename-bad-prefix": "Le nom du fichier commence par <strong>« $1 »</strong> qui est typiquement un nom non-descriptif attribué automatiquement par les appareils photo numériques.\nVeuillez choisir un nom de fichier plus descriptif.",
        "filename-prefix-blacklist": " #<!-- laisser cette ligne telle quelle --><pre>\n# La syntaxe est la suivante :\n#  * Tout ce qui figure entre un caractère \"#\" jusqu’à la fin de la ligne est un commentaire ;\n#  * Toute ligne non vide est un préfixe typique de nom de fichier assigné automatiquement par les appareils numériques :\nCIMG # Casio\nDSC_ # Nikon\nDSCF # Fuji\nDSCN # Nikon\nDUW # certains téléphones mobiles\nIMG # générique\nJD # Jenoptik\nMGP # Pentax\nPICT # divers\n #</pre><!-- laisser cette ligne telle quelle -->",
        "upload-proto-error": "Protocole incorrect",
-       "upload-proto-error-text": "L’import requiert des URL commençant par <code>http://</code> ou <code>ftp://</code>.",
+       "upload-proto-error-text": "L’import à distance requiert que les URL commencent par <code>http://</code> ou <code>ftp://</code>.",
        "upload-file-error": "Erreur interne",
        "upload-file-error-text": "Une erreur interne est survenue en voulant créer un fichier temporaire sur le serveur. \nVeuillez contacter un [[Special:ListUsers/sysop|administrateur]].",
        "upload-misc-error": "Erreur d’import inconnue",
        "upload-dialog-button-upload": "Téléverser",
        "upload-form-label-infoform-title": "Détails",
        "upload-form-label-infoform-name": "Nom",
-       "upload-form-label-infoform-name-tooltip": "Un titre descriptif unique pour le fichier, qui servira comme nom de fichier. Vous pouvez utiliser du langage courant avec des espaces. Ne pas inclure l’extension du fichier.",
+       "upload-form-label-infoform-name-tooltip": "Un titre descriptif unique pour le fichier, qui servira comme nom de fichier. Vous pouvez utiliser le langage courant avec des espaces. Ne pas inclure l’extension du fichier.",
        "upload-form-label-infoform-description": "Description",
        "upload-form-label-infoform-description-tooltip": "Décrire brièvement tout ce qu’il y a de particulier concernant cette œuvre.\nPour une photo, mentionner les choses principales qui sont vues, l’occasion, ou l’endroit.",
        "upload-form-label-usage-title": "Utilisation",
        "upload-form-label-not-own-work-local-generic-local": "Vous pouvez aussi essayer [[Special:Upload|la page de téléchargement par défaut]].",
        "upload-form-label-own-work-message-generic-foreign": "Je comprends que je téléverse ce fichier vers un dépôt partagé. Je confirme agir en accord avec les conditions d’utilisation et les règles relatives aux licences de celui-ci.",
        "upload-form-label-not-own-work-message-generic-foreign": "Si vous n’êtes pas en mesure de téléverser ce fichier de façon conforme aux règles de ce dépôt partagé, veuillez fermer cette boîte de dialogue et essayer une autre méthode.",
-       "upload-form-label-not-own-work-local-generic-foreign": "Vous pouvez également essayer d’utiliser [[Special:Upload|la page de téléversement de {{SITENAME}}]], si les règles du site autorisent le téléversement du fichier.",
-       "backend-fail-stream": "Impossible de lire le fichier $1.",
-       "backend-fail-backup": "Impossible de sauvegarder le fichier $1.",
+       "upload-form-label-not-own-work-local-generic-foreign": "Vous pouvez également essayer d’utiliser [[Special:Upload|la page de téléversement de {{SITENAME}}]], si leur règles de site autorisent le téléversement du fichier.",
+       "backend-fail-stream": "Impossible de lire le fichier \"$1\".",
+       "backend-fail-backup": "Impossible de sauvegarder le fichier \"$1\".",
        "backend-fail-notexists": "Le fichier $1 n’existe pas.",
        "backend-fail-hashes": "Impossible d’obtenir les hachages du fichier pour comparaison.",
-       "backend-fail-notsame": "Un fichier différent existe déjà pour $1 .",
+       "backend-fail-notsame": "Un fichier différent existe déjà pour \"$1\" .",
        "backend-fail-invalidpath": "$1 n’est pas un chemin de stockage valide.",
-       "backend-fail-delete": "Impossible de supprimer le fichier $1.",
+       "backend-fail-delete": "Impossible de supprimer le fichier \"$1\".",
        "backend-fail-describe": "Impossible de modifier les métadonnées du fichier « $1 ».",
-       "backend-fail-alreadyexists": "Le fichier $1 existe déjà.",
+       "backend-fail-alreadyexists": "Le fichier \"$1\" existe déjà.",
        "backend-fail-store": "Impossible de stocker le fichier $1 en $2.",
        "backend-fail-copy": "Impossible de copier le fichier $1 en $2.",
        "backend-fail-move": "Impossible de déplacer le fichier $1 en $2.",
index ddc6770..416d1fd 100644 (file)
        "passwordreset-emailtext-user": "Dh'iarr an cleachdaiche $1 air {{SITENAME}} ath-shuidheachadh an fhacail-fhaire air {{SITENAME}} ($4). Tha {{PLURAL:$3|an cunntas-cleachdaiche|na cunntasan-cleachdaiche}} a leanas co-cheangailte ris an t-seòladh puist-d seo:\n\n$2\n\nFalbhaidh an ùine air {{PLURAL:$3|an fhacal-fhaire shealach|na faclan-faire sealach}} seo an ceann $5 {{PLURAL:$5|latha|latha|làithean|latha}}.\nBu chòir dhut logadh a-steach agus facal-faire ùr a thaghadh an-dràsta. Ma dh'iarr cuideigin eile seo no ma chuimhnich thu air an fhacal-fhaire agad 's mur eil thu airson atharrachadh tuilleadh, leig seachad an teachdaireachd seo 's lean ort leis an t-seann fhacal-fhaire.",
        "passwordreset-emailelement": "Ainm-cleachdaiche: \n$1\n\nFacal-faire sealach: \n$2",
        "passwordreset-emailsentemail": "Ma tha am post-d seo co-cheangailte ris a’ chunntas agad, thèid post-d airson ath-shuidheachadh an fhacail-fhaire a chur.",
-       "passwordreset-emailsent-capture": "Chaidh post-d a chum ath-shuidheachadh an fhacail-fhaire a chur agus chì thu sin gu h-ìosal.",
-       "passwordreset-emailerror-capture": "Chaidh post-d a chum ath-shuidheachadh an fhacail-fhaire a ghintinn agus chì thu sin gu h-ìosal ach cha b' urrainn dhuinn a chur dhan chleachdaiche: $1",
        "changeemail": "Atharraich no thoir air falbh an seòladh puist-d",
        "changeemail-header": "Lìon am foirm seo a dh’atharrachadh an t-seòlaidh phuist-d agad. Ma tha thu airson an co-cheangal eadar post-d sam bith is an cunntas agad a thoirt air falbh, fàg an seòladh ùr bàn nuair a chuireas tu am foirm.",
        "changeemail-no-info": "Feumaidh tu logadh a-steach mus dèan thu inntrigeadh dìreach dhan duilleag seo.",
        "minoredit": "Seo mùthadh beag",
        "watchthis": "Cum sùil air an duilleag seo",
        "savearticle": "Sàbhail an duilleag",
+       "publishpage": "Foillsich an duilleag",
+       "publishchanges": "Foillsich mùthaidhean",
        "preview": "Ro-shealladh",
        "showpreview": "Seall an ro-shealladh",
        "showdiff": "Seall na mùthaidhean",
        "undo-nochange": "Tha coltas gun deach am mùthadh seo a neo-dhèanamh mu thràth.",
        "undo-summary": "Neo-dhèan mùthadh $1 leis [[Special:Contributions/$2|$2]] ([[User talk:$2|an deasbaireachd]])",
        "undo-summary-username-hidden": "Neo-dhèan am mùthadh $1 le cleachdaiche falaichte",
-       "cantcreateaccounttitle": "Cha ghabh an cunntas a chruthachadh",
        "cantcreateaccount-text": "Chuir [[User:$3|$3]] bacadh air cruthachadh chunntasan on t-seòladh IP seo (<strong>$1</strong>).\n\nDh'innis $3 gun do rinn {{GENDER:$3|e|i}} seo air sgàth: <em>$2</em>",
        "cantcreateaccount-range-text": "Chuir [[User:$3|$3]] casg air daoine a tha airson cunntasan a chruthachadh on sheòlaidhean IP taobh a-staigh na rainse <strong>$1</strong> agus tha sin a' gabhail a-steach an t-seòlaidh IP agad-sa (<strong>$4</strong>).\n\nDh'innis $3 gun do {{GENDER:$1|rinn e|rinn i|rinneadh}} seo air sgàth an adhbhair seo: <em>$2</em>",
        "viewpagelogs": "Seall logaichean na duilleige seo",
        "tooltip-ca-nstab-category": "Seall duilleag na roinn-seòrsa",
        "tooltip-minoredit": "Comharraich seo mar dheasachadh beag",
        "tooltip-save": "Sàbhail na mùthaidhean agad",
+       "tooltip-publish": "Foillsich na mùthaidhean agad",
        "tooltip-preview": "Ro-sheall na mùthaidhean agad; saoil an cleachd thu seo mus sàbhail thu iad?",
        "tooltip-diff": "Seall na mùthaidhean a chuir mi air an teacs",
        "tooltip-compareselectedversions": "Seall an diofar eadar an dà mhùthadh dhen duilleag seo a thagh thu",
index f729895..f9f91b4 100644 (file)
        "passwordreset-emailelement": "Nome de usuario: \n$1\n\nContrasinal temporal: \n$2",
        "passwordreset-emailsentemail": "Se esta é unha dirección de correo electrónico asociada á súa conta, entón enviarase un correo electrónico para o restablecemento do seu contrasinal.",
        "passwordreset-emailsentusername": "Se hai unha dirección de correo electrónico asociada con este nome de usuario, entón enviarase un correo electrónico para o restablecemento do contrasinal.",
-       "passwordreset-emailsent-capture": "Enviouse un correo electrónico de restablecemento do contrasinal, mostrado a continuación.",
-       "passwordreset-emailerror-capture": "Xerouse un correo electrónico de restablecemento do contrasinal, mostrado a continuación, pero o envío {{GENDER:$2|ao usuario|á usuaria}} fallou: $1",
        "passwordreset-emailsent-capture2": "{{PLURAL:$1|O correo de reinicialización do contrasinal foi enviado|Os correos de reinicialización do contrasinal foron enviados}}. {{PLURAL:$1|O nome de usuario e contrasinal móstrase abaixo|A lista de nomes de usuarios e contrasinais móstranse abaixo}}.",
        "passwordreset-emailerror-capture2": "O envío do correo {{GENDER:$2|ó usuario|á usuaria}} fallou: $1 {{PLURAL:$3|O nome de usuario e contrasinal móstrase abaixo|A lista de usuarios e contrasinais móstranse abaixo}}.",
        "passwordreset-nocaller": "Cómpre proporcionar un chamador",
        "passwordreset-nodata": "Non se indicou o nome de usuario ou a dirección de correo electrónico",
        "changeemail": "Cambiar ou eliminar o enderezo de correo electrónico",
        "changeemail-header": "Encha este formulario para cambiar o seu enderezo de correo electrónico. Se vostede quere eliminar a asociación da dirección de correo electrónico da súa conta, deixe en branco a nova dirección de correo electrónico cando envíe o formulario.",
-       "changeemail-passwordrequired": "Terá que escribir o seu contrasinal para confirmar este cambio.",
        "changeemail-no-info": "Debe rexistrarse para acceder directamente a esta páxina.",
        "changeemail-oldemail": "Enderezo de correo electrónico actual:",
        "changeemail-newemail": "Novo enderezo de correo electrónico:",
        "undo-nochange": "Semella que alguén xa desfixo a edición.",
        "undo-summary": "Desfíxose a edición $1 de [[Special:Contributions/$2|$2]] ([[User talk:$2|conversa]])",
        "undo-summary-username-hidden": "Desfíxose a edición $1 dun usuario agochado",
-       "cantcreateaccounttitle": "Non pode crear unha conta de usuario",
        "cantcreateaccount-text": "A creación de contas desde este enderezo IP ('''$1''') foi bloqueada por [[User:$3|$3]].\n\nA razón dada por $3 foi ''$2''",
        "cantcreateaccount-range-text": "O usuario [[User:$3|$3]] bloqueou a creación de contas desde enderezos IP no rango <strong>$1</strong>, no que se inclúe o seu enderezo IP (<strong>$4</strong>).\n\nA razón que deu $3 foi <em>$2</em>.",
        "viewpagelogs": "Ver os rexistros desta páxina",
index 807ce58..80cf567 100644 (file)
        "passwordreset-emailtext-user": "વેબસાઈટ  {{SITENAME}} ના વપરાશકર્તા $1 એ તમારા {{SITENAME}} ($4) નો પાસવર્ડ રિસેટ કરવાની રજૂઆત કરી છે. આ ઈમેઈલ એડ્રેસ સાથે {{PLURAL:$3|નું ખાતું|ના ખાતા}} જોડાયેલ છે.\n\n$2\n\n{{PLURAL:$3|આ કામચલાઉ પાસવર્ડ|આ બધા કામચલાઉ પાસવર્ડ}} {{PLURAL:$5|એક દિવસ|$5 દિવસ}} માં નષ્ટ થઇ જશે. તમારે અત્યારે જ ખાતું ખોલીને નવો પાસવર્ડ સેટ કરી લેવો જોઈએ .જો કોઈ બીજા એ આ રજૂઆત કરી હોય, અથવા જો તમને પોતાનો અસલ પાસવર્ડ યાદ હોય, અને તેને બદલવા નથી માગતા, તો આ સંદેશાને જતો કરીને પોતાના અસલ પાસવર્ડ ને વાપરી શકો છો..",
        "passwordreset-emailelement": "વપરાશકર્તા નામ: \n$1\n\nકામચલાઉ પાસવર્ડ: \n$2",
        "passwordreset-emailsentemail": "પાસવર્ડ બદલવાનો ઇમેલ મોકલવામાં આવ્યો છે.",
-       "passwordreset-emailsent-capture": "પાસવર્ડ બદલવાનો ઇમેલ મોકલવામાં આવ્યો છે, જે નીચે પ્રમાણે છે.",
-       "passwordreset-emailerror-capture": "પાસવર્ડ ફરી ગોઠવવા માટેનો ઇમેલ બનાવવામાં આવ્યો છે, જે નીચે પ્રમાણે છે, પરંતુ તે {{GENDER:$2|સભ્ય}}ને મોકલવામાં નિષ્ફળ થયો છે: $1",
        "changeemail": "ઇમેલ સરનામું બદલો",
        "changeemail-header": "તમારા ખાતાનું ઇમેલ સરનામું બદલો",
        "changeemail-no-info": "બારોબાર આ પાનું જોવા માટે પ્રવેશ કરવો આવશ્યક છે.",
        "undo-failure": "વચ્ચે થયેલા અન્ય ફેરફાર થવાને કારણે આ ફેરફારો ઉલટાવી ન શકાયા",
        "undo-norev": "ફેરફાર સાચવી ન શકાયો કેમકે તે અસ્તિત્વમાં નથી અથવા તો ભૂંસી નખાયો છે.",
        "undo-summary": "[[Special:Contributions/$2|$2]] ([[User talk:$2|talk]])એ કરેલો ફેરફાર $1 પાછો વાળ્યો",
-       "cantcreateaccounttitle": "ખાતું ખોલી શકાય તેમ નથી",
        "cantcreateaccount-text": "આ IP સરનામા  ('''$1''') પર નવા ખાતાની રચના પર   [[User:$3|$3]] દ્વારા રોક લગાવાઇ છે.\n\n\n$3 દ્વારા અપાયેલ કારણ છે ''$2''",
        "viewpagelogs": "આ પાનાનાં લૉગ જુઓ",
        "nohistory": "આ પાનાનાં ફેરફારનો ઇતિહાસ નથી.",
index b4b9c89..228c715 100644 (file)
        "passwordreset-emailelement": "שם משתמש:\n$1\n\nסיסמה זמנית:\n$2",
        "passwordreset-emailsentemail": "אם כתובת הדואר האלקטרוני הזאת משויכת לחשבון שלך, אז יישלח דואר אלקטרוני לאיפוס הסיסמה.",
        "passwordreset-emailsentusername": "אם יש כתובת דואר אלקטרוני שמשויכת לשם המשתמש הזה, אז יישלח דואר אלקטרוני לאיפוס הסיסמה.",
-       "passwordreset-emailsent-capture": "נשלח דואר אלקטרוני לאיפוס הסיסמה, והוא מוצג להלן.",
-       "passwordreset-emailerror-capture": "נוצר דואר אלקטרוני לאיפוס הסיסמה, והוא מוצג להלן, אך שליחתו ל{{GENDER:$2|משתמש|משתמשת}} נכשלה: $1",
        "passwordreset-emailsent-capture2": "{{PLURAL:$1|דוא\"ל איפוס הסיסמה נשלח|הודעות דוא\"ל של איפוס הסיסמה נשלחו}}. {{PLURAL:$1|שם המשתמשים והסיסמה מוצגים|רשימה של שמות המשתמשים והסיסמאות מוצגת}} להלן.",
        "passwordreset-emailerror-capture2": "לא ניתן היה לשלוח דוא\"ל ל{{GENDER:$2|משתמש|משתמשת}}: $1 {{PLURAL:$3|שם המשתמש והסיסמה מוצגים|רשימה של שמות המשתמשים והסיסמאות מוצגת}} להלן.",
        "passwordreset-nocaller": "לא סופק הקורא הנדרש",
        "passwordreset-nodata": "לא סופק שם משתמש או כתובת דוא\"ל",
        "changeemail": "שינוי או הסרת כתובת דוא\"ל",
        "changeemail-header": "יש למלא את הטופס הזה כדי לשנות את כתובת הדוא\"ל שלך. אם ברצונך להימנע משיוך כתובת דוא\"ל כלשהי לחשבון שלך, יש להשאיר את שדה כתובת הדוא\"ל החדשה ריק בעת שליחת הטופס.",
-       "changeemail-passwordrequired": "יש להקליד את הסיסמה שלך כדי לאשר את השינוי.",
        "changeemail-no-info": "נדרשת כניסה לחשבון כדי לגשת לדף זה ישירות.",
        "changeemail-oldemail": "כתובת דוא\"ל נוכחית:",
        "changeemail-newemail": "כתובת דוא\"ל חדשה:",
        "undo-nochange": "נראה שהעריכה כבר בוטלה.",
        "undo-summary": "ביטול גרסה $1 של [[Special:Contributions/$2|$2]] ([[User talk:$2|שיחה]])",
        "undo-summary-username-hidden": "ביטול גרסה $1 של משתמש מוסתר",
-       "cantcreateaccounttitle": "לא ניתן ליצור את החשבון",
        "cantcreateaccount-text": "אפשרות יצירת החשבונות מכתובת ה־IP הזאת (<strong>$1</strong>) נחסמה על־ידי [[User:$3|$3]].\n\nהסיבה שניתנה על־ידי $3 היא \"$2\".",
        "cantcreateaccount-range-text": "אפשרות יצירת החשבונות מכתובות IP בתוך הטווח <strong>$1</strong>, כולל כתובת ה־IP שלך (<strong>$4</strong>), נחסמה על־ידי [[User:$3|$3]].\n\nהסיבה שניתנה על־ידי $3 היא \"$2\".",
        "viewpagelogs": "הצגת יומנים עבור דף זה",
index 17f116b..9603a3f 100644 (file)
        "passwordreset-emailtext-user": "Suradnik $1 na {{SITENAME}} zatražio podsjetnik o pojedinostima vašeg računa za {{SITENAME}}\n($4). Sljedeći {{PLURAL:$3|račun suradnika je|računi suradnika su}} povezani s ovom e-mail adresom:\n\n$2\n\n{{PLURAL:$3|Ova privremena lozinka|Ove privremene lozinke}} će isteći u {{PLURAL:$5|jedan dan|$5 dana}}.\nTrebate se prijaviti i odabrati novu lozinku. Ukoliko je netko drugi napravio ovaj\nzahtjev, ili ako ste sjeti Vaše izvorne lozinke, a vi je više ne želite promijeniti, \nmožete zanemariti ovu poruku i nastavite koristiti staru lozinku.",
        "passwordreset-emailelement": "Suradničko ime: \n$1\n\nPrivremena lozinka: \n$2",
        "passwordreset-emailsentemail": "Ako je ova adresa povezana s Vašim suradničkim računom, na nju će biti poslan podsjetnik na zaporku.",
-       "passwordreset-emailsent-capture": "Poslan Vam je podsjetnik kao e-pošta (tekst je prikazan dolje).",
-       "passwordreset-emailerror-capture": "Napravljena je e-poruka za ponovno postavljanje zaporke (prikazana ispod), ali njeno slanje suradniku nije uspjelo: $1",
        "changeemail": "Promijeni ili izbriši e-mail adresu",
        "changeemail-header": "Promijeni adresu e-pošte računa",
        "changeemail-no-info": "Morate biti prijavljeni da biste izravno pristupili ovoj stranici.",
        "undo-norev": "Izmjena nije mogla biti uklonjena jer ne postoji ili je obrisana.",
        "undo-nochange": "Čini se da je uređivanje već otkazano.",
        "undo-summary": "uklanjanje izmjene $1 {{GENDER:$2|suradnika|suradnice}} [[Posebno:Doprinosi/$2|$2]] ([[Razgovor sa suradnikom:$2|razgovor]])",
-       "cantcreateaccounttitle": "Nije moguće stvoriti suradnički račun",
        "cantcreateaccount-text": "Otvaranje suradničkog računa ove IP adrese ('''$1''') blokirao/la je [[User:$3|$3]].\n\nRazlog koji je dao/la $3 je ''$2''",
        "viewpagelogs": "Vidi evidencije za ovu stranicu",
        "nohistory": "Ova stranica nema starijih izmjena.",
index b2daf38..007eada 100644 (file)
        "passwordreset-emailtext-user": "Wužiwar $1 na {{GRAMMAR:lokatiw|{{SITENAME}}}} je anulowanje twojeho hesła za {{GRAMMAR:akuzatiw|{{SITENAME}}}} požadał ($4).  {{PLURAL:$3|Slědowace wužiwarske konto je|Slědowacej wužiwarskej konće stej|Slědowace wužiwarske konta su}} z tutej e-mejlowej adresu {{PLURAL:$3|zwjazane|zwjazanej|zwjazane}}:\n\n$2\n\n{{PLURAL:$3|Tute nachwilne hesło spadnje|Tutej nachwilnej hesle spadnjetej|Tute nachwilne hesła spadnu}} za {{PLURAL:$5|jedyn dźeń|$5 dnjej|$5 dny|$5 dnjow}}.\nTy měł so nětko přizjewić a nowe hesło wubrać. Jeli něchtó druhi je tute naprašowanje pósłał, abo jeli sy so zaso na prěnjotne hesło dopomnił a wjace nochceš jo změnić, móžeš tutu zdźělenku ignorować a swoje stare hesło dale wužiwać.",
        "passwordreset-emailelement": "Wužiwarske mjeno: \n$1\n\nNachwilne hesło: \n$2",
        "passwordreset-emailsentemail": "Jeli tuta e-mejlowa adresa je z wašim kontom zwjazana, so mejlka za wróćostajenje hesła pósćele.",
-       "passwordreset-emailsent-capture": "E-mejl za anulowanje hesła je so pósłała, kotraž so deleka pokazuje.",
-       "passwordreset-emailerror-capture": "E-mejl za anulowanje hesła je so wutworiła, kotraž so deleka pokazuje, ale słanje {{GENDER:$2|wužiwarjej|wužiwarce}} je so njeporadźiło: $1",
        "changeemail": "E-mejlowu adresu změnić abo wotstronić",
        "changeemail-header": "Wupjelń tutón formular, zo by swoju e-mejlowu adresu změnił. Jeli chceš zwisk e-mejloweje adresy ze swijim kontom wotstronić,  wostaj polo e-mejloweje adresy prózdne, hdyž formular preč sćeleš.",
        "changeemail-no-info": "Dyrbiš so přizjewić, zo by direktny přistup na tutu stronu měł.",
        "minoredit": "Snadna změna",
        "watchthis": "Stronu wobkedźbować",
        "savearticle": "Stronu składować",
+       "publishpage": "Stronu wozjewić",
+       "publishchanges": "Změny wozjewić",
        "preview": "Přehlad",
        "showpreview": "Přehlad pokazać",
        "showdiff": "Změny pokazać",
        "undo-nochange": "Zda so, zo změna je so hižo cofnyła.",
        "undo-summary": "Změna $1 [[Special:Contributions/$2|$2]] ([[User talk:$2|diskusija]]) bu cofnjena.",
        "undo-summary-username-hidden": "Změna $1 schowaneho wužiwarja je so anulowała",
-       "cantcreateaccounttitle": "Wužiwarske konto njeda so wutworić.",
        "cantcreateaccount-text": "Wutworjenje wužiwarskeho konta z IP-adresy '''$1''' bu wot [[User:$3|$3]] zablokowane.\n\nPřičina za blokowanje, podata wot $3, je: ''$2''",
        "cantcreateaccount-range-text": "Załoženje kontow z IP-adresow we wobłuku '''$1'', kotryž twoju IP-adresu wobsahuje (<strong>$4</strong>), je so wot [[User:$3|$3]] zablokowało.\n\nPřičina podata wot $3 je <em>$2</em>",
        "viewpagelogs": "protokole tuteje strony pokazać",
index 75ef088..17df2d7 100644 (file)
        "parser-template-recursion-depth-warning": "Limit depase pou kantite fwa yon modèl ka rele tèt li ($1)",
        "language-converter-depth-warning": "Limit sou pwofondè konvètisè lang yo depase ($1)",
        "undo-summary": "Revoke revizyon $1 ki te fèt pa [[Special:Contributions/$2|$2]] ([[User talk:$2|diskite]])",
-       "cantcreateaccounttitle": "Ou pa kapab kreye yon kont.",
        "viewpagelogs": "gade jounal paj sa a",
        "nohistory": "Istorik pou paj sa pa egziste ditou.",
        "currentrev": "Vèsyon kounye a",
index c0acf2e..9ad03b8 100644 (file)
        "password-change-forbidden": "Nem módosíthatod a jelszót ezen a wikin.",
        "externaldberror": "Hiba történt a külső adatbázis hitelesítése közben, vagy nem vagy jogosult a külső fiókod frissítésére.",
        "login": "Bejelentkezés",
+       "login-security": "Személyazonosságod igazolása",
        "nav-login-createaccount": "Bejelentkezés / fiók létrehozása",
        "userlogin": "Bejelentkezés / fiók létrehozása",
        "userloginnocreate": "Bejelentkezés",
        "userlogin-resetpassword-link": "Elfelejtetted a jelszavad?",
        "userlogin-helplink2": "Segítség a bejelentkezéshez",
        "userlogin-loggedin": "Már be vagy jelentkezve mint {{GENDER:$1|$1}}. Ha más néven akarsz belépni, alább megteheted.",
+       "userlogin-reauth": "Újra be kell jelentkezned, hogy igazold, te vagy $1.",
        "userlogin-createanother": "Másik felhasználói fiók létrehozása",
        "createacct-emailrequired": "E-mail cím",
        "createacct-emailoptional": "E-mail cím (opcionális)",
        "createacct-reason-ph": "Miért hozol létre egy másik fiókot",
        "createacct-submit": "Felhasználói fiók létrehozása",
        "createacct-another-submit": "Fiók létrehozása",
+       "createacct-continue-submit": "Fiók létrehozásának folytatása",
+       "createacct-another-continue-submit": "Fiók létrehozásának folytatása",
        "createacct-benefit-heading": "A(z) {{SITENAME}}-t hozzád hasonló emberek készítik.",
        "createacct-benefit-body1": "{{PLURAL:$1|szerkesztés|szerkesztés}}",
        "createacct-benefit-body2": "{{PLURAL:$1|lap|lap}}",
        "nocookiesnew": "A felhasználói fiókod létrejött, de nem vagy bejelentkezve. A wiki sütiket („cookie”) használ a szerkesztők azonosítására. Nálad ezek le vannak tiltva. Kérlek, engedélyezd őket a böngésződben, majd lépj be az új azonosítóddal és jelszavaddal.",
        "nocookieslogin": "A wiki sütiket („cookie”) használ a szerkesztők azonosításhoz.\nNálad ezek le vannak tiltva.\nEngedélyezd őket a böngésződben, majd próbáld újra.",
        "nocookiesfornew": "A felhasználói fiók nem lett létrehozva, mivel nem sikerült megerősítenünk a forrását.\nEllenőrizd, hogy a sütik engedélyezve vannak-e, majd frissítsd az oldalt, és próbálkozz újra.",
+       "createacct-loginerror": "A fiók sikeresen létrejött, de nem tudtál automatikusan bejelentkezni. Kérjük, [[Special:UserLogin|jelentkezz be manuálisan]]!",
        "noname": "Érvénytelen szerkesztőnevet adtál meg.",
        "loginsuccesstitle": "Sikeres bejelentkezés",
        "loginsuccess": "'''Sikeresen bejelentkeztél a(z) {{SITENAME}} wikibe „$1” néven.'''",
        "passwordreset-emailelement": "Felhasználónév: \n$1\n\nIdeiglenes jelszó: \n$2",
        "passwordreset-emailsentemail": "Ha ez az e-mail-cím van a fiókodhoz társítva, egy jelszó-visszaállító e-mailt küldünk.",
        "passwordreset-emailsentusername": "Ha ehhez a felhasználónévhez tartozik e-mail cím, akkor egy jelszó-visszaállító levelet küld a rendszer.",
-       "passwordreset-emailsent-capture": "Az alább látható jelszó-visszaállító e-mail lett elküldve.",
-       "passwordreset-emailerror-capture": "A jelszó-visszaállító e-mail generálása megtörtént, mint az alább látszik, de elküldése a {{GENDER:$2|szerkesztőnek}} nem sikerült: $1",
+       "passwordreset-emailsent-capture2": "A jelszóvisszaállító {{PLURAL:$1|e-mailt|e-maileket}} elküldtük. A felhasználói {{PLURAL:$1|név és a jelszó|nevek és jelszavak listája}} lentebb látható.",
        "passwordreset-invalideamil": "Érvénytelen e-mail cím",
        "changeemail": "E-mail cím megváltoztatása vagy eltávolítása",
        "changeemail-header": "Töltsd ki ezt az űrlapot az e-mail-címed megváltoztatásához. Ha nem szeretnél semmilyen e-mail-címet kapcsolni a fiókodhoz, hagyd üresen az új e-mail-cím mezőjét az űrlap elküldésekor.",
-       "changeemail-passwordrequired": "Meg kell adnod a jelszavadat ennek a változtatásnak a végrehajtásához.",
        "changeemail-no-info": "A lap közvetlen eléréséhez be kell jelentkezned.",
        "changeemail-oldemail": "Jelenlegi e-mail-cím:",
        "changeemail-newemail": "Új e-mail-cím:",
        "undo-nochange": "A szerkesztés már vissza lett állítva.",
        "undo-summary": "Visszavontam [[Special:Contributions/$2|$2]] ([[User talk:$2|vita]]) szerkesztését (oldid: $1)",
        "undo-summary-username-hidden": "A rejtett felhasználó által végzett $1 változat visszavonása",
-       "cantcreateaccounttitle": "Felhasználói fiók létrehozása sikertelen",
        "cantcreateaccount-text": "Erről az IP-címről ('''$1''') nem lehet regisztrálni, mert [[User:$3|$3]] blokkolta az alábbi indokkal:\n\n:''$2''",
        "cantcreateaccount-range-text": "A regisztrációt a(z) <strong>$1</strong> IP-címtartományban, amelybe a te IP-címed (<strong>$4</strong>) is tartozik, [[User:$3|$3]] blokkolta.",
        "viewpagelogs": "A lap a rendszernaplókban",
        "userrights-changeable-col": "Megváltoztatható csoportok",
        "userrights-unchangeable-col": "Nem megváltoztatható csoportok",
        "userrights-conflict": "Felhasználói jogok ütközése! Kérlek, végezd el újra a változtatásokat.",
-       "userrights-removed-self": "Sikeresen eltávolítottad a saját jogosultságaidat, így már nem tudod elérni ezt az oldalt.",
+       "userrights-removed-self": "Eltávolítottad a saját jogosultságaidat, így már nem tudod elérni ezt az oldalt.",
        "group": "Csoport:",
        "group-user": "szerkesztők",
        "group-autoconfirmed": "automatikusan megerősített szerkesztők",
        "right-override-export-depth": "Lapok exportálása a hivatkozott lapokkal együtt, legfeljebb 5-ös mélységig",
        "right-sendemail": "e-mail küldése más felhasználóknak",
        "right-passwordreset": "Jelszó visszaállítási emailek megtekintése",
-       "right-managechangetags": "[[Special:Tags|címkék]] létrehozása és törlése az adatbázisban",
+       "right-managechangetags": "[[Special:Tags|címkék]] létrehozása és (de)aktiválása",
        "right-applychangetags": "[[Special:Tags|címkék]] alkalmazása a változakra",
        "right-changetags": "egyedi lapváltozatokon és naplóbejegyzéseken tetszőleges [[Special:Tags|címkék]] hozzáadása és törlése",
        "right-deletechangetags": "[[Special:Tags|Címkék]] törlése az adatbázisból",
        "rightslogtext": "Ez a rendszernapló a felhasználó jogosultságok változásait mutatja.",
        "action-read": "lap olvasása",
        "action-edit": "lap szerkesztése",
-       "action-createpage": "új lap készítése",
-       "action-createtalk": "vitalap készítése",
+       "action-createpage": "ennek a lapnak a létrehozása",
+       "action-createtalk": "vitalap létrehozása",
        "action-createaccount": "felhasználói fiók elkészítése",
        "action-history": "laptörténet megtekintése",
        "action-minoredit": "szerkesztés aprónak jelölése",
        "action-viewmyprivateinfo": "személyes adatok megtekintése",
        "action-editmyprivateinfo": "személyes adatok szerkesztése",
        "action-editcontentmodel": "a lap tartalom modelljének szerkesztése",
-       "action-managechangetags": "adatbázis címkék létrehozása és törlése",
+       "action-managechangetags": "adatbáziscímkék létrehozása és (de)aktiválása",
        "action-applychangetags": "változtatások címkézése",
        "action-changetags": "egyedi változtatások és napló bejegyzések tetszőleges címkével való ellátása és törlése",
        "action-deletechangetags": "címkék törlése az adatbáziból",
+       "action-purge": "oldal gyorsítótárának ürítése",
        "nchanges": "$1 változtatás",
        "enhancedrc-since-last-visit": "$1 az utolsó látogatás óta",
        "enhancedrc-history": "történet",
        "recentchanges-page-added-to-category": "[[:$1]] hozzáadva a kategóriához",
        "recentchanges-page-added-to-category-bundled": "[[:$1]] hozzáadva a kategóriához, [[Special:WhatLinksHere/$1|ez a lap be van illesztve más lapokra]]",
        "recentchanges-page-removed-from-category": "[[:$1]] eltávolítva a kategóriából",
-       "recentchanges-page-removed-from-category-bundled": "[[:$1]] és {{PLURAL:$2|egy oldal|$2 oldal}} eltávolítva a kategóriából",
+       "recentchanges-page-removed-from-category-bundled": "[[:$1]] eltávolítva a kategóriából, [[Special:WhatLinksHere/$1|ez a lap be van illesztve más lapokra]]",
        "upload": "Fájl feltöltése",
        "uploadbtn": "Fájl feltöltése",
        "reuploaddesc": "Visszatérés a feltöltési űrlaphoz.",
        "uploaded-script-svg": "A feltöltött SVG fájlodban szkriptelemet találtunk: \"$1\".",
        "uploaded-hostile-svg": "Nem biztonságos CSS kódot találtunk a feltöltött SVG fájlod stíluselemei között.",
        "uploaded-event-handler-on-svg": "Az alábbi eseménykezelő-attribútum beállítása nem megengedett az SVG fájlokban: <code>$1=$2</code>.",
-       "uploaded-href-unsafe-target-svg": "Nem biztonságos célra mutató href-et találtam a feltöltött SVG fájlban: <code>&lt;$1 $2=\"$3\"&gt;</code>.",
+       "uploaded-href-unsafe-target-svg": "Nem biztonságos adatra mutató href-et találtunk a feltöltött SVG-fájlban: URI-cél <code>&lt;$1 $2=\"$3\"&gt;</code>.",
        "uploaded-animate-svg": "A feltöltött SVG fájlban \"animate\" taget találtam, ami az alábbi \"from\" attribútumával megváltoztathat egy href-et: <code>&lt;$1 $2=\"$3\"&gt;</code>.",
        "uploaded-setting-handler-svg": "Az SVG kódok, amelyek a \"handler\" attribútumot távolra/adatra/szkriptre állítják, le vannak tiltva. A feltöltött SVG fájlban a következőt találtam: <code>$1=\"$2\"</code>.",
        "uploaded-remote-url-svg": "Az SVG kódok, amelyek bármely stílus-attribútumot távoli URL-ra állítják, le vannak tiltva. A feltöltött SVG fájlban a következőt találtam: <code>$1=\"$2\"</code>.",
index 761b3cf..591cfa5 100644 (file)
        "passwordreset-emailelement": "Nomine de usator: \n$1\n\nContrasigno temporari: \n$2",
        "passwordreset-emailsentemail": "Si iste adresse es associate a tu conto, alora un e-mail pro reinitialisar le contrasigno essera inviate.",
        "passwordreset-emailsentusername": "Si il ha un adresse de e-mail associate a iste conto, alora un e-mail pro reinitialisar le contrasigno essera inviate.",
-       "passwordreset-emailsent-capture": "Un message de e-mail pro le reinitialisation del contrasigno ha essite inviate; iste message es monstrate hic infra.",
-       "passwordreset-emailerror-capture": "Un e-mail pro le reinitialisation del contrasigno ha essite generate; iste message es monstrate hic infra, ma le invio al {{GENDER:$2|usator}} ha fallite: $1",
        "passwordreset-emailsent-capture2": "Le {{PLURAL:$1|message|messages}} de e-mail pro reinitialisation de contrasigno ha essite inviate. Le {{PLURAL:$1|nomine de usator e contrasigno|lista de nomines de usator e contrasignos}} appare hic infra.",
        "passwordreset-emailerror-capture2": "Le invio de e-mail al {{GENDER:$2|usator}} ha fallite: $1 Le {{PLURAL:$3|nomine de usator e contrasigno|lista de nomines de usator e contrasignos}} appare hic infra.",
        "passwordreset-nocaller": "Un appellator debe esser fornite",
        "passwordreset-nodata": "Ni un nomine de usator ni un adresse de e-mail ha essite fornite",
        "changeemail": "Cambiar o remover adresse de e-mail",
        "changeemail-header": "Completa iste formulario pro cambiar tu adresse de e-mail. Si tu vole remover le association de omne adresse de e-mail ab tu conto, lassa le campo pro le nove adresse de e-mail vacue quando tu submitte le formulario.",
-       "changeemail-passwordrequired": "Essera necessari entrar tu contrasigno pro confirmar iste cambiamento.",
        "changeemail-no-info": "Tu debe aperir un session pro poter acceder directemente a iste pagina.",
        "changeemail-oldemail": "Adresse de e-mail actual:",
        "changeemail-newemail": "Adresse de e-mail nove:",
        "undo-nochange": "Pare que iste modification ha jam essite disfacite.",
        "undo-summary": "Annullava le version $1 per [[Special:Contributions/$2|$2]] ([[User talk:$2|Discussion]] | [[Special:Contributions/$2|{{MediaWiki:Contribslink}}]])",
        "undo-summary-username-hidden": "Disfacer le revision $1 facite per un usator celate",
-       "cantcreateaccounttitle": "Non pote crear conto",
        "cantcreateaccount-text": "Le creation de contos desde iste adresse IP ('''$1''') ha essite blocate per [[User:$3|$3]].\n\nLe motivo que $3 dava es ''$2''",
        "cantcreateaccount-range-text": "Le creation de contos ab le adresses IP in le intervallo <strong>$1</strong>, le qual include tu adresse IP (<strong>$4</strong>), ha essite blocate per [[User:$3|$3]].\n\nLe motivo fornite per $3 es <em>$2</em>",
        "viewpagelogs": "Vider le entratas del registro pro iste pagina",
index b585c93..8d570ec 100644 (file)
        "passwordreset-emailelement": "Nagan ti agar-aramat: \n$1\n\nTemporario a kontrasenias: \n$2",
        "passwordreset-emailsentemail": "No daytoy nga adres ti esurat ket mainaig iti pakabilangam, maipatulodto ti maysa nga esurat iti panangisaad manen ti kontrasenias.",
        "passwordreset-emailsentusername": "No adda adres ti esurat a mainaig iti daytoy a nagan ti agar-aramat, addanto maipatulod nga esurat iti panangisaad manen ti kontrasenia.",
-       "passwordreset-emailsent-capture": "Ti maysa nga esurat ti panangisaad manen ti kontrasenias ket naipatuloden, a naipakita dita baba.",
-       "passwordreset-emailerror-capture": "Naaramid ti maysa nga esurat a panangisaad manen ti kontrasenias, a napaikita dita baba, ngem ti panangitulod kenni {{GENDER:$2|agar-aramat}} ket napaay: $1",
        "changeemail": "Sukatan wenno ikkaten ti adres ti esurat",
        "changeemail-header": "Kompletuen daytoy a porma tapno masukatan ti adres ti esuratmo. No kayatmo a maikkat ti pannakainaig iti ania man nga adres ti esurat manipud iti pakabilangam, ibati a blanko ti baro nga adres ti esurat no ited ti porma.",
-       "changeemail-passwordrequired": "Masapulmonto nga ikabil ti kontraseniasmo tapno mapasingkedan daytoy a panagbaliw.",
        "changeemail-no-info": "Masapul a nakastrekka tapno dagus a makapan iti ditoy a panid.",
        "changeemail-oldemail": "Agdama nga esurat a pagtaengan:",
        "changeemail-newemail": "Baro nga esurat a pagtaengan:",
        "undo-nochange": "Ti inurnos ket kasla naibabawin.",
        "undo-summary": "Ibabawi ti $1 a binaliwan babaen ni [[Special:Contributions/$2|$2]] ([[User talk:$2|tungtungan]])",
        "undo-summary-username-hidden": "Isubli ti $1 a binaliwan babaen ti nailemmeng nga agar-aramat",
-       "cantcreateaccounttitle": "Saan a makapartuat iti pakabilangan",
        "cantcreateaccount-text": "Ti panagpartuat iti pakabilangan manipud ti daytoy nga IP a pagtaengan (<strong>$1</strong>) ket sinerraan babaen ni [[User:$3|$3]].\n\nTi inted a rason babaen ni $3 ket <em>$2</em>",
        "cantcreateaccount-range-text": "Ti panagpartuat iti pakabilangan manipud kadagiti pagtaengan ti IP iti sakop ti <strong>$1</strong>, a mairaman ti IP a pagtaengam (<strong>$4</strong>), ket sinerraan babaen ni [[User:$3|$3]].\n\nTi inted a rason babaen ni $3 ket <em>$2</em>",
        "viewpagelogs": "Kitaen dagiti listaan para iti daytoy a panid",
index 2a71972..7ce6810 100644 (file)
        "passwordreset-emailelement": "Nome utente: \n$1\n\nPassword temporanea: \n$2",
        "passwordreset-emailsentemail": "Se questo indirizzo di posta elettronica è associato con la tua utenza, allora verrà inviata una email per reimpostare la password.",
        "passwordreset-emailsentusername": "Se c'è un indirizzo di posta elettronica associato con questo nome utente, allora verrà inviata una email per reimpostare la password.",
-       "passwordreset-emailsent-capture": "È stata inviata una email di reimpostazione della password, il contenuto è riportato di seguito.",
-       "passwordreset-emailerror-capture": "È stata generata una email di reimpostazione della password, riportata di seguito. L'invio {{GENDER:$2|all'utente}} non è riuscito: $1",
        "passwordreset-emailsent-capture2": "L'email di reimpostazione della password {{PLURAL:$1|è stata inviata|sono state inviate}}. {{PLURAL:$1|Il nome|L'elenco di nomi}} utente e password è mostrato di seguito.",
        "passwordreset-emailerror-capture2": "Invio di email {{GENDER:$2|all'utente}} non riuscito: $1. {{PLURAL:$3|Il nome|L'elenco di nomi}} utente e password è mostrato di seguito.",
        "passwordreset-nocaller": "Un chiamante deve essere fornito",
        "passwordreset-nodata": "Non è stato fornito né un nome utente né un indirizzo di posta elettronica",
        "changeemail": "Modifica o rimuovi indirizzo di posta elettronica",
        "changeemail-header": "Completa questo modulo per cambiare il tuo indirizzo email. Se vuoi rimuovere l'associazione di qualsiasi indirizzo email dalla tua utenza, lascia il nuovo indirizzo email vuoto quando invii il modulo.",
-       "changeemail-passwordrequired": "Sarà necessario inserire la password per confermare la modifica.",
        "changeemail-no-info": "Devi aver effettuato l'accesso per accedere a questa pagina direttamente.",
        "changeemail-oldemail": "Indirizzo email attuale:",
        "changeemail-newemail": "Nuovo indirizzo email:",
        "undo-nochange": "Sembra che la modifica sia già stata annullata.",
        "undo-summary": "Annullata la modifica $1 di [[Special:Contributions/$2|$2]] ([[User talk:$2|discussione]])",
        "undo-summary-username-hidden": "Annullata la modifica $1 di un utente nascosto",
-       "cantcreateaccounttitle": "Impossibile registrare un utente",
        "cantcreateaccount-text": "La registrazione è stata bloccata da [[User:$3|$3]] per questo indirizzo IP ('''$1''').\n\nLa motivazione del blocco fornita da $3 è la seguente: ''$2''",
        "cantcreateaccount-range-text": "La registrazione da indirizzi IP nell'intervallo <strong>$1</strong>, che include il tuo (<strong>$4</strong>), è stata bloccata da [[User:$3|$3]].\n\nLa motivazione fornita da $3 è <em>$2</em>",
        "viewpagelogs": "Visualizza i registri relativi a questa pagina",
        "watchnologin": "Accesso non effettuato",
        "addwatch": "Aggiungi agli osservati speciali",
        "addedwatchtext": "\"[[:$1]]\" e la sua pagina di discussione sono state aggiunte alla propria [[Special:Watchlist|lista degli osservati speciali]].",
+       "addedwatchtext-talk": "\"[[:$1]]\" e la sua pagina associata sono state aggiunte alla propria [[Special:Watchlist|lista degli osservati speciali]].",
        "addedwatchtext-short": "La pagina \"$1\" è stata aggiunta alla propria lista degli osservati speciali.",
        "removewatch": "Rimuovi dagli osservati speciali",
        "removedwatchtext": "\"[[:$1]]\" e la sua pagina di discussione sono state rimosse dalla propria [[Special:Watchlist|lista degli osservati speciali]].",
+       "removedwatchtext-talk": "\"[[:$1]]\" e la sua pagina associata sono state rimosse dalla propria [[Special:Watchlist|lista degli osservati speciali]].",
        "removedwatchtext-short": "La pagina \"$1\" è stata rimossa dalla propria lista degli osservati speciali.",
        "watch": "Segui",
        "watchthispage": "Segui questa pagina",
index 6a184d7..ec7a8a3 100644 (file)
        "passwordreset-emailelement": "利用者名: \n$1\n\n仮パスワード: \n$2",
        "passwordreset-emailsentemail": "このメールアドレスがあなたのアカウントに関連付けられている場合は、パスワードリセットのメールが送信されます。",
        "passwordreset-emailsentusername": "この利用者名に関連付けられたメールアドレスがある場合は、パスワードリセットのメールが送信されます。",
-       "passwordreset-emailsent-capture": "下記の内容の、パスワード再設定メールをお送りしました。",
-       "passwordreset-emailerror-capture": "以下の内容のパスワード再設定メールを生成しましたが、{{GENDER:$2|利用者}}への送信に失敗しました: $1",
        "passwordreset-emailsent-capture2": "パスワードリセットの{{PLURAL:$1|メール}}が送信されました。{{PLURAL:$1|利用者名とパスワード|利用者名とパスワードの一覧}}は以下のとおりです。",
        "passwordreset-emailerror-capture2": "{{GENDER:$2|利用者}}へのメール送信に失敗しました: $1{{PLURAL:$3|利用者名とパスワード|利用者名とパスワードの一覧}}は以下のとおりです。",
        "passwordreset-ignored": "パスワードのリセットが処理されませんでした。プロバイダーが設定されていない可能性があります。",
        "passwordreset-invalideamil": "無効なメールアドレスです",
        "changeemail": "メールアドレスの変更または除去",
        "changeemail-header": "あなたのメールアドレスを変更するには、このフォームを完成させます。もし、あなたのアカウントから任意のメールアドレスの関連付けを削除したい場合は、フォームの送信時に、新しいメールアドレスを空白のままにします。",
-       "changeemail-passwordrequired": "この変更を確認するためにパスワードを入力する必要があります。",
        "changeemail-no-info": "このページに直接アクセスするためにはログインしている必要があります。",
        "changeemail-oldemail": "現在のメールアドレス:",
        "changeemail-newemail": "新しいメールアドレス:",
        "undo-nochange": "指定した編集は既に取り消されたようです。",
        "undo-summary": "[[Special:Contributions/$2|$2]] ([[User talk:$2|トーク]]) による版 $1 を取り消し",
        "undo-summary-username-hidden": "秘匿された利用者による版 $1 を取り消し",
-       "cantcreateaccounttitle": "アカウントを作成できません",
        "cantcreateaccount-text": "この IP アドレス (<strong>$1</strong>) からのアカウント作成は、[[User:$3|$3]] によってブロックされています。\n\n$3 が示した理由: <em>$2</em>",
        "cantcreateaccount-range-text": "この IP アドレス (<strong>$4</strong>) を含む、IP アドレス範囲 <strong>$1</strong> からのアカウント作成は、[[User:$3|$3]] によってブロックされています。\n\n$3 が示した理由: <em>$2</em>",
        "viewpagelogs": "このページの記録を閲覧",
index 516949e..f3a6409 100644 (file)
        "passwordreset-emailtext-user": "Panganggo $1 seka {{SITENAME}} njaluk ganti tembung sandhiné Sampéyan ana ing {{SITENAME}} ($4). {{PLURAL:$3|Rèkèning|Rèkèning-rèkèning}} ngisor iki magepokan karo padunungané layang èlèktronik iki:\n\n$2\n\n{{PLURAL:$3|Tembung sandhi sawetara iki}} bakal kedaluwarsa ing {{PLURAL:$5|sak dina|$5 dina}}.\nSampéyan kudu mlebu log lan milih siji tembung sandhi anyar saiki. Yèn wong liya sing njaluk iki, utawa yèn Sampéyan jebul wis kèlingan tembung sandhiné sing lawas saéngga ora ana niyat kanggo ngganti, Sampéyan bisa ngejaraké wara-wara iki lan bacutaké nganggo tembung sandhiné lawas Sampéyan.",
        "passwordreset-emailelement": "Jeneng panganggo: \n$1\n\nTembung wadi sauntara: \n$2",
        "passwordreset-emailsentemail": "Yèn layang èlèktronik iki nggayut akuning sampéyan, layang kanggo salin tembung wadi bakal dikirim.",
-       "passwordreset-emailsent-capture": "Layang èlèktronik kanggo mbalèkaké tembung sandhi wis dikirim, bisa didelok ngisor iki.",
-       "passwordreset-emailerror-capture": "Layang èlèktronik pangèling tembung sandhi wis digawe, yaiku sing ditampilaké nèng ngisor iki, nanging ora kasil dikirim ing {{GENDER:$2|panganggo}}: $1",
        "changeemail": "Owah utawa busak alamat layang èlèktronik",
        "changeemail-header": "Ganti alamat layang èlèktronik akun",
        "changeemail-no-info": "Sampéyan kudu mlebu log kanggo ngaksès kaca iki langsung.",
        "minoredit": "Iki besutan cilik",
        "watchthis": "Awasi kaca iki",
        "savearticle": "Simpen kaca",
+       "publishpage": "Babar kaca",
+       "publishchanges": "Babar owahan",
        "preview": "Pratuduh",
        "showpreview": "Deleng pratuduh",
        "showdiff": "Tuduhaké owahan",
        "undo-norev": "Besutan iki ora bisa diwurungaké amarga wis ora ana utawa wis dibusak.",
        "undo-summary": "Mbalèkaké owahan $1 déning [[Special:Contributions/$2|$2]] ([[User talk:$2|rembugan]])",
        "undo-summary-username-hidden": "Batalna revisi $1 saking panganggo kang didhelikake",
-       "cantcreateaccounttitle": "Akun ora bisa digawé",
        "cantcreateaccount-text": "Saka alamat IP iki ('''$1''') ora diparengaké nggawé akun utawa rékening. Sing mblokir utawa ora marengaké iku [[User:$3|$3]].\n\nAlesané miturut $3 yaiku ''$2''",
        "cantcreateaccount-range-text": "Nggawe akun saking alamat IP \"$1\", sing termasuk IP sampeyan (<strong>$4</strong>), sampun diblokir kaliyan [[User:$3|$3]].\n\nAlesan pamblokiran yaiku \"$2\"",
        "viewpagelogs": "Deleng cathetaning kaca iki",
index d80554d..c634c56 100644 (file)
        "passwordreset-emailtext-user": "$1 есімді қатысушы {{SITENAME}} сайтында ($4) құпия сөзді өзгертуге өтініш білдірді. Мына қатысушы {{PLURAL:$3|аккаунт|аккаунттар}} осы електронды почта қатысты:\n\n$2\n\n{{PLURAL:$3|Бұл уақытша құпия сөз|Бұл уақытша құпия сөздер}} {{PLURAL:$5|бір күнде|$5 күнде}}уақыты аяқталады.\nСіз кіруіңіз және жаңа құпия сөзді таңдауыңыз керек. Егер бұл өтінішті басқа біреу жасаса, немесе сіз  бұрынғы құпия сөзіңізді еске түсірсеңіз, және құпия сөзді ауыстыруды қаламасаңыз, сіз бұл хабарламаны ескермей және бұрыңғы құпия сөзді қолдана беруіңізге болады.",
        "passwordreset-emailelement": "Қатысушы есімі: \n$1\n\nУақытша құпия сөз: \n$2",
        "passwordreset-emailsentemail": "Бұл email мекенжайы тіркелгіңізге байланысқан, сол себепті құпия сөзді өзгерту электронды пошта арқылы жөнелтіледі.",
-       "passwordreset-emailsent-capture": "Құпия сөзді өзгерту электронды пошта арқылы жөнелтілді, ол төменде көрсетілген.",
-       "passwordreset-emailerror-capture": "Құпиясөзді өзгерту электрон хаты жасалды, ол төменде көрсетілген, бірақ ол {{GENDER:$2|қатысушыға}} жөнелтілмеді: $1",
        "changeemail": "Е-пошта мекенжайын өзгерту немесе аластау",
        "changeemail-header": "Е-пошта мекен-жайының өзгертілуі",
        "changeemail-no-info": "Бұл бетке тікелей ену үшін жүйеге кіруіңіз керек.",
        "minoredit": "Бұл шағын өңдеме",
        "watchthis": "Бұл бетті бақылау",
        "savearticle": "Бетті сақтау",
+       "savechanges": "Өзгерістерді сақтау",
+       "publishpage": "Бетті жариялау",
+       "publishchanges": "Өзгерістерді жариялау",
        "preview": "Қарап шығу",
        "showpreview": "Алдын-ала қарау",
        "showdiff": "Өзгерістерді көрсет",
        "undo-nochange": "Өңдеме әлдеқашан жоққа шығарылғаны анықталды.",
        "undo-summary": "[[Special:Contributions/$2|$2]] ([[User talk:$2|т]]) істеген нөмір $1 нұсқасын жоққа шығарды",
        "undo-summary-username-hidden": "$1 нұсқасын жасырылған қатысушы жоққа шығарды",
-       "cantcreateaccounttitle": "Тіркелгі жасалмады",
        "cantcreateaccount-text": "Бұл IP мекенжайдан (<strong>$1</strong>) жаңа тіркелгі жасауын [[User:$3|$3]] бұғаттаған.\n\n$3 есімді қатысушының келтіріген себебі: <em>$2</em>",
        "cantcreateaccount-range-text": "<strong>$1</strong> ауқымындағы IP мекенжайдан сіздің IP мекенжайыңыз да кіреді (<strong>$4</strong>) жаңа тіркелгі жасауын [[User:$3|$3]] бұғаттаған.\n\n$3 есімді қатысушының келтіріген себебі: ''$2'",
        "viewpagelogs": "Бұл беттің журнал оқиғаларын қарау",
        "tooltip-ca-nstab-category": "Санат бетін қарау",
        "tooltip-minoredit": "Бұны шағын өңдеме деп белгілеу",
        "tooltip-save": "Жасаған өзгерістеріңізді сақтау",
+       "tooltip-publish": "Өзгерістеріңізді жариялаңыз",
        "tooltip-preview": "Сақтаудың алдынан жасаған өзгерістеріңізді қарап шығыңыз!",
        "tooltip-diff": "Мәтінге қандай өзгерістерді жасағаныңызды қарау.",
        "tooltip-compareselectedversions": "Беттің екі бөлектенген нұсқасы айырмасын қарау.",
        "mw-widgets-dateinput-placeholder-day": "ЖЖЖЖ-АА-КК",
        "mw-widgets-dateinput-placeholder-month": "ЖЖЖЖ-АА",
        "mw-widgets-titleinput-description-new-page": "бет жоқ екен",
-       "mw-widgets-titleinput-description-redirect": "$1 дегенге бағыттату",
-       "api-error-blacklisted": "Өтініш, сипаттама атауының басқасын таңдаңыз."
+       "mw-widgets-titleinput-description-redirect": "$1 дегенге бағыттату"
 }
index 7480241..5d2c25c 100644 (file)
        "jumpto": "ಇಲ್ಲಿಗೆ ಹೋಗು:",
        "jumptonavigation": "ಸಂಚರಣೆ",
        "jumptosearch": "ಹುಡುಕು",
-       "view-pool-error": "$1",
+       "view-pool-error": "ಕ್ಷಮಿಸಿ, ಸದ್ಯಕ್ಕೆ ಸರ್ವರ್‌ಗಳ ಮೇಲೆ ಹೆಚ್ಚಿನ ಹೊರೆ ಇದೆ.\nಬಹಳಷ್ಟು ಬಳಕೆದಾರರು ಈ ಸಂಪನ್ಮೂಲವನ್ನು ನೋಡಲು ಪ್ರಯತ್ನಿಸುತ್ತಿದ್ದಾರೆ.\nನೀವು ಈ ಸಂಪನ್ಮೂಲವನ್ನು ಇನ್ನೊಮ್ಮೆ ನೋಡಲು ಪ್ರಯತ್ನಿಸುವ ಮೊದಲು ಸ್ವಲ್ಪಹೊತ್ತು ಕಾಯಿರಿ.\n\n$1",
        "generic-pool-error": "ಕ್ಷಮಿಸಿ, ಸದ್ಯಕ್ಕೆ ಸರ್ವರ್‌ಗಳ ಮೇಲೆ ಹೆಚ್ಚಿನ ಹೊರೆ ಇದೆ.\nಬಹಳಷ್ಟು ಬಳಕೆದಾರರು ಈ ಸಂಪನ್ಮೂಲವನ್ನು ನೋಡಲು ಪ್ರಯತ್ನಿಸುತ್ತಿದ್ದಾರೆ.\nನೀವು ಈ ಸಂಪನ್ಮೂಲವನ್ನು ಇನ್ನೊಮ್ಮೆ ನೋಡಲು ಪ್ರಯತ್ನಿಸುವ ಮೊದಲು ಸ್ವಲ್ಪಹೊತ್ತು ಕಾಯಿರಿ.",
        "pool-timeout": "ಕಾಲಾವಕಾಶ ಲಾಕ್ ಕಾಯುವುದು",
        "pool-queuefull": "ಪ್ರಕ್ರಿಯೆಯನ್ನು ವಿಶೇಷ ಕ್ಯು ಪೂರ್ಣ",
        "passwordreset-domain": "ಕ್ಷೇತ್ರ:",
        "passwordreset-email": "ಇ-ಮೇಲ್ ವಿಳಾಸ:",
        "passwordreset-emailsentemail": "ಪ್ರವೇಶಪದವನ್ನು ಪುನಃಸ್ಥಾಪಿಸಿದ ಮಿಂಚಂಚೆಯನ್ನು ಕಳುಹಿಸಲಾಗಿದೆ.",
-       "passwordreset-emailsent-capture": "ಪ್ರವೇಶಪದವನ್ನು ಪುನಃಸ್ಥಾಪಿಸಿದ ಮಿಂಚಂಚೆಯನ್ನು ಕಳುಹಿಸಲಾಗಿದೆ,ಇದನ್ನು ಈ ಕೆಳಗೆ ತೋರಿಸಲಾಗಿದೆ.",
        "changeemail": "ಮಿಂಚಂಚೆ ವಿಳಾಸವನ್ನು ಬದಲಾಯಿಸಿ",
        "changeemail-no-info": "ನೀವು ಈ ಪುಟವನ್ನು ನೇರತಲುಪಲು ಲಾಗಿನ್ ಆಗಿರುವುದು ಆವಶ್ಯಕ.",
        "changeemail-oldemail": "ಪ್ರಸ್ತುತ ಮಿಂಚಂಚೆ ವಿಳಾಸ:",
        "undo-success": "ಸಂಪಾದನೆಯನ್ನು ವಜಾ ಮಾಡಬಹುದು. ದಯವಿಟ್ಟು ಕೆಳಗಿರುವ ತುಲನೆಯನ್ನು ಪರೀಕ್ಷಿಸಿ ನೀವು ಮಾಡಲು ಇಚ್ಚಿಸಿರುವುದನ್ನು ಖಾತ್ರಿ ಮಾಡಿಕೊಂಡು ವಜಾಗೊಳಿಸುವ ಕ್ರಿಯೆಯನ್ನು \nಪೂರ್ಣಗೊಳಿಸಲು ಬದಲಾವಣೆಗಳನ್ನು ಉಳಿಸಿ.",
        "undo-norev": "ಸಂಪಾದನೆಯನ್ನು ವಜಾಗೊಳಿಸಲು ಸಾದ್ಯವಿಲ್ಲ ಏಕೆಂದರೆ ಒಂದೊ ಇದು ಅಸ್ತಿತ್ವದಲ್ಲಿ ಇಲ್ಲ ಅಧವಾ ಇದು ಅಳಿಸಲ್ಪಟ್ಟಿದೆ",
        "undo-summary": "[[Special:Contributions/$2|$2]] ([[User talk:$2|talk]]) ರ $1 ಪರಿಷ್ಕರಣೆಯನ್ನು ವಜಾ ಮಾಡಿ",
-       "cantcreateaccounttitle": "ಖಾತೆಯನ್ನು ಸೃಷ್ಟಿಸಲಾಗುತ್ತಿಲ್ಲ",
        "viewpagelogs": "ಈ ಪುಟಗಳ ದಾಖಲೆಗಳನ್ನು ವೀಕ್ಷಿಸಿ",
        "nohistory": "ಈ ಪುಟಕ್ಕೆ ಬದಲಾವಣೆಗಳ ಇತಿಹಾಸ ಇಲ್ಲ.",
        "currentrev": "ಈಗಿನ ತಿದ್ದುಪಡಿ",
index f548224..b18dd80 100644 (file)
        "passwordreset-emailelement": "사용자 이름: \n$1\n\n임시 비밀번호: \n$2",
        "passwordreset-emailsentemail": "당신의 계정과 연결된 이메일 주소가 있다면, 비밀번호 재설정 메일이 전해질 것입니다.",
        "passwordreset-emailsentusername": "이 사용자 이름과 연결된 이메일 주소가 있다면 비밀번호 초기화 이메일이 전송됩니다.",
-       "passwordreset-emailsent-capture": "비밀번호 재설정 이메일이 발송되었으며, 아래에 나타나 있습니다.",
-       "passwordreset-emailerror-capture": "비밀번호 재설정 이메일이 생성되어 아래에 나타나 있지만, {{GENDER:$2|사용자}}에게 발송하는 데에는 실패했습니다: $1",
        "passwordreset-emailsent-capture2": "비밀번호 재설정 이메일을 보냈습니다. {{PLURAL:$1|사용자 이름과 비밀번호는|사용자 이름과 비밀번호의 목록은}} 아래에 나타납니다.",
        "passwordreset-emailerror-capture2": "{{GENDER:$2|사용자}} 이메일 보내기 실패: $1 {{PLURAL:$3|사용자 이름과 비밀번호가|사용자 이름과 비밀번호의 목록이}} 아래에 나타납니다.",
        "passwordreset-nocaller": "호출자를 지정해야 합니다",
        "passwordreset-nodata": "사용자 이름이나 이메일 주소가 지정되지 않았습니다",
        "changeemail": "이메일 주소를 바꾸거나 제거하기",
        "changeemail-header": "이메일 주소를 바꾸려면 이 양식을 채우세요. 계정에서 이메일 연동을 취소하고 싶다면 양식을 제출할 때 새 이메일 주소를 공란으로 두세요.",
-       "changeemail-passwordrequired": "변경을 적용하려면 비밀번호를 입력해야 합니다.",
        "changeemail-no-info": "이 페이지에 직접 접근하려면 로그인해야 합니다.",
        "changeemail-oldemail": "현재 이메일 주소:",
        "changeemail-newemail": "새 이메일 주소:",
        "undo-nochange": "편집이 이미 되돌려진 것으로 나타납니다.",
        "undo-summary": "[[Special:Contributions/$2|$2]] ([[User talk:$2|토론]])의 $1판 편집을 되돌림",
        "undo-summary-username-hidden": "숨겨진 사용자가 $1 판을 되돌림",
-       "cantcreateaccounttitle": "계정을 만들 수 없습니다",
        "cantcreateaccount-text": "현재 IP 주소('''$1''')는 [[User:$3|$3]] 사용자에 의해 계정 만들기가 차단되었습니다.\n\n차단 이유는 다음과 같습니다: $2",
        "cantcreateaccount-range-text": "당신의 IP 주소(<strong>$4</strong>)가 속해 있는 <strong>$1</strong> 대역에서의 계정 만들기를 [[User:$3|$3]]님이 차단했습니다.\n\n$3님이 제시한 이유는 \"$2\"입니다.",
        "viewpagelogs": "이 문서의 기록 보기",
index 139dabe..3586530 100644 (file)
        "passwordreset-emailelement": "Metmaacher Name: \n$1\n\nEijmohl-Paßwoot: \n$2",
        "passwordreset-emailsentemail": "Wann dat en <i lang=\"en\" xml:lang=\"en\" dir=\"ltr\" title=\"„de eläktrohnesche Poß“\">e-mail</i>-Adräß vun Der es, dann weed en <i lang=\"en\" xml:lang=\"en\" dir=\"ltr\" title=\"„de eläktrohnesche Poß“\">e-mail</i> för Dinge Zohjang verschek, öm e neu Paßwoot ze krijje.",
        "passwordreset-emailsentusername": "Wann heh dä Metmaacher en <i lang=\"en\" xml:lang=\"en\" dir=\"ltr\" title=\"„de eläktrohnesche Poß“\">e-mail</i>-Adräß hät, dann weed en <i lang=\"en\" xml:lang=\"en\" dir=\"ltr\" title=\"„de eläktrohnesche Poß“\">e-mail</i> verschek, öm e neu Paßwoot ze krijje.",
-       "passwordreset-emailsent-capture": "En <i lang=\"en\" xml:lang=\"en\" dir=\"ltr\" title=\"„de eläktrohnesche Poß“\">e-mail</i> met Aanjahbe zom neue Paßwoot för der Zohjang heh es verschek woode. Heh dronger kanns De se lässe.",
-       "passwordreset-emailerror-capture": "En <i lang=\"en\" xml:lang=\"en\" dir=\"ltr\" title=\"„de eläktrohnesche Poß“\">e-mail</i> met Aanjahbe zom neue Paßwoot för der Zohjang heh sullt verschek wääde, ävver dat Verscheke aan {{GENDER:$2|dä|dat|dä Metmaacher|de|dat}} $2 hät nit jeflup: $1",
        "passwordreset-emailsent-capture2": "{{PLURAL:$1|En <i lang=\"en\" xml:lang=\"en\" dir=\"ltr\" title=\"„de eläktrohnesche Poß“\">e-mail</i> es|De <i lang=\"en\" xml:lang=\"en\" dir=\"ltr\" title=\"„de eläktrohnesche Poß“\">e-mail</i>s sin|Nix es}} verschek woode, öm e neu Paßwoot ze krijje. {{PLURAL:$1|Dä Nahme vum Metmaacher un dat Paßwood|Di Leß met dä Nahme un Paßwööter|Nix weed}} heh noh aanjezeijsch.",
        "passwordreset-emailerror-capture2": "{{GENDER:$2|Däm|Däm|Däm Metmaacher|Dä|Däm}} $1 en <i lang=\"en\" xml:lang=\"en\" dir=\"ltr\" title=\"„de eläktrohnesche Poß“\">e-mail</i> ze scheke hät nit jeflupp: {{PLURAL:$3|Dä Nahme vum Metmaacher un dat Paßwood|Di Leß met dä Nahme un Paßwööter|Nix weed}} heh noh aanjezeijsch.",
        "passwordreset-nocaller": "Entärne Fähler: Ene Oprohfer moß aanjejovve sin.",
        "passwordreset-nodata": "Keine Metmaacher_Nahme un kein Adräß för de <i lang=\"en\" xml:lang=\"en\" dir=\"ltr\" title=\"„de eläktrohnesche Poß“\">e-mail</i> es aanjejovve woode.",
        "changeemail": "Donn en Adräß för de <i lang=\"en\">e-mail</i> ändere udder fott schmiiße",
        "changeemail-header": "Donn heh dat Fommulaa ußfölle, öm Ding Adräß för de <i lang=\"en\" xml:lang=\"en\" dir=\"ltr\" title=\"„de eläktrohnesche Poß“\">e-mail</i> ze ändere. Wann De en Adräß loß wähde wells, maach dat Fäld läddesch, ih dat De dat Fommolaa loß scheks.",
-       "changeemail-passwordrequired": "Do moß Ding Paßwood enjävve, öm di Änderong ze beschtähteje.",
        "changeemail-no-info": "Do mööts ald enjelogg sin, öm tiräk op di Sigg jonn ze dörve",
        "changeemail-oldemail": "Ding Address för de <i lang=\"en\">e-mail</i> es jäz:",
        "changeemail-newemail": "Ding neue Address för de <i lang=\"en\">e-mail</i> sull wääde:",
        "undo-nochange": "Di Änderong schingk ald retuur jemaat woode ze sin.",
        "undo-summary": "Di Änderong $1 wood {{GENDER:$2|vum|vum|vumm Metmaacher|vun dä|vum}} [[Special:Contributions/$2|$2]] ([[User talk:$2|Klaaf]]) zeröck jenomme.",
        "undo-summary-username-hidden": "Nemm di Väsjohn $1 vun enem verschtoche Metmaacher widder retuhr.",
-       "cantcreateaccounttitle": "Kann keine Zojang enrichte",
        "cantcreateaccount-text": "Dä [[User:$3|$3]] hät verbodde, dat mer sich vun dä IP-Adress '''$1''' uß als ene neue Metmaacher aanmelde könne soll.\n\nAls Jrund för et Sperre es enjedraare: ''$2''",
        "cantcreateaccount-range-text": "Ne neue Metmaacher aanmälde vun <i lang=\"en\" xml:lang=\"en\" dir=\"ltr\" title=\"Internet Protocol\">IP</i>-Adräße em Berett vun <strong>$1</strong>, woh de Dinge dren es, wood vum {{GENDER:$3|vum|vum|vumm Metmaacher|vun dä|vum}} [[User:$3|$3]] verbodde.\nDer Jrond: <em><$2</em>\n\nDing <i lang=\"en\" xml:lang=\"en\" dir=\"ltr\" title=\"Internet Protocol\">IP</i>-Adräß es: <strong>$4</strong>",
        "viewpagelogs": "De Logböcher för heh di Sigg beloore",
index 9479f3c..52a727a 100644 (file)
        "parser-template-loop-warning": "Ansa formulae detecta: [[$1]]",
        "undo-norev": "Recensio abrogari non potuit quia non est aut deleta est.",
        "undo-summary": "Abrogans recensionem $1 ab usore [[Special:Contributions/$2|$2]] ([[User talk:$2|Disputatio]])",
-       "cantcreateaccounttitle": "Non licuit nomen tibi imponere",
        "cantcreateaccount-text": "Ex hoc loco IP ('''$1''') nomen sibi imponere ab usore [[User:$3|$3]] interdicitur.\nQui hanc causam dedit: ''$2''",
        "viewpagelogs": "Vide acta huius paginae",
        "nohistory": "Huic paginae non est historia.",
index bff977d..39aa238 100644 (file)
        "passwordreset-emailelement": "Benotzernumm: \n$1\n\nTemporärt Passwuert: \n$2",
        "passwordreset-emailsentemail": "Wann dës E-Mailadress mat Ärem Benotzerkont assoziéiert ass, da gëtt Eng E-Mail fir d'Passwuert zréckzesetze geschéckt.",
        "passwordreset-emailsentusername": "Wann eng E-Mailadress mat dësem Benotzernumm associéiert ass, da gëtt Eng E-Mail fir d'Passwuert zeréckzesetze geschéckt.",
-       "passwordreset-emailsent-capture": "Eng Mail fir d'Passwuert zréckzesetze gouf geschéckt, Dir gesitt se hei drënner.",
-       "passwordreset-emailerror-capture": "Eng Mail fir d'Passwuert zréckzesetze gouf geschéckt, Dir gesitt se hei drënner, awer de {{GENDER:$2|Benotzer}} konnt se net kréien: $1",
        "passwordreset-invalideamil": "Net-valabel E-Mail-Adress",
        "passwordreset-nodata": "Et gouf weder e Benotzernumm nach e Passwuert uginn",
        "changeemail": "E-Mail-Adress änneren oder ewechhuelen",
        "changeemail-header": "Fëllt dëse Formulaire aus fir Är E-Mailadress z'änneren.  Wann Dir d'Verbindung tëscht Ärer E-Mailadress an Ärem Benotzerkont ewechhuele wëllt, da loosst d'Feld e-Mailadress eidel wann Dir de Formulaire späichert.",
-       "changeemail-passwordrequired": "Dir musst Äert Passwuert agi fir dës Ännerung ze konfirméieren.",
        "changeemail-no-info": "Dir musst ageloggt sinn, fir direkt op dës Säit ze kommen.",
        "changeemail-oldemail": "Aktuell Mailadress:",
        "changeemail-newemail": "Nei Mailadress:",
        "undo-nochange": "D'Ännerung gouf anscheinend schonn zeréckgesat.",
        "undo-summary": "Ännerung $1 vu(n) [[Special:Contributions/$2|$2]] ([[User talk:$2|Diskussioun]] | [[Special:Contributions/$2|{{MediaWiki:Contribslink}}]]) annulléieren.",
        "undo-summary-username-hidden": "Versioun $1 vun engem verstoppte Benotzer zrécksetzen",
-       "cantcreateaccounttitle": "Benotzerkont konnt net opgemaach ginn",
        "cantcreateaccount-text": "D'Opmaache vu Benotzerkonten vun dëser IP Adress ('''$1''') gouf vum [[User:$3|$3]] gespaart.\n\nDe Benotzer $3 huet \"$2\" als Grond uginn.",
        "cantcreateaccount-range-text": "D'Uleeë vu Benotzerkonte vun IP-Adressen aus dem Beräich \"$1\", zu deem Är IP-Adress (<strong>$4</strong>) gehéiert, gouf vum [[User:$3|$3]] gespaart.\n\nDe Grond den den $3 uginn huet ass <em>$2</em>",
        "viewpagelogs": "Logbicher fir dës Säit weisen",
index 5c22e14..779c36c 100644 (file)
        "tog-hidepatrolled": "Gemarkeerde wieziginge verberge in recente wieziginge",
        "tog-newpageshidepatrolled": "Gemarkeerde pagina's verberge in de lies mit nuuj pagina's",
        "tog-extendwatchlist": "Oetgebreide volglies gebroeke óm alle verangeringe te zeen en neet allein de lèste",
-       "tog-usenewrc": "Tuun verangeringe per pagina in recènte verangeringe en volglies (Javascript nudig)",
+       "tog-usenewrc": "Tuun verangeringe per pagina in recènte verangeringe en volglies",
        "tog-numberheadings": "Köpkes automatisch nummere",
-       "tog-showtoolbar": "Laot edit toolbar zeen",
-       "tog-editondblclick": "Bewirk pagina's bie 'ne dobbelklik (JavaScript)",
-       "tog-editsectiononrightclick": "Secties bewirke mit 'ne rechtermoesklik op sectietitels (JavaScript nudig)",
+       "tog-showtoolbar": "Laot bewirkingwerkbalk zeen",
+       "tog-editondblclick": "Bewirk pagina's bie 'ne dobbelklik",
+       "tog-editsectiononrightclick": "Secties bewirke mit 'ne rechtermoesklik op sectietitels",
        "tog-watchcreations": "Volg autematis pagina's die ich aanmaak en bestenj die ich upload",
        "tog-watchdefault": "Voog pagina's em bestenj die se bewirks toe aan dien volglies",
        "tog-watchmoves": "Volg autematis pagina's en bestenj die ich verplaats",
        "tog-watchdeletion": "Volg autematis pagina's en bestenj die ich ewegsjaf",
+       "tog-watchuploads": "Nuuj besjtenj die ich upload toevoge aan mienn volglies",
+       "tog-watchrollback": "Pagina's boe-in ich get höb óngedaon gemaak autematis volge",
        "tog-minordefault": "Markeer sjtanderd alle bewirkinge es klein",
        "tog-previewontop": "Veurvertuin baove bewèrkingsveld tuine",
        "tog-previewonfirst": "Preview laote zien bie de ierste bewirking",
        "tog-shownumberswatching": "'t Aantal gebroekers tuine die dees pagina volg",
        "tog-oldsig": "Bestaonde ongerteikening:",
        "tog-fancysig": "Es wikiteks behanjele (zonder autematische verwiezing)",
-       "tog-uselivepreview": "\"live veurbesjouwing\" gebroeke (vereis JavaScript - experimenteel)",
+       "tog-uselivepreview": "\"live veurbesjouwing\" gebroeke",
        "tog-forceeditsummary": "'n Melding gaeve bie 'n laeg samevatting",
        "tog-watchlisthideown": "Eige bewirkinge verberge op mien volglies",
        "tog-watchlisthidebots": "Botbewirkinge op mien volglies verberge",
        "tog-watchlisthideminor": "Klein bewirkinge op mien volglies verberge",
        "tog-watchlisthideliu": "Bewirkinge van aangemelde gebroekers op mien volglies versjtaeke",
+       "tog-watchlistreloadautomatically": "Herlaaj de volglies autematis es 'n filter is verangerd (JavaScript vereis)",
        "tog-watchlisthideanons": "Bewirkinge van anonieme gebroekers op mien volglies versjtaeke",
        "tog-watchlisthidepatrolled": "Gemarkeerde wieziginge op mien volglies verberge",
+       "tog-watchlisthidecategorization": "Verberg categorisatie  van  pagina's",
        "tog-ccmeonemails": "'n Kopie nao mich versjikke van de e-mail dae ich nao anger gebroekers sjik",
        "tog-diffonly": "Pagina-inhaud zónger verangeringe neet tuine",
        "tog-showhiddencats": "Verbórge categorië tuine",
        "tog-norollbackdiff": "Wieziginge eweglaote nao trökdrieje",
-       "tog-useeditwarning": "Waorssjoew mich es ich 'n bewerkdje pagina die nag neet is opgeslage wil verlaote",
+       "tog-useeditwarning": "Waarsjoew mich es ich 'n bewerkde pagina die nog neet is opgeslage wil verlaote",
+       "tog-prefershttps": "Ummer 'n beveiligde verbinding gebroeke es ich ingelog bin",
        "underline-always": "Altied",
        "underline-never": "Noets",
        "underline-default": "Sjtanderd van de browser",
        "oct": "okt",
        "nov": "nov",
        "dec": "dec",
+       "january-date": "$1 jannewarie",
+       "february-date": "$1 fibberwarie",
+       "march-date": "$1 miert",
+       "april-date": "$1 april",
+       "may-date": "$1 mei",
+       "june-date": "$1 juni",
+       "july-date": "$1 juli",
+       "august-date": "$1 augustus",
+       "september-date": "$1 september",
+       "october-date": "$1 oktober",
+       "november-date": "$1 november",
+       "december-date": "$1 december",
+       "period-am": "AM",
+       "period-pm": "PM",
        "pagecategories": "{{PLURAL:$1|Categorie|Categorieë}}",
        "category_header": "Artikele in categorie \"$1\"",
        "subcategories": "Subcategorieë",
        "newwindow": "(in nuuj venster)",
        "cancel": "Aafbraeke",
        "moredotdotdot": "Miè...",
+       "morenotlisted": "Deze lies is neet compleet.",
        "mypage": "Mien gebroekerspagina",
        "mytalk": "Euverlèk",
        "anontalk": "Euverlèk veur dit IP adres",
        "actions": "Hanjeling",
        "namespaces": "Naamruumdes",
        "variants": "Anger vorme",
+       "navigation-heading": "Navigatiemenu",
        "errorpagetitle": "Fout",
        "returnto": "Truuk nao $1.",
        "tagline": "Van {{SITENAME}}",
        "permalink": "Permanente link",
        "print": "Aafdrukke",
        "view": "Bekieke",
-       "edit": "Bewèrk",
+       "view-foreign": "Betrach op $1",
+       "edit": "Bewirk",
+       "edit-local": "Lokaal besjrieving bewirke",
        "create": "Aanmake",
-       "editthispage": "Pagina bewirke",
+       "create-local": "Lokaal besjrieving toeveuge",
+       "editthispage": "Dees pagina bewirke",
        "create-this-page": "Dees pagina aanmake",
        "delete": "Wisse",
        "deletethispage": "Wisse",
+       "undeletethispage": "Dees pagina trökzètte",
        "undelete_short": "$1 {{PLURAL:$1|bewirking|bewirkinge}} trökzètte",
        "viewdeleted_short": "{{PLURAL:$1|ein eweggesjafde versie|$1 eweggesjafde versies}} bekieke",
        "protect": "Besjirm",
        "otherlanguages": "Anger tale",
        "redirectedfrom": "(Doorverweze van $1)",
        "redirectpagesub": "Doorverwiespagina",
+       "redirectto": "Doorverwieze nao:",
        "lastmodifiedat": "Dees pagina is 't lèts verangerd op $2, $1.",
        "viewcount": "Dees pagina is {{PLURAL:$1|1 kier|$1 kier}} bekeke.",
        "protectedpage": "Beveiligde pagina",
        "pool-errorunknown": "Ónbekènde fout",
        "aboutsite": "Euver {{SITENAME}}",
        "aboutpage": "Project:Info",
-       "copyright": "De inhawd is besjikbaar ónger de $1.",
+       "copyright": "De inhawd is besjikbaar ónger de $1 behauve is angers aangegeve.",
        "copyrightpage": "{{ns:project}}:Auteursrechte",
        "currentevents": "In 't nuujs",
        "currentevents-url": "Project:In 't nuujs",
        "disclaimers": "Aafwiezinge aansjprakelikheid",
        "disclaimerpage": "Project:Algemein aafwiezing aansjprakelikheid",
        "edithelp": "Hulp bie bewirke",
+       "helppage-top-gethelp": "Hölp",
        "mainpage": "Veurblaad",
        "mainpage-description": "Veurblaad",
        "policy-url": "Project:Beleid",
        "hidetoc": "versjtaek",
        "collapsible-collapse": "Inklappe",
        "collapsible-expand": "Oetklappe",
+       "confirmable-confirm": "Bis {{GENDER:$1|diech}} zeker?",
+       "confirmable-yes": "Jao",
+       "confirmable-no": "Nein",
        "thisisdeleted": "$1 tuine of trökzètte?",
        "viewdeleted": "$1 tuine?",
        "restorelink": "{{PLURAL:$1|ein eweggesjafde versie|$1 eweggesjafde versies}}",
        "nstab-template": "Sjabloon",
        "nstab-help": "Hulppagina",
        "nstab-category": "Categorie",
+       "mainpage-nstab": "Veurblaad",
        "nosuchaction": "Gevraogde hanjeling besjteit neet",
        "nosuchactiontext": "De opdrach in de URL is ongeldig.\nMäögelik höbs te 'n typefout gemaak in de URL, of 'n verkierde verwiezing gevolg.\n't Kan ouch wieze op 'n fout in de software van {{SITENAME}}.",
        "nosuchspecialpage": "D'r besjteit gein speciaal pagina mit deze naam",
        "passwordreset-emailtext-user": "Gebroeker $1 op de site {{SITENAME}} haet dien gebroekersgegaeves veur {{SITENAME}} ($4) ópgevraog.\nDe volgende {{PLURAL:$3|gebroeker is|gebroekers zint}} gekoppeld aan dit e-mailadres:\n\n$2\n\n{{PLURAL:$3|Dit tiedelik wachwaord vervilt|Dees tiedelike wachweurd vervallen}} euver {{PLURAL:$5|einen daag|$5 daag}}.\nMel dich aan en veranger 't wachwaord noe. Es se dit verzeuk neet zelf hes gedaon, of es se 't oorspronkelik wachwaord nog kins en 't neet anges wils, laot dit berich den en blief dien aad wachwaord gebroeke.",
        "passwordreset-emailelement": "Gebroekersnaam: \n$1\n\nTiedelik wachwaord: \n$2",
        "passwordreset-emailsentemail": "d'r Is per mail 'n herinnering versjik.",
-       "passwordreset-emailsent-capture": "d'r Is 'ne herinneringse-mail versjik. Deze weurt hieónger getuind.",
-       "passwordreset-emailerror-capture": "d'r Is 'ne herinneringse-mail aangemaak. Deze weurt hieónger getuind. 't Verzènje nao de gebroeker is mislök óm de volgende raeje: $1",
        "changeemail": "Veranger dien e-mailadres",
        "changeemail-header": "Veranger 't e-mailadres van miene gebroekersnaam",
        "changeemail-no-info": "Doe moos aangemeld zien ierdets doe dees pagina gebroeke kens.",
        "minoredit": "Dit is 'n klein verangering",
        "watchthis": "Volg dees pagina",
        "savearticle": "Pagina opsjlaon",
+       "publishpage": "Pagina publicere",
+       "publishchanges": "Verangeringe publicere",
        "preview": "Naokieke",
        "showpreview": "Betrach dees bewirking",
        "showdiff": "Toen verangeringe",
        "token_suffix_mismatch": "'''Dien bewerking is geweigerd omdat dien client de laesteikes in 't bewerkingstoken onjuist haet behandeld. De bewerking is geweigerd om verminking van de paginateks te veurkomme. Dit gebeurt soms es d'r een webgebaseerde proxydienst wurt gebroek die foute bevat.'''",
        "edit_form_incomplete": "'''Sommige ongerdeile van 't bewerkingsformuleer höbbe de server neet bereik. Controleer of dien bewerkinge intak zien en perbeer 't obbenuits.'''",
        "editing": "Bewirkingspagina: $1",
-       "creating": "$1 aanmakendj",
+       "creating": "Aanmake van $1",
        "editingsection": "Bewirke van sectie van $1",
        "editingcomment": "Bewirke $1 (commentair)",
        "editconflict": "Bewirkingsconflik: $1",
        "undo-failure": "De verangering kòs neet ongedaon gemaak waere waeges angere striedige verangeringe.",
        "undo-norev": "De bewerking kon neet ongedaan gemaak waere, omdat die neet besteet of is verwijderd.",
        "undo-summary": "Versie $1 van [[Special:Contributions/$2|$2]] ([[User talk:$2|euverlèk]]) óngedaon gemaak.",
-       "cantcreateaccounttitle": "Aanmake gebroeker misluk.",
        "cantcreateaccount-text": "'t Aanmake van gebroekers van dit IP-adres ('''$1''') is geblokkeerd door [[User:$3|$3]].\n\nDe door $3 opgegaeve reje is ''$2''",
        "viewpagelogs": "Logbeuk veur dees pagina tuine",
        "nohistory": "Dees pagina is nog neet bewirk.",
        "special-characters-group-lao": "Lao",
        "special-characters-group-khmer": "Cambodzjaans",
        "mw-widgets-dateinput-placeholder-day": "JJJJ-MM-DD",
-       "mw-widgets-dateinput-placeholder-month": "JJJJ-MM",
-       "api-error-blacklisted": "Kees 'nen angere, besjrievendje naam."
+       "mw-widgets-dateinput-placeholder-month": "JJJJ-MM"
 }
index 041c73f..74b2357 100644 (file)
        "passwordreset-emailelement": "نام کاربری: \n$1\n\nگذرواژهٔ موقت: \n$2",
        "passwordreset-emailsentemail": "اگر نشانی پست الکترونیکی که وارد کردید برای حساب کاربریتان ثبت شده باشد، یک نامهٔ بازنشانی گذرواژه به آن فرستاده می‌شود.",
        "passwordreset-emailsentusername": "اگر نشانی پست الکترونیکی مرتبطی موجود باشد، یک نامه برای بازنشانی گذرواژه به آن ارسال خواهد شد.",
-       "passwordreset-emailsent-capture": "یک ایمیل بازنشانی که در پایین نمایش داده شده، فرستاده شده است.",
-       "passwordreset-emailerror-capture": "ایمیل بازنشانی، که در زیر نمایش داده شده، ایجاد شد، ولی ارسال آن به {{GENDER:$2|کاربر}} موفقیت‌آمیز نبود: $1",
        "changeemail": "تغییر یا حذف نشانی ایمیل",
        "changeemail-header": "برای تغییر ایمیلتان این فرم را کامل کنید. برای حذف ایملیتان کافی است بخش ایمیل را خالی رها کنید و فرم را ارسال کنید.",
-       "changeemail-passwordrequired": "برای تائید این تغییر باید گذرواژه‌تان را وارد کنید.",
        "changeemail-no-info": ".برای دسترسی مستقیم به این صفحه شما باید به سیستم وارد شده باشید",
        "changeemail-oldemail": ":نشانی ایمیل ایسة هؤمة",
        "changeemail-newemail": ":نشانی ایمیل تازة",
        "undo-nochange": "به نظر می‌رسد ویرایش از پیش واگردانی شده است.",
        "undo-summary": "خنثی‌سازی ویرایش $1 توسط [[Special:Contributions/$2|$2]] ([[User talk:$2|بحث]])",
        "undo-summary-username-hidden": "خنثی‌سازی نسخهٔ $1 به دست یک کاربر پنهان‌شده",
-       "cantcreateaccounttitle": "نمی‌توان حساب باز کرد",
        "cantcreateaccount-text": "امكان ساختن حساب کاربری از این این نشانی آی‌پی ('''$1''') توسط [[User:$3|$3]] سلب شده است.\n\nدلیل ارائه شده توسط $3 چنین است: $2",
        "cantcreateaccount-range-text": "ایجاد حساب از آدرس آی‌پی در مجموعه‌ی <strong>$1</strong>، که شامل آدرس آی‌پی شما (<strong>$4</strong>) است، توسط [[User:$3|$3]] متوقف شده‌است.\nدلیل ارائه شده توسط $3، $2 است.",
        "viewpagelogs": "نمایش سیاهه‌های این صفحه",
index 319770c..a59c30b 100644 (file)
        "passwordreset-emailelement": "Naudotojo vardas: \n$1\n\nLaikinas slaptažodis: \n$2",
        "passwordreset-emailsentemail": "Jeigu šis el. pašto adresas yra susietas su jūsų paskyra, tada slaptažodžio atkūrimo laiškas bus išsiųstas.",
        "passwordreset-emailsentusername": "Jeigu buvo el. paštas susietas su šiuo naudotojo vardu, tai slaptažodžio atkūrimo el. laiškas bus išsiųstas.",
-       "passwordreset-emailsent-capture": "Slaptažodžio priminimo laiškas bus išsiųstas, toks koks parodytas.",
-       "passwordreset-emailerror-capture": "Priminimo elektroninis laiškas buvo sukurtas, toks, koks parodytas žemiau, bet pasiuntimas naudotojui buvo nesėkmingas: $1",
        "passwordreset-emailsent-capture2": "Slaptažodžio keitimo {{PLURAL:$1|el. laiškas buvo išsiųstas|el. laiškai buvo išsiųsti}}. {{PLURAL:$1|vartotojo vardas ir slaptažodis rodomi|vartotojų vardų ir slaptažodžių sąrašas rodomas}} žemiau.",
        "passwordreset-emailerror-capture2": "El. laiško siuntimas {{GENDER:$2|vartotojui}} nepavyko: $1 {{PLURAL:$3|vartotojo vardas ir slaptažodis rodomi|vartotojų vardų ir slaptažodžių sąrašas rodomas}} žemiau.",
        "passwordreset-nocaller": "Skambinantysis turi būti nurodytas",
        "passwordreset-nodata": "Vartotojo vardas ir el. paštas buvo nepateikti",
        "changeemail": "Pakeisti ar pašalinti el. pašto adresą",
        "changeemail-header": "Užpildykite šią formą, kad pakeistumėte savo el. pašto adresą. Jeigu norite pašalinti bet kurio el. pašto adreso susiejimą su savo paskyra, palikite naujojo el. pašto adreso lauką tuščią, kai pateiksite formą.",
-       "changeemail-passwordrequired": "Jums reikės įvesti savo slaptažodį, kad patvirtintumėte šį pakeitimą.",
        "changeemail-no-info": "Jūs turite būti prisijungęs, kad pasiektumėte puslapį tiesiogiai.",
        "changeemail-oldemail": "Dabartinis el. pašto adresas:",
        "changeemail-newemail": "Naujas el. pašto adresas:",
        "undo-nochange": "Panašu, kad keitimas jau buvo atšauktas.",
        "undo-summary": "Atšauktas [[Special:Contributions/$2|$2]] ([[User talk:$2|Aptarimas]] | [[Special:Contributions/$2|{{MediaWiki:Contribslink}}]]) keitimas ($1 versija)",
        "undo-summary-username-hidden": "Atmesti versiją $1, atliktą paslėpto naudotojo",
-       "cantcreateaccounttitle": "Paskyrų kūrimas negalimas",
        "cantcreateaccount-text": "Paskyrų kūrimą iš šio IP adreso ('''$1''') užblokavo [[User:$3|$3]].\n\n$3 nurodyta priežastis yra ''$2''",
        "cantcreateaccount-range-text": "Naudotojas [[User:$3|$3]] nustatė draudimą kurti paskyras iš IP adresų plotmės <strong>$1</strong>, į kurią patenka ir jūsiškis IP adresas (<strong>$4</strong>).",
        "viewpagelogs": "Rodyti šio puslapio specialiuosius veiksmus",
index b20432e..ecd1cf0 100644 (file)
        "passwordreset-emailtitle": "Konta informācija {{SITENAME}}",
        "passwordreset-emailelement": "Lietotājvārds: \n$1\n\nPagaidu parole: \n$2",
        "passwordreset-emailsentemail": "Paroles atiestatīšanas e-pasts ir nosūtīts.",
-       "passwordreset-emailsent-capture": "Atgādinājuma e-pasta ziņojums ir nosūtīts, tas parādīts zemāk.",
-       "passwordreset-emailerror-capture": "Atgādinājuma e-pasta ziņojums tika izveidots, tas parādīts zemāk, bet nosūtīšana lietotājam neizdevās: $1",
        "passwordreset-nosuchcaller": "Izsaucējs nepastāv: $1",
        "passwordreset-invalideamil": "Nederīga e-pasta adrese",
        "changeemail": "Mainīt e-pasta adresi",
        "undo-failure": "Šo labojumu nevar atcelt, jo ir veikti nozīmīgi labojumi vēl pēc šī labojuma izdarīšanas.",
        "undo-norev": "Šo izmaiņu nevar atcelt, jo tādas nav vai tā ir izdzēsta.",
        "undo-summary": "Atcēlu [[Special:Contributions/$2|$2]] ([[User talk:$2|Diskusija]]) izdarīto izmaiņu $1",
-       "cantcreateaccounttitle": "Nevar izveidot dalībnieku",
        "cantcreateaccount-text": "[[Lietotājs:$3|$3]] ir bloķējis lietotāja izveidošanu no šīs IP adreses ('''$1''').\n\n$3 norādītais iemesls ir ''$2''",
        "viewpagelogs": "Apskatīt ar šo lapu saistītos reģistru ierakstus",
        "nohistory": "Šai lapai nav pieejama versiju hronoloģija.",
index 29737f4..e02a91c 100644 (file)
        "passwordreset-emailtext-user": "प्रयोक्ता $1 {{अन्तर्जाल}} पर अहाँक खाता विवरणक {{SITENAME}} लेल फेरसँ ($4) आग्रह केने छथि। ई प्रयोक्ता {{PLURAL:$3|खाता अछि|खाता सभ अछि}} ऐ ई-पत्र संकेतसँ जुड़ल: $2\n{{PLURAL:$3| ई अस्थायी कूटशब्द|ई सभ अस्थायी कूटशब्द}} खतम भऽ जाएत {{PLURAL:$5|एक दिन|$5 दिन}} मे।\nअहाँ सम्प्रवेश करू आ एकटा नव कूटशब्द आब चुनू। जँ कियो दोसर ई आग्रह केने छथि, वा जँ अहाँकेँ अपन मूल कूटशब्द मोन पड़ि गेल अछि, आ अहाँ आब ओइ कूटशब्दकेँ नै बदलऽ चाहै छी, अहाँ ऐ संदेशकेँ बिसरि सकै छी आ अपन पुरान कूटशब्दक प्रयोग जारी राखि सकै छी।",
        "passwordreset-emailelement": "प्रयोक्ता: \n$1\n\nअस्थायी कूटशब्द: \n$2",
        "passwordreset-emailsentemail": "एकटा ई-पत्र मोन पाड़बा लेल पठाओल गेल अछि।",
-       "passwordreset-emailsent-capture": "एकटा स्मरण ई-पत्र पठाएल गेल अछि, जे नीचाँ देखाएल अछि।",
-       "passwordreset-emailerror-capture": "एकटा स्मरण ई-पत्र बनाएल गेल अछि, जे नीचाँ देखाएल अछि, मुदा प्र्योक्ताकेँ एकरा पठेबाक प्रयास विफल भेल: $1",
        "changeemail": "ई-मेल पता परिवर्तित करी",
        "changeemail-header": "अपन ईमेल पता परिवर्तन हेतु एकरा पुरा करी। यदि अहाँ अपन वर्तमान ईमेल पता हटाबैलेल चाहैत छी, तँ एकरा खाली छोडि दी आ एकरा भेजी।",
        "changeemail-no-info": "अहाँक ई पन्नाक सोझे प्रयोग करबालेल सम्प्रवेशित हुअए पडत।",
        "undo-nochange": "ऐना लगया की ई सम्पादन कें पहील से पूर्ववत करई देन अछि।",
        "undo-summary": "[[Special:Contributions/$2|$2]] ([[User talk:$2|वार्ता]])द्वारा कएल अन्तर $1 के पूर्ववत कएलक",
        "undo-summary-username-hidden": "नुकाएल गेल प्रयोक्ताद्वारा केल गेल परिवर्तन $1 के पूर्ववत केल गेल",
-       "cantcreateaccounttitle": "खाता नै बना सकल",
        "cantcreateaccount-text": "(<strong>$1</strong>) अनिकेत पतासँ खाता निर्माण प्रतिबन्धित कएल गेल [[User:$3|$3]]।\n$3 द्वारा देल कारण अछि ''$2''",
        "cantcreateaccount-range-text": "<strong>$1</strong> के श्रेणी में आबई वाला आई॰पी पता सऽ, जएमें आहाँ कें आई॰पी पता (<strong>$4</strong>) शामिल अछि, नया खाता के रचना [[User:$3|$3]] द्वारा अवरोधित केल गेल अछि। \n\n$3 द्वारा देल गेल कारण अछि: \"$2\"",
        "viewpagelogs": "ई पन्नाक वृत्तलेखसभ देखी",
index 6780a3f..868df89 100644 (file)
        "passwordreset-emailtext-user": "Sasaurang (mungkin Sanak, dari alamaik IP $1) mamintak parubahan kato sandi untuak {{SITENAME}} ($4).\n{{PLURAL:$3|Akun}} barikuik takaik jo alamaik surel ko:\n\n$2\n\n{{PLURAL:$3|Sandi samantaro}} barikuik akan habih masonyo dalam {{PLURAL:$5|$5 ari}}.\nSanak harus masuak dan mamiliah sandi baru. Jikok urang lain mambuek pamintaan ko atau jikok Sanak ingek sandi awal dan indak nio maubahnyo, Sanak dapek mangacuahkan pasan ko dan taruih manggunoan kato sandi lamo.",
        "passwordreset-emailelement": "Namo pangguno: \n$1\n\nSandi samantaro: \n$2",
        "passwordreset-emailsentemail": "Surel parubahan kato sandi alah dikirim.",
-       "passwordreset-emailsent-capture": "Surel parubahan kato sandi alah dikirim, nan nampak di bawah ko.",
-       "passwordreset-emailerror-capture": "Surel parubahan kato sandi nan ditampilan di bawah, alah dibuek, tapi pangirimannyo ka {{GENDER:$2|pangguno}} gagal: $1",
        "changeemail": "Tuka alamaik surel.",
        "changeemail-header": "Ganti alamaik surel.",
        "changeemail-no-info": "Sanak harus masuak log untuak mangakses laman ko.",
        "minoredit": "Suntiangan ketek",
        "watchthis": "Pantau laman ko",
        "savearticle": "Simpan",
+       "publishpage": "Tabikan laman",
+       "publishchanges": "Tabikan parubahan",
        "preview": "Caliak",
        "showpreview": "Pratonton",
        "showdiff": "Parubahan",
        "undo-failure": "Suntiangan ko indak dapek dibatalan dek konflik panyuntiangan antaro.",
        "undo-norev": "Suntiangan ko indak dapek dibatalan dek laman indak ditamukan atau lah dihapuih.",
        "undo-summary": "Mambatalan revisi $1 oleh [[Special:Contributions/$2|$2]] ([[User talk:$2|maota]])",
-       "cantcreateaccounttitle": "Indak dapek mambuek akun",
        "cantcreateaccount-text": "Mambuek akun dari alamat IP ko ('''$1''') alah diblok jo [[User:$3|$3]].\n\nAlasan nan diagiah jo $3 adolah ''$2''",
        "viewpagelogs": "Caliak log untuak laman ko",
        "nohistory": "Indak ado sajarah panyuntiangan untuak laman ko",
index 087ea59..170ccd8 100644 (file)
        "passwordreset-emailelement": "Корисничко име: \n$1\n\nПривремена лозинка: \n$2",
        "passwordreset-emailsentemail": "Ако ова е регистрираната е-пошта поврзана со вашата сметка, тогаш ќе ви биде испратено писмо за задавање на нова лозинка.",
        "passwordreset-emailsentusername": "Ако има соодветна регистрирана е-пошта поврзана со ова корисничко име, тогаш ќе ви биде испратена порака за промена на лозинката.",
-       "passwordreset-emailsent-capture": "Испратено е писмо за измена на лозинката (прикажано подолу).",
-       "passwordreset-emailerror-capture": "Создадено е писмо за измена на лозинката (прикажано подолу), но не успеав да го испратам на {{GENDER:$2|корисникот}}: $1",
        "passwordreset-emailsent-capture2": "{{PLURAL:$1|Е-поштата за задавање на нова лозинка|Е-поштата за задавање на нови лозинки}} е испратена. Подолу е {{PLURAL:$1|е прикажано корисничкото име и лозинката|прикажан список на кориснички имиња и лозинки}}.",
        "passwordreset-emailerror-capture2": "Испраќањето е-пошта на {{GENDER:$2|корисникот}} не успеа: $1 Подолу е {{PLURAL:$3|прикажано корисничкото име и лозинката|прикажан список на кориснички имиња и лозинки}}.",
        "passwordreset-nocaller": "Мора да се укаже повикувач",
        "passwordreset-nodata": "Немате укажано ни корисничко име, ни е-пошта.",
        "changeemail": "Смени или отстрани е-пошта",
        "changeemail-header": "Пополнете го образецов за да ја смените е-поштата. Ако сакате да ја отстраните адресата од вашата сметка, оставете го празно полето за нова е-пошта.",
-       "changeemail-passwordrequired": "Ќе треба да ја внесете лозинката за да ја потврдите измената.",
        "changeemail-no-info": "Мора да бидете најавени ако сакате да имате директен пристап до оваа страница.",
        "changeemail-oldemail": "Тековна е-пошта:",
        "changeemail-newemail": "Нова е-пошта:",
        "undo-nochange": "Се чини дека измената (уредувањето) е веќе вратена.",
        "undo-summary": "Откажано уредувањето $1 на уредникот [[Special:Contribs/$2|$2]] ([[User talk:$2|разговор]])",
        "undo-summary-username-hidden": "Поништи ја преработката $1 на скриен корисник",
-       "cantcreateaccounttitle": "Не може да се создаде корисничка сметка",
        "cantcreateaccount-text": "Создавањето на корисничка сметка од оваа IP-адреса ('''$1''') е блокирано од страна на [[User:$3|$3]].\n\nОбразложението дадено од страна на $3 е ''$2''",
        "cantcreateaccount-range-text": "Создавањето на сметки од IP-адреси во опсегот <strong>$1</strong> каде спаѓа вашата IP-адреса (<strong>$4</strong>) е блокирано од корисникот [[User:$3|$3]].\n\n$3 ја наведе следнава причина: <em>$2</em>",
        "viewpagelogs": "Преглед на дневници за оваа страница",
index 793c5ab..389d307 100644 (file)
        "passwordreset-emailelement": "ഉപയോക്തൃനാമം: \n$1\n\nതാത്കാലിക രഹസ്യവാക്ക്: \n$2",
        "passwordreset-emailsentemail": "താങ്കളുടെ അംഗത്വത്തിന് നൽകിയിട്ടുള്ള ഇമെയിൽ വിലാസം ഇതാണെങ്കിൽ,  രഹസ്യവാക്ക് പുനർസജ്ജീകരണ ഇമെയിൽ അയക്കുന്നതാണ്.",
        "passwordreset-emailsentusername": "ഈ ഉപയോക്തൃനാമത്തിന് ഒരു ഇമെയിൽ വിലാസം ചേർത്തിട്ടുണ്ടെങ്കിൽ,  രഹസ്യവാക്ക് പുനർസജ്ജീകരണ ഇമെയിൽ അയക്കുന്നതാണ്.",
-       "passwordreset-emailsent-capture": "രഹസ്യവാക്ക് പുനർസജ്ജീകരണ ഇമെയിൽ അയച്ചിട്ടുണ്ട്, അത് താഴെക്കൊടുക്കുന്നു.",
-       "passwordreset-emailerror-capture": "താഴെക്കൊടുത്തിരിക്കുന്ന, രഹസ്യവാക്ക് പുനർസജ്ജീകരണ ഇമെയിൽ സൃഷ്ടിക്കാനായെങ്കിലും, അത് {{GENDER:$2|ഉപയോക്താവിന്}} അയയ്ക്കുന്നത് പരാജയപ്പെട്ടു: $1",
        "changeemail": "ഇമെയിൽ വിലാസം മാറ്റുക അല്ലെങ്കിൽ നീക്കംചെയ്യുക",
        "changeemail-header": "താങ്കളുടെ ഇമെയിൽ വിലാസത്തിൽ മാറ്റംവരുത്താൻ ഈ ഫോം പൂരിപ്പിച്ചു നൽകുക.താങ്കളുടെ അംഗത്വവുമായി ഏതെങ്കിലുമൊരു ഇമെയിൽ വിലാസത്തിനുള്ള ബന്ധം ഒഴിവാക്കാൻ ഫോം പൂരിപ്പിക്കുമ്പോൾ പുതിയ ഇമെയിൽ വിലാസത്തിനുള്ള ഭാഗം ഒഴിച്ചിടുക.",
-       "changeemail-passwordrequired": "ഈ മാറ്റം സ്ഥിരീകരിക്കാൻ താങ്കളുടെ രഹസ്യവാക്ക് നൽകുക.",
        "changeemail-no-info": "ഈ താൾ നേരിട്ടു കാണുന്നതിന് താങ്കൾ ലോഗിൻ ചെയ്തിരിക്കണം.",
        "changeemail-oldemail": "ഇപ്പോഴത്തെ ഇമെയിൽ വിലാസം:",
        "changeemail-newemail": "പുതിയ ഇമെയിൽ വിലാസം:",
        "undo-nochange": "തിരുത്ത് മുമ്പേ തന്നെ ഒഴിവാക്കിയതായി കാണുന്നു.",
        "undo-summary": "[[Special:Contributions/$2|$2]] ([[User talk:$2|സംവാദം]]) ചെയ്ത നാൾപ്പതിപ്പ് $1 നീക്കം ചെയ്യുന്നു",
        "undo-summary-username-hidden": "മറയ്ക്കപ്പെട്ട ഉപയോക്താവ് ചെയ്ത നാൾപ്പതിപ്പ് $1 തിരസ്കരിക്കുക",
-       "cantcreateaccounttitle": "അംഗത്വം സൃഷ്ടിക്കാൻ സാധിച്ചില്ല",
        "cantcreateaccount-text": "ഈ ഐ.പി. ('''$1''') വിലാസത്തിൽ നിന്നു അംഗത്വം സൃഷ്ടിക്കുന്നത് [[User:$3|$3]] നിരോധിച്ചിരിക്കുന്നു.\n\n$3 അതിനു കാണിച്ചിരിക്കുന്ന കാരണം ''$2'' ആണ്‌.",
        "cantcreateaccount-range-text": "താങ്കളുടെ ഐ.പി. വിലാസം (<strong>$4</strong>) ഉൾപ്പെടുന്ന <strong>$1</strong> എന്ന പരിധിയിലെ ഐ.പി. വിലാസങ്ങളിൽ നിന്ന് അംഗത്വമെടുക്കുന്നത് [[User:$3|$3]] തടഞ്ഞിരിക്കുകയാണ്.\n\n$3 നൽകിയിരിക്കുന്ന കാരണം <em>$2</em> എന്നാണ്",
        "viewpagelogs": "ഈ താളുമായി ബന്ധപ്പെട്ട രേഖകൾ കാണുക",
index 7f02a6c..4a82353 100644 (file)
        "passwordreset-emailtext-user": "Pengguna $1 telah memohon supaya kata laluan diset semula untuk {{SITENAME}} anda ($4). {{PLURAL:$3|Akaun|Akaun-akaun}} pengguna yang berikut\ndikaitkan dengan alamat e-mel ini:\n\n$2\n\n{{PLURAL:$3|Kata|Kata-kata}} laluan sementara ini akan luput dalam masa $5 hari. Anda harus log masuk dan membuat kata laluan yang baru sekarang. Jika permohonan ini dibuat oleh orang lain, atau jika anda teringat kembali kata laluan asal anda dan anda tidak lagi berhasrat untuk mengubahnya, anda boleh mengabaikan pesanan ini dan terus menggunakan kata laluan lama anda.",
        "passwordreset-emailelement": "Nama pengguna: \n$1\n\nKata laluan sementara: \n$2",
        "passwordreset-emailsentemail": "Jika ini ialah alamat e-mel yang terdaftar untuk akaun anda, maka e-mel set semula kata laluan akan dihantar.",
-       "passwordreset-emailsent-capture": "E-mel set semula kata laluan telah dihantar, seperti yang dipaparkan di bawah.",
-       "passwordreset-emailerror-capture": "E-mel set semula kata laluan telah dihasilkan, seperti yang dipaparkan di bawah, tetapi tidak berjaya dihantar kepada {{GENDER:$2|pengguna}} berkenaan: $1",
        "changeemail": "Tukar atau padamkan alamat e-mel",
        "changeemail-header": "Lengkapkan borang ini untuk menukar alamat e-mel anda. Jika anda ingin memutuskan sebarang hubungan alamat e-mel daripada akaun anda, biarkan ruangan alamat e-mel kosong ketika menghantar borang.",
-       "changeemail-passwordrequired": "Anda akan dikehendaki memasukkan kata laluan untuk mengesahkan perubahan ini.",
        "changeemail-no-info": "Anda hendaklah log masuk terlebih dahulu untuk mencapai laman ini secara terus.",
        "changeemail-oldemail": "Alamat e-mel sekarang:",
        "changeemail-newemail": "Alamat e-mel baru:",
        "undo-nochange": "Suntingan itu nampaknya sudah dibatalkan.",
        "undo-summary": "Membatalkan semakan $1 oleh [[Special:Contributions/$2|$2]] ([[User talk:$2|Perbincangan]])",
        "undo-summary-username-hidden": "Buat asal semakan $1 oleh pengguna tersembunyi",
-       "cantcreateaccounttitle": "Akaun tidak dapat dibuka",
        "cantcreateaccount-text": "Pembukaan akaun daripada alamat IP ini (<b>$1</b>) telah disekat oleh [[User:$3|$3]].\n\nSebab yang diberikan oleh $3 ialah ''$2''",
        "cantcreateaccount-range-text": "Pembukaan akaun dari alamat-alamat IP dalam julat <strong>$1</strong>, termasuk alamat IP anda (<strong>$4</strong>), telah disekat oleh [[User:$3|$3]].\n\nSebab yang diberikan oleh $3 ialah <em>$2</em>",
        "viewpagelogs": "Lihat log bagi laman ini",
index 9cae000..21bf1d8 100644 (file)
        "minoredit": "အရေးမကြီးသော ​ပြင်​ဆင်​မှု ​ဖြစ်​သည်​",
        "watchthis": "ဤစာမျက်နှာကို စောင့်ကြည့်ရန်",
        "savearticle": "ဤစာမျက်နှာကို သိမ်းရန်",
+       "publishpage": "စာမျက်နှာကို လွှင့်တင်ရန်",
+       "publishchanges": "ပြောင်းလဲမှုများကို လွှင့်တင်ရန်",
        "preview": "နမူနာ",
        "showpreview": "န​မူ​နာ​ပြ​ရန်",
        "showdiff": "ပြင်​ဆင်​ထား​သည်​များ​ကို​ ပြရန်",
index 591bdec..d60887a 100644 (file)
        "edit-conflict": "Tlapatlaliztli yāōyōtōn",
        "edit-already-exists": "Ahmo mohuelīti mochīhua yancuīc zāzanilli.\nYe ia.",
        "content-model-javascript": "JavaScript",
-       "cantcreateaccounttitle": "Ahmo huelītih mochīhua cuentah",
        "cantcreateaccount-text": "[[User:$3|$3]] ōcquīxti cuentah tlachīhualiztli īpal inīn IP ('''$1''').\n\nĪxtlamatiliztli īpal $3 cah ''$2''",
        "viewpagelogs": "Tiquinttāz tlahcuilōlloh inīn zāzaniltechcopa",
        "nohistory": "Nicān ahmō oncah tlaīxtlapatlaliztlahtōllōtl.",
index a39cb81..1858d4d 100644 (file)
        "passwordreset-emailelement": "Nomme utente: \n$1\n\nPassword temporanea: \n$2",
        "passwordreset-emailsentemail": "Si chesto fosse nu cunto e-mail suoccio a 'o cunto vuost, allora buò dicere ca se mannarrà na mmasciata e-mail pe' riabbià 'a password.",
        "passwordreset-emailsentusername": "Si esistesse nu cunto e-mail suòccio a stu nomme utente, allora se mannarrà na mmasciata pe' riabbià 'a password.",
-       "passwordreset-emailsent-capture": "Na mmasciata e-mail pe' riabbià 'a password è stata mannata, chista mmasciata 'a putite vedé ccà abbascio.",
-       "passwordreset-emailerror-capture": "Na mmasciata e-mail pe' riabbià 'a password è stata mannata, 'a putite vedé ccà abbascio, ma aita sapé ca nun s'è mannata a {{GENDER:$2|l'utente}} pecché c'è stato cocch'errore: $1",
        "passwordreset-emailsent-capture2": "L'email 'e reimpostazione d' 'a password {{PLURAL:$1|è stata mannata|so' state mannate}}. {{PLURAL:$1|'O nomme|L'elenco 'e nomme}} utente e password è mmustato ccà.",
        "passwordreset-emailerror-capture2": "'O mannà 'email {{GENDER:$2|a ll'utente}} guastaje: $1. {{PLURAL:$3|'O nomme|L'elenco 'e nomme}} utente e password se ffà vedé ccà.",
        "passwordreset-nocaller": "Nu chiammate s'avess'a dà",
        "passwordreset-nodata": "Nun è stato fornito né nomme utente né indirizzo 'e posta email",
        "changeemail": "Cagna o lèva l'indirizzo e-mail",
        "changeemail-header": "Ghienchete stu modulo pe' puté cagnà 'o indirizzo e-mail d' 'o vuosto. Si vuje vulite luvà e 'o scucchià l'associazione 'e cocche cunto mail d' 'o cunto vuosto, lassate 'o cunto e-mail nuovo abbacante quanno mannarrate stu modulo.",
-       "changeemail-passwordrequired": "Avit'a miette 'a password vuosto pe' dà a cunferma 'e stu cagnamiento.",
        "changeemail-no-info": "Avite 'a trasì ('o login) pe ffà l'acciesso a sta paggena direttamente.",
        "changeemail-oldemail": "Indirizzo email 'e mmò:",
        "changeemail-newemail": "Indirizzo e-mail nuovo:",
        "undo-nochange": "Pare c' 'o cagnamiento s'è già fatto turnà arreto.",
        "undo-summary": "Canciella 'o cagnamiento $1 'e [[Special:Contributions/$2|$2]] ([[User talk:$2|Chiàcchiera]])",
        "undo-summary-username-hidden": "Annullato 'o cagnamiento $1 pe n'utente annascunnuto",
-       "cantcreateaccounttitle": "Nun se può crià cunto",
        "cantcreateaccount-text": "'A riggistraziona è stata bloccata 'a l'utente [[User:$3|$3]] 'a st'innerizzo IP ('''$1''').\n\n'O mutivo dato 'a $3 è chistu ccà: ''$2''",
        "cantcreateaccount-range-text": "'A criazione 'e cunte 'a ll'indirizze int'o ntervallo <strong>$1</strong>, che cummiglia 'o vuosto (<strong>$4</strong>), è stata bloccata 'a l'utente [[User:$3|$3]].\n\n'O mutivo dato 'a $3 è chistu ccà: <em>$2</em>",
        "viewpagelogs": "Vide 'e log azzeccate a sta paggena",
index 6332449..150527f 100644 (file)
        "passwordreset-emailelement": "Brukernavn: \n$1\n\nMidlertidig passord: \n$2",
        "passwordreset-emailsentemail": "Hvis denne epostadressen er koblet til din konto, så vil det bli sendt en epost om tilbakestilling av passord.",
        "passwordreset-emailsentusername": "Hvis det finnes en epostadresse knyttet til dette brukernavnet, vil en epost med informasjon om tilbakestilling av passord bli sendt.",
-       "passwordreset-emailsent-capture": "Passordtilbakestillingseposten vist under har blitt sendt ut.",
-       "passwordreset-emailerror-capture": "En passordtilbakestillingsepost ble laget, men det lyktes ikke å sende denne til {{GENDER:$2|brukeren}}: $1",
        "changeemail": "Endre eller fjerne epostadresse",
        "changeemail-header": "Fyll ut dette skjemaet for å bytte din epost-adresse. Hvis du vil fjerne epostadressen fra din konto, kan du la ny epostadresse-feltet være tomt når.",
-       "changeemail-passwordrequired": "Du må skrive inn passordet ditt for å bekrefte denne endringen.",
        "changeemail-no-info": "Du må være innlogget for å få direkte tilgang til denne siden.",
        "changeemail-oldemail": "Nåværende e-postadresse:",
        "changeemail-newemail": "Ny e-postadresse:",
        "undo-nochange": "Det ser ut til at redigeringen allerede er tilbakestilt.",
        "undo-summary": "Fjerner revisjon $1 av [[Special:Contributions/$2|$2]] ([[User talk:$2|diskusjon]])",
        "undo-summary-username-hidden": "Fjern revisjon $1 av en skjult bruker",
-       "cantcreateaccounttitle": "Kan ikke opprette konto",
        "cantcreateaccount-text": "Kontooppretting fra denne IP-adressen ('''$1''') har blitt blokkert av [[User:$3|$3]].\n\nGrunnen som ble oppgitt av $3 er ''$2''",
        "cantcreateaccount-range-text": "Opprettelsen av en brukerkonto fra IP-adresser i intervallet <strong>$1</strong>, som inneholder din IP-adresse (<strong>$4</strong>), er blitt blokkert av [[User:$3|$3]].\n\nÅrsaken angitt av $3 er <em>$2</em>",
        "viewpagelogs": "Vis logger for denne siden",
index 73f9631..6cd436a 100644 (file)
        "minoredit": "Blots lütte Ännern",
        "watchthis": "Op disse Siet oppassen",
        "savearticle": "Siet spiekern",
+       "publishpage": "Siet nee afspiekern",
+       "publishchanges": "ännerte Siet afspiekern",
        "preview": "Vörschau",
        "showpreview": "Vörschau wiesen",
        "showdiff": "Ünnerscheed wiesen",
        "undo-failure": "Kunn de Siet nich op de vörige Version trüchdreihn. De Afsnitt is twischendör al wedder ännert worrn.",
        "undo-norev": "De Ännern kunn nich trüchdreiht warrn, de gifft dat nich oder is wegsmeten worrn.",
        "undo-summary": "Ännern $1 vun [[Special:Contributions/$2|$2]] ([[User talk:$2|Diskuschoon]]) trüchdreiht.",
-       "cantcreateaccounttitle": "Brukerkonto kann nich anleggt warrn",
        "cantcreateaccount-text": "Dat Opstellen vun Brukerkonten vun de IP-Adress '''$1''' ut is vun [[User:$3|$3]] sperrt worrn.\n\nDe Grund weer: ''$2''",
        "viewpagelogs": "Logbook för disse Siet",
        "nohistory": "Disse Siet hett keen Vörgeschicht.",
index bda199e..4a97196 100644 (file)
        "passwordreset-emailtext-user": "{{SITENAME}} को $1 प्रयोगकर्ताले  {{SITENAME}} ($4)को लागि खाता विवरणको निम्ति एउटा अनुस्मारकको अनुरोध गरेको छ। निम्न प्रयोगकर्ता {{PLURAL:$3|खाता यस इमेल ठेगानासित सम्बन्धित छ|खाताहरू यस इमेल ठेगानासित सम्बन्धित छन्}}:\n\n$2\n\n{{PLURAL:$3|यो अस्थाई पासवर्डको|यी अस्थाई पासवर्डहरूको}} समय {{PLURAL:$5|एक दिन|$5 दिन}}मा सकिनेछ।\nतपाईंले प्रवेश गरेर अहिले नैं नयाँ पासवर्ड छान्नुहोस्। यदि अरु कसैले अनुरोध गरेको भए अथवा यदि तपाईंलाई मूल पासवर्ड याद भए अनि यसलाई परिवर्तन गर्न चाहनुहुन्न भनें, तपाईंले यस सन्देशलाई अनदेखा गर्नुहोस् र पुरानै पासवर्डलाई चालू राख्नुहोस्।",
        "passwordreset-emailelement": "प्रयोगकर्ताको नाम: \n$1\n\nअस्थाई पासवर्ड: \n$2",
        "passwordreset-emailsentemail": "पासवर्ड परिवर्तनको लागि इमेल पठाइएको छ।",
-       "passwordreset-emailsent-capture": "पासवर्ड परिवर्तनको लागि इमेल पठाइयो, जुन तल देखाइएकोछ।",
-       "passwordreset-emailerror-capture": "पासवर्ड रिसेट इमेल जारि गरिएको छ, जुन तल देखाइएको छ, तर यसलाई {{GENDER:$2|प्रयोगकर्ता}}मा पठाउन विफल भयो: $1",
        "changeemail": "इमेल ठेगाना परिवर्तन गर्नुहोस",
        "changeemail-header": "खाताको इमेल ठेगाना परिवर्तन गर्नुहोस",
        "changeemail-no-info": "यस पृष्ठमा सिधै जानको लागि प्रवेश गर्नु पर्ने हुन्छ ।",
        "undo-nochange": "सम्पादन पहिला नै विफल गरिएको छ ।",
        "undo-summary": "  $1द्वारा पुनरावलोकन [[Special:Contributions/$2|$2]] ([[User talk:$2|वार्तालाप]]) खारेज गर्नुहोस",
        "undo-summary-username-hidden": "अदृश्य प्रयोगकर्ताको संशोधन $1 लाई पहिला जस्तै बनाउने",
-       "cantcreateaccounttitle": "खाता बनाउन सकिएन",
        "cantcreateaccount-text": "IP ठेगाना ('''$1''')बाट खाता खोल्न  [[User:$3|$3]]द्वारा बन्देज लगाइएको छ।\n\n $3ले दिनुभएको कारण  ''$2'' हो",
        "cantcreateaccount-range-text": "<strong>$1</strong> को श्रेणीमा आउने आइपि ठेगानाबाट, जसमा तपाईंको आइपि ठेगाना (<strong>$4</strong>) सामेल छ, नयाँ खाता सृजना [[User:$3|$3]]द्वारा अवरोधित गरिएको छ। \n\n$3 द्वारा दिइएको कारण: \"$2\"",
        "viewpagelogs": "यस पृष्ठका लगहरू हेर्नुहोस्",
index 3357ad2..4a0ba41 100644 (file)
        "passwordreset-emailelement": "Gebruikersnaam: \n$1\n\nTijdelijk wachtwoord: \n$2",
        "passwordreset-emailsentemail": "Als dit e-mailadres aan uw account gekoppeld is, dan wordt er een e-mail verzonden om uw wachtwoord opnieuw in te stellen.",
        "passwordreset-emailsentusername": "Als er een e-mailadres geregistreerd is voor die gebruikersnaam, dan wordt er een e-mail verzonden om uw wachtwoord opnieuw in te stellen.",
-       "passwordreset-emailsent-capture": "Er is een e-mail voor het opnieuw instellen van een wachtwoord verzonden. Deze wordt hieronder weergegeven.",
-       "passwordreset-emailerror-capture": "Er is een e-mail voor het opnieuw instellen van een wachtwoord aangemaakt. Deze wordt hieronder weergegeven. Het verzenden naar de {{GENDER:$2|gebruiker}} is mislukt om de volgende reden: $1",
        "passwordreset-invalideamil": "Ongeldig e-mailadres",
        "changeemail": "E-mailadres wijzigen of verwijderen",
        "changeemail-header": "Vul dit formulier in om uw e-mailadres te wijzigen. Als u het e-mailadres wilt ontkoppelen van uw account, laat het e-mailadres dan leeg als u het formulier opslaat.",
-       "changeemail-passwordrequired": "U  moet uw wachtwoord invoeren om deze wijziging te bevestigen.",
        "changeemail-no-info": "U moet aangemeld zijn om rechtstreeks toegang te hebben tot deze pagina.",
        "changeemail-oldemail": "Huidig e-mailadres:",
        "changeemail-newemail": "Nieuw e-mailadres:",
        "undo-nochange": "De bewerking lijkt al ongedaan gemaakt te zijn.",
        "undo-summary": "Versie $1 van [[Special:Contributions/$2|$2]] ([[User talk:$2|overleg]]) ongedaan gemaakt",
        "undo-summary-username-hidden": "Versie $1 door een verborgen gebruiker ongedaan gemaakt",
-       "cantcreateaccounttitle": "Registreren is mislukt.",
        "cantcreateaccount-text": "Registreren vanaf dit IP-adres ('''$1''') is geblokkeerd door [[User:$3|$3]].\n\nDe door $3 opgegeven reden is ''$2''",
        "cantcreateaccount-range-text": "Het aanmaken van gebruikers vanaf IP-adressen in de range <strong>$1</strong> is niet mogelijk doordat dit is ingesteld door [[User:$3|$3]]. Uw IP-adres $4 bevindt zich in deze range.\n\nDe reden voor de blokkade is <em>$2</em>",
        "viewpagelogs": "Logboek voor deze pagina bekijken",
index 2e7b628..bffd6e9 100644 (file)
        "passwordreset-emailtext-user": "Brukaren $1 på {{SITENAME}} bad om ei påminning for kontodetaljane dine for {{SITENAME}} ($4). {{PLURAL:$3|Den fylgjande brukarkontoen|Dei fylgjande brukarkontoane}} er assosierte med denne e-postadressa:\n\n$2\n\n{{PLURAL:$3|Dette mellombels passordet|Desse mellombels passorda}} vil verta ugilde om {{PLURAL:$5|éin dag|$5 dagar}}.\nDu bør logga inn og velja eit nytt passord no. Om nokon andre enn deg bad om denne påminninga, eller du har kome i hug det opphavlege passordet og ikkje lenger ynskjer å endra det, kan du sjå bort frå denne meldinga og halda fram med å nytta det gamle passordet ditt.",
        "passwordreset-emailelement": "↓Brukarnamn: \n$1\n\nMellombels passord: \n$2",
        "passwordreset-emailsentemail": "Ein e-post for attendestilling av passord er vorten send",
-       "passwordreset-emailsent-capture": "Ein e-post om attendestilling av passord - vist under - er vorten send",
-       "passwordreset-emailerror-capture": "Ein e-post om attendestilling av passord vart oppretta, og er vist nedanfor; men det lukkast ikkje å senda han til {{GENDER:$2|brukaren}}: $1",
        "changeemail": "↓Endre e-postadresse",
        "changeemail-header": "↓Endre kontoen si e-postadresse",
        "changeemail-no-info": "↓Du må vera pålogga for å få tilgang direkte til denne sida.",
        "undo-failure": "Endringa kunne ikkje attenderullast grunna konflikt med endringar som er gjorde i mellomtida.",
        "undo-norev": "Endringa kunne ikkje fjernast fordi han ikkje finst eller vart sletta",
        "undo-summary": "Rullar attende versjon $1 av [[Special:Contributions/$2|$2]] ([[User talk:$2|diskusjon]])",
-       "cantcreateaccounttitle": "Kan ikkje opprette brukarkonto",
        "cantcreateaccount-text": "Kontooppretting frå denne IP-adressa ('''$1''') er blokkert av [[User:$3|$3]].\n\nGrunnen som vart gjeven av $3 er ''$2''",
        "viewpagelogs": "Vis loggane for sida",
        "nohistory": "Det finst ikkje nokon historikk for denne sida.",
index 66bf6a4..829bb0e 100644 (file)
        "passwordreset-emailtext-user": "{{SITENAME}} 'ਤੇ User $1 ਨੇ ਤੁਹਾਡੇ {{SITENAME}} ($4) ਉਤਲੇ ਪਛਾਣ-ਸ਼ਬਦ ਨੂੰ ਮੁੜ-ਬਣਾਉਣ ਦੀ ਬੇਨਤੀ ਕੀਤੀ ਹੈ। ਇਸ ਈਮੇਲ ਪਤੇ ਨਾਲ਼ ਹੇਠ ਲਿਖੇ {{PLURAL:$3|ਖਾਤੇ|ਖਾਤਿਆਂ}} ਦਾ ਵਾਸਤਾ ਹੈ:\n\n$2\n\n{{PLURAL:$3|ਇਸ ਆਰਜ਼ੀ ਪਛਾਣ-ਸ਼ਬਦ|ਇਹਨਾਂ ਆਰਜ਼ੀ ਪਛਾਣ-ਸ਼ਬਦਾਂ}} ਦੀ ਮਿਆਦ {{PLURAL:$5|ਇੱਕ ਦਿਨ|$5 ਦਿਨਾਂ}} 'ਚ ਮੁੱਕ ਜਾਵੇਗੀ।\nਤੁਹਾਨੂੰ ਹੁਣੇ ਦਾਖ਼ਲ ਹੋ ਕੇ ਕੋਈ ਨਵਾਂ ਪਛਾਣ-ਸ਼ਬਦ ਬਣਾ ਲੈਣਾ ਚਾਹੀਦਾ ਹੈ। ਜੇਕਰ ਕਿਸੇ ਹੋਰ ਨੇ ਇਹ ਬੇਨਤੀ ਕੀਤੀ ਹੈ ਜਾਂ ਤੁਹਾਨੂੰ ਆਪਣਾ ਪਹਿਲਾ ਪਛਾਣ-ਸ਼ਬਦ ਯਾਦ ਆ ਗਿਆ ਹੈ ਅਤੇ ਹੁਣ ਤੁਸੀਂ ਉਹਨੂੰ ਬਦਲ਼ਨਾ ਨਹੀਂ ਲੋਚਦੇ ਤਾਂ ਤੁਸੀਂ ਇਸ ਸੁਨੇਹੇ ਨੂੰ ਅਣਡਿੱਠਾ ਕਰ ਕੇ ਆਪਣਾ ਪੁਰਾਣਾ ਪਛਾਣ-ਸ਼ਬਦ ਵਰਤਦੇ ਰਹਿ ਸਕਦੇ ਹੋ।",
        "passwordreset-emailelement": "ਯੂਜ਼ਰ-ਨਾਂ: \n$1\n\nਆਰਜ਼ੀ ਪਾਸਵਰਡ: \n$2",
        "passwordreset-emailsentemail": "ਇੱਕ ਪਾਸਵਰਡ ਮੁੜ-ਸੈੱਟ ਈ-ਮੇਲ ਭੇਜੀ ਜਾ ਚੁੱਕੀ ਹੈ।",
-       "passwordreset-emailsent-capture": "ਇੱਕ ਯਾਦ-ਦਹਾਨੀ ਈ-ਮੇਲ, ਜਿਹੜੀ ਕਿ ਹੇਠਾਂ ਦਿੱਸ ਰਹੀ ਹੈ, ਭੇਜੀ ਜਾ ਚੁੱਕੀ ਹੈ।",
-       "passwordreset-emailerror-capture": "ਪਛਾਣ-ਸ਼ਬਦ ਮੁੜ ਬਣਾਉਣ ਵਾਸਤੇ ਈਮੇਲ ਤਿਆਰ ਹੋ ਗਈ ਸੀ, ਜੋ ਹੇਠਾਂ ਵਿਖਾਈ ਗਈ ਹੈ, ਪਰ ਇਹਨੂੰ {{GENDER:$2|ਵਰਤੋਂਕਾਰ}} ਵੱਲ ਨਹੀਂ ਘੱਲਿਆ ਜਾ ਸਕਿਆ: $1",
        "passwordreset-invalideamil": "ਗ਼ਲਤ ਈਮੇਲ ਪਤਾ",
        "changeemail": "ਈ-ਮੇਲ ਸਿਰਨਾਵਾਂ ਬਦਲੋ ਜਾੰ ਹਟਾਓ",
        "changeemail-header": "ਖਾਤੇ ਵਾਲਾ ਈ-ਮੇਲ ਸਿਰਨਾਵਾਂ ਬਦਲੋ",
        "undo-nochange": "ਲਗਦਾ ਹੈ ਕਿ ਿਹ ਸੋਧ ਪਹਿਲਾਂ ਹੀ ਮੋੜ ਦਿੱਤੀ ਗਈ ਹੈ।",
        "undo-summary": "[[Special:Contributions/$2|$2]] ([[User talk:$2|ਗੱਲ-ਬਾਤ]]) ਦੀ ਸੋਧ $1 ਨਕਾਰੀ",
        "undo-summary-username-hidden": "ਗੁਪਤ ਵਰਤੋਂਕਾਰ ਵੱਲੋਂ ਕੀਤੀ $1 ਸੋਧ ਰੱਦ ਕਰੋ",
-       "cantcreateaccounttitle": "ਖਾਤਾ ਬਣਾਇਆ ਨਹੀਂ ਜਾ ਸਕਦਾ",
        "cantcreateaccount-text": "[[User:$3|$3]] ਨੇ ਇਸ IP ਪਤੇ ('''$1''') ਤੋਂ ਖਾਤਾ ਬਣਾਉਣ ਤੇ ਪਾਬੰਦੀ ਲਾਈ ਹੈ।\n\n$3 ਨੇ ਕਾਰਨ ਇਹ ਦੱਸਿਆ ਹੈ, ''$2''",
        "viewpagelogs": "ਇਹ ਸਫ਼ੇ ਲਈ ਇੰਦਰਾਜ ਵੇਖੋ",
        "nohistory": "ਇਸ ਸਫ਼ੇ ਲਈ ਕੋਈ ਸੋਧ ਅਤੀਤ ਨਹੀਂ ਹੈ।",
index 2e10b6a..f6b9259 100644 (file)
        "passwordreset-emailelement": "Nazwa użytkownika: \n$1\n\nTymczasowe hasło: \n$2",
        "passwordreset-emailsentemail": "Jeśli ten adres e‐mail jest przypisany do Twojego konta, zostanie na niego wysłany e-mail do odzyskiwania hasła.",
        "passwordreset-emailsentusername": "Jeśli z tym kontem powiązany jest adres e‐mail, zostanie na niego wysłany e-mail do odzyskiwania hasła.",
-       "passwordreset-emailsent-capture": "Wyświetlony poniżej e‐mail pozwalający na zresetowanie hasła został wysłany.",
-       "passwordreset-emailerror-capture": "Poniżej wyświetlony e‐mail pozwalający na zresetowanie hasła został wygenerowany, ale nie udało się wysłać go do {{GENDER:$2|użytkownika|użytkowniczki}}: $1",
        "passwordreset-emailsent-capture2": "{{PLURAL:$1|Został wysłany e-mail|Zostały wysłane e-mail}} z informacjami o resetowaniu hasła. {{PLURAL:$1|Użytkownik i hasło jest pokazany|Lista użytkowników i haseł jest pokazana}} poniżej.",
        "passwordreset-emailerror-capture2": "Wysyłanie e-maila do {{GENDER:$2|użytkownika|użytkowniczki}} nie powiodło się: $1 {{PLURAL:$3|Użytkownik i hasło jest pokazany|Lista użytkowników i haseł jest pokazana}} poniżej.",
        "passwordreset-nocaller": "Musi być podany wywołujący",
        "passwordreset-nodata": "Nie podano ani nazwy użytkownika, ani adresu e-mail",
        "changeemail": "Zmiana lub usunięcie adresu e‐mail",
        "changeemail-header": "Wypełnij ten formularz, aby zmienić swój adres e-mail. Jeśli chcesz usunąć swój adres e-mail, to przy wypełnianiu formularza pozostaw puste pole nowego adresu e-mail.",
-       "changeemail-passwordrequired": "Musisz podać swoje hasło, aby potwierdzić tę zmianę.",
        "changeemail-no-info": "Musisz być zalogowany, by uzyskać bezpośredni dostęp do tej strony.",
        "changeemail-oldemail": "Obecny adres e‐mail:",
        "changeemail-newemail": "Nowy adres e-mail:",
        "undo-nochange": "Wygląda na to, że edycja została już anulowana.",
        "undo-summary": "Anulowanie wersji $1 autora [[Special:Contributions/$2|$2]] ([[User talk:$2|dyskusja]])",
        "undo-summary-username-hidden": "Anulowanie wersji $1 autorstwa ukrytego użytkownika",
-       "cantcreateaccounttitle": "Nie można utworzyć konta",
        "cantcreateaccount-text": "Tworzenie konta z tego adresu IP ('''$1''') zostało zablokowane przez [[User:$3|$3]].\n\nPodany przez $3 powód to ''$2''",
        "cantcreateaccount-range-text": "Tworzenie konta z adresów IP w zakresie <strong>$1</strong>, zawierającego twój adres IP (<strong>$4</strong>), zostało zablokowane przez [[User:$3|$3]].\n\nPodany przez $3 powód to <em>$2</em>",
        "viewpagelogs": "Zobacz rejestry operacji dla tej strony",
index 3ae5be0..e0b4667 100644 (file)
        "passwordreset-emailtext-user": "L'utent $1 ansima a {{SITENAME}} a l'ha ciamà na riampostassion ëd soa ciav për {{SITENAME}} ($4). {{PLURAL:$3|Ël cont utent sì-sota a l'é|Ij cont utent sì-sota a son}} associà a st'adrëssa ëd pòsta eletrònica:\n\n$2\n\n{{PLURAL:$3|Costa ciav provisòria|Coste ciav provisòrie}} a scadran da-sì {{PLURAL:$5|un di|$5 di}}.\nA dovrìa intré ant ël sistema e serne na ciav neuva adess. Se quaidun d'àutr a l'ha fàit costa arcesta, o s'a l'é arcordasse soa ciav original, e a veul pa pi cangela, a peul ignoré ës mëssagi e continué a dovré soa veja ciav.",
        "passwordreset-emailelement": "Stranòm: \n$1\n\nCiav provisòria: \n$2",
        "passwordreset-emailsentemail": "Un mëssagi ëd riampostassion ëd la ciav a l'é stàit spedì.",
-       "passwordreset-emailsent-capture": "Un mëssagi ëd riampostassion ëd la ciav a l'é stàit mandà, e a l'é mostrà sì-sota.",
-       "passwordreset-emailerror-capture": "Un mëssagi ëd riampostassion ëd la ciav a l'é stàit generà, e a l'é smonù sì-sota, ma la spedission a {{GENDER:$2|l'utent}} a l'é falìa: $1",
        "changeemail": "Cangé l'adrëssa ëd pòsta eletrònica",
        "changeemail-header": "Cangé l'adrëssa ëd pòsta eletrònica dël cont",
        "changeemail-no-info": "A dev esse intrà ant ël sistema për andé diretament a costa pàgina.",
        "undo-nochange": "A smija che la modìfica a sia già stàita anulà.",
        "undo-summary": "Gavà la revision $1 fàita da [[Special:Contributions/$2|$2]] ([[User talk:$2|Ciaciarade]])",
        "undo-summary-username-hidden": "Anulé la revision $1 ëd n'utent ëstërmà",
-       "cantcreateaccounttitle": "As peul pa registresse d'utent",
        "cantcreateaccount-text": "La cression ëd cont neuv a parte da st'adrëssa IP-sì ('''$1''') a l'é stàita blocà da [[User:$3|$3]].\n\nLa rason butà da $3 për ël blocagi a l'é stàita: ''$2''",
        "cantcreateaccount-range-text": "La creassion ëd cont da l'adrëssa IP ant l'antërval <strong>$1</strong>, ch'a comprend soa adrëssa IP (<strong>$4</strong>), a l'é stàita blocà da [[User:$3|$3]].\n\nLa rason dàita da $3 a l'é <em>$2</em>",
        "viewpagelogs": "Smon ij registr dë sta pàgina-sì",
index a7709b6..f50e348 100644 (file)
        "passwordreset-emailelement": "Usuário: \n$1\n\nSenha temporária: \n$2",
        "passwordreset-emailsentemail": "Se este é um endereço de e-mail registrado para a sua conta, em seguida, um e-mail de redefinição de senha será enviada.",
        "passwordreset-emailsentusername": "Se houver um endereço de email associado a esta conta, ser-lhe-á enviada uma mensagem para redefinir a sua senha.",
-       "passwordreset-emailsent-capture": "Foi enviado um e-mail de lembrete, que é mostrado abaixo.",
-       "passwordreset-emailerror-capture": "Foi gerado um e-mail de recuperação da senha, conforme mostrado abaixo, mas o envio {{GENDER:$2|ao usuário|à usuária}} falhou. $1",
        "passwordreset-emailsent-capture2": "A redefinição da senha {{PLURAL:$1|do e-mail|dos e-mails}} foi enviada. {{PLURAL:$1|O nome de usuário e senha|A lista de nomes de usuário e senhas}} encontram-se a seguir.",
        "changeemail": "Alterar ou remover endereço de email",
        "changeemail-header": "Preencha este formulário para alterar seu endereço de e-mail. Se você gostaria de remover a associação de qualquer endereço de e-mail da sua conta, deixe o novo endereço de email em branco quando enviar o formulário.",
-       "changeemail-passwordrequired": "Você terá que digitar sua senha para confirmar esta mudança.",
        "changeemail-no-info": "Para acessar diretamente esta página você tem de estar autenticado.",
        "changeemail-oldemail": "Endereço de e-mail atual:",
        "changeemail-newemail": "Novo endereço de e-mail:",
        "undo-nochange": "Parece que a edição já foi desfeita.",
        "undo-summary": "Desfeita a edição $1 de [[Special:Contributions/$2|$2]] ([[User talk:$2|Discussão]])",
        "undo-summary-username-hidden": "Desfazer a revisão $1 de um usuário oculto",
-       "cantcreateaccounttitle": "Não é possível criar uma conta",
        "cantcreateaccount-text": "Este IP ('''$1''') foi bloqueado de criar novas contas por [[User:$3|$3]].\n\nA justificativa apresentada por $3 foi ''$2''",
        "cantcreateaccount-range-text": "A criação de conta a partir dos endereços IP no intervalo <strong>$1</strong>, que inclui o seu endereço IP (<strong>$4</strong>), foi bloqueada por [[User:$3|$3]].\n\nA razão dada por $3 é <em>$2</em>",
        "viewpagelogs": "Ver registros para esta página",
index 3a0cfb0..16842c2 100644 (file)
        "passwordreset-emailelement": "{{GENDER:$1|Utilizador|Utilizadora}}: \n$1\n\nPalavra-passe temporária: \n$2",
        "passwordreset-emailsentemail": "Se este é o endereço de correio eletrónico associado a esta conta, ser-lhe-á enviada uma palavra-passe de reposição.",
        "passwordreset-emailsentusername": "Se houver um endereço de correio eletrónico associado a esta conta, ser-lhe-á enviada uma mensagem para redefinir a sua palavra-passe.",
-       "passwordreset-emailsent-capture": "Foi enviado um correio eletrónico para recuperação da palavra-passe, que é mostrado abaixo.",
-       "passwordreset-emailerror-capture": "Foi gerado um correio eletrónico para redefinição da palavra-passe, mostrado abaixo, mas o seu envio para {{GENDER:$2|o utilizador|a utilizadora}} falhou: $1",
        "passwordreset-invalideamil": "Correio eletrónico inválido",
        "passwordreset-nodata": "Não foram fornecidos nome de utilizador(a) nem endereço de correio eletrónico",
        "changeemail": "Alterar ou remover o endereço de correio eletrónico",
        "changeemail-header": "Complete este formulário para alterar o seu endereço de correio eletrónico. Se quer eliminar a associação de qualquer endereço de correio eletrónico com a sua conta, deixe em branco o novo endereço de correio eletrónico ao submeter o formulário.",
-       "changeemail-passwordrequired": "Necessita de introduzir a sua palavra-passe para confirmar esta alteração.",
        "changeemail-no-info": "Precisa de iniciar sessão para aceder diretamente a esta página.",
        "changeemail-oldemail": "Correio eletrónico atual:",
        "changeemail-newemail": "Novo endereço de correio eletrónico:",
        "undo-nochange": "A edição parece já ter sido desfeita.",
        "undo-summary": "Desfez a edição $1 de [[Special:Contributions/$2|$2]] ([[User talk:$2|Discussão]])",
        "undo-summary-username-hidden": "Desfez a edição $1 de um utilizador oculto",
-       "cantcreateaccounttitle": "Não é possível criar uma conta",
        "cantcreateaccount-text": "A criação de contas a partir deste endereço IP ('''$1''') foi bloqueada por [[User:$3|$3]].\n\nO motivo apresentado por $3 foi ''$2''",
        "cantcreateaccount-range-text": "A criação de conta a partir dos endereços IP no intervalo <strong>$1</strong>, que inclui o seu endereço IP (<strong>$4</strong>), foi bloqueada por [[User:$3|$3]].\n\nA razão dada por $3 é <em>$2</em>",
        "viewpagelogs": "Ver registos para esta página",
index 2408f24..953ebbb 100644 (file)
        "passwordreset-emailelement": "This is a body of a password reset email to allow them into the system with a new password. Parameters:\n* $1 - the user's login name. This parameter can be used for GENDER.\n* $2 - the temporary password given by the system",
        "passwordreset-emailsentemail": "Used in [[Special:PasswordReset]].\n\nSee also:\n* {{msg-mw|Passwordreset-emailsent-capture}}\n* {{msg-mw|Passwordreset-emailerror-capture}}",
        "passwordreset-emailsentusername": "Used in [[Special:PasswordReset]].\n\nSee also:\n* {{msg-mw|Passwordreset-emailsent-capture}}\n* {{msg-mw|Passwordreset-emailerror-capture}}",
-       "passwordreset-emailsent-capture": "Used in [[Special:PasswordReset]].\n\nSee also:\n* {{msg-mw|Passwordreset-emailsentemail}}\n* {{msg-mw|Passwordreset-emailsentusername}}\n* {{msg-mw|Passwordreset-emailerror-capture}}",
-       "passwordreset-emailerror-capture": "Error message displayed in [[Special:PasswordReset]] when sending an email fails. Parameters:\n* $1 - error message\n* $2 - username, used for GENDER\nSee also:\n* {{msg-mw|Passwordreset-emailsentemail}}\n* {{msg-mw|Passwordreset-emailsentusername}}\n* {{msg-mw|Passwordreset-emailsent-capture}}",
        "passwordreset-emailsent-capture2": "Used in [[Special:PasswordReset]].\n\nParameters:\n* $1 - number of accounts notified\n\nSee also:\n* {{msg-mw|Passwordreset-emailsentemail}}\n* {{msg-mw|Passwordreset-emailsentusername}}\n* {{msg-mw|Passwordreset-emailerror-capture}}",
        "passwordreset-emailerror-capture2": "Error message displayed in [[Special:PasswordReset]] when sending an email fails. Parameters:\n* $1 - error message\n* $2 - username, used for GENDER\n* $3 - number of accounts notified\n\nSee also:\n* {{msg-mw|Passwordreset-emailsentemail}}\n* {{msg-mw|Passwordreset-emailsentusername}}\n* {{msg-mw|Passwordreset-emailsent-capture}}\n* {{msg-mw|Passwordreset-emailerror-capture}}",
        "passwordreset-nocaller": "Shown when a password reset was requested but the caller was not provided. This is an internal error.",
        "changeemail": "Title of [[Special:ChangeEmail|special page]]. This page also allows removing the user's email address.",
        "changeemail-summary": "{{ignored}}",
        "changeemail-header": "Text of [[Special:ChangeEmail]].",
-       "changeemail-passwordrequired": "Shown on [[Special:ChangeEmail]] if users are required to enter their password to change their email address..",
        "changeemail-no-info": "Error message for [[Special:ChangeEmail]].\n\nParameters:\n* $1 (unused) - a link to [[Special:UserLogin]] with {{msg-mw|loginreqlink}} as link description",
        "changeemail-oldemail": "Label for e-mail address field in [[Special:ChangeEmail]].",
        "changeemail-newemail": "Label for e-mail address field in [[Special:ChangeEmail]]. See also {{msg-mw|changeemail-newemail-help}}",
        "watchthis": "Text of checkbox above {{msg-mw|Showpreview}} button in editor.\n\nSee also:\n* {{msg-mw|Watchthis}}\n* {{msg-mw|Accesskey-watch}}\n* {{msg-mw|Tooltip-watch}}\n{{Identical|Watch this page}}",
        "savearticle": "Text on the button to create a new page. It should be an action which is short and makes clear that the effect is immediate and public.\n\nSee also {{msg-mw|showpreview}} and {{msg-mw|showdiff}} for the other buttons, and {{msg-mw|savechanges}} for the label for the button when the page is being modified.\n\nSee also:\n* {{msg-mw|Accesskey-publish}}\n* {{msg-mw|Tooltip-publish}}\n{{Identical|Save page}}",
        "savechanges": "Text on the button to save the changes to an existing page. It should be an action which is short and makes clear that the effect is immediate and public.\n\nSee also {{msg-mw|showpreview}} and {{msg-mw|showdiff}} for the other buttons, and {{msg-mw|savearticle}} for the label for the button when the page is being modified.\n\nNote: This i18n is being introduced in advance of usage to provide extra time for translators.\n\nSee also:\n* {{msg-mw|Accesskey-publish}}\n* {{msg-mw|Tooltip-publish}}\n{{Identical|Save changes}}",
-       "publishpage": "పేజీని ప్రచురించు",
-       "publishchanges": "మార్పులను ప్రచురించు",
+       "publishpage": "Text on the button to create a new page on a public wiki. It should be an action which is short and makes clear that the effect is immediate and public.\n\nSee also {{msg-mw|showpreview}} and {{msg-mw|showdiff}} for the other buttons, and {{msg-mw|publishchanges}} for the label for the button when the page is being modified.\n\nNote: This i18n is being introduced in advance of usage to provide extra time for translators.\n\nSee also:\n* {{msg-mw|Accesskey-publish}}\n* {{msg-mw|Tooltip-publish}}\n{{Identical|Publish page}}",
+       "publishchanges": "Text on the button to save the changes to an existing page on a public wiki. It should be an action which is short and makes clear that the effect is immediate and public.\n\nSee also {{msg-mw|showpreview}} and {{msg-mw|showdiff}} for the other buttons, and {{msg-mw|publishchanges}} for the label for the button when the page is being created.\n\nNote: This i18n is being introduced in advance of usage to provide extra time for translators.\n\nSee also:\n* {{msg-mw|Accesskey-publish}}\n* {{msg-mw|Tooltip-publish}}\n{{Identical|Publish changes}}",
        "preview": "The title of the Preview page shown after clicking the \"Show preview\" button in the edit page. Since this is a heading, it should probably be translated as a noun and not as a verb.\n\n{{Identical|Preview}}",
        "showpreview": "The text of the button to preview the page you are editing. See also {{msg-mw|showdiff}} and {{msg-mw|savearticle}} for the other buttons.\n\nSee also:\n* {{msg-mw|Showpreview}}\n* {{msg-mw|Accesskey-preview}}\n* {{msg-mw|Tooltip-preview}}\n{{Identical|Show preview}}",
        "showdiff": "Button below the edit page. See also {{msg-mw|Showpreview}} and {{msg-mw|Savearticle}} for the other buttons.\n\nSee also:\n* {{msg-mw|Showdiff}}\n* {{msg-mw|Accesskey-diff}}\n* {{msg-mw|Tooltip-diff}}\n{{Identical|Show change}}",
        "undo-nochange": "Message appears if an attempt to revert an edit by clicking the \"undo\" link results in an edit making no change to the current version of the page.\n\nSee also:\n* {{msg-mw|Undo-failure}}\n* {{msg-mw|Undo-norev}}",
        "undo-summary": "Edit summary for an undo action. Parameters:\n* $1 - revision ID\n* $2 - username\n{{Identical|Undo}}",
        "undo-summary-username-hidden": "Edit summary for an undo action where the username of the old revision is hidden.\n\nParameters:\n* $1 - the revision ID being undone\nSee also:\n* {{msg-mw|Undo-summary}}",
-       "cantcreateaccounttitle": "Used as title of the error message {{msg-mw|Cantcreateaccount-text}}.",
-       "cantcreateaccount-text": "Used as error message, with the title {{msg-mw|Cantcreateaccounttitle}}.\n* $1 - target IP address\n* $2 - reason or {{msg-mw|Blockednoreason}}\n* $3 - username\nSee also:\n* {{msg-mw|Cantcreateaccount-range-text}}",
+       "cantcreateaccount-text": "Used as error message when account creation is prevented by an IP block.\n* $1 - target IP address\n* $2 - reason or {{msg-mw|Blockednoreason}}\n* $3 - username\nSee also:\n* {{msg-mw|Cantcreateaccount-range-text}}",
        "cantcreateaccount-range-text": "Used instead of the {{msg-mw|Cantcreateaccount-text}} when the block is a range block.\n* $1 - target IP address range\n* $2 - reason or {{msg-mw|Blockednoreason}}\n* $3 - username\n* $4 - current user's IP address",
        "createaccount-hook-aborted": "Placeholder message to return with API errors on account create; passes through the message from a hook {{notranslate}}",
        "viewpagelogs": "Link displayed in history of pages",
        "uploadstash-errclear": "Used as error message in [[Special:UploadStash]].",
        "uploadstash-refresh": "Used as link text in [[Special:UploadStash]].",
        "uploadstash-thumbnail": "Used as link text in [[Special:UploadStash]].",
+       "uploadstash-exception": "Error message shown when an action related to the upload stash fails unexpectedly.\n\nParameters:\n* $1 - exception name, e.g. 'UploadStashFileNotFoundException'\n* $2 - exceptions details (always in English), e.g. 'cannot find path, or not a plain file'",
        "invalid-chunk-offset": "Error that can happen if chunks get uploaded out of order.\nAs a result of this error, clients can continue from an offset provided or restart the upload.\nUsed on [[Special:UploadWizard]].",
        "img-auth-accessdenied": "[[mw:Manual:Image Authorization|Manual:Image Authorization]]: Access Denied\n{{Identical|Access denied}}",
        "img-auth-nopathinfo": "[[mw:Manual:Image Authorization|Manual:Image Authorization]]: Missing PATH_INFO - see english description\n{{Doc-important|This is plain text. Do not use any wiki syntax.}}",
index 590fc20..2dafc36 100644 (file)
        "passwordreset-emailelement": "Nume de utilizator: \n$1\n\nParolă temporară: \n$2",
        "passwordreset-emailsentemail": "Dacă această adresă de e-mail este asociată contului dumneavoastră, atunci se va trimite un e-mail de resetare a parolei.",
        "passwordreset-emailsentusername": "Dacă există o adresă de e-mail asociată acestui nume de utilizator, atunci se va trimite un e-mail de resetare a parolei.",
-       "passwordreset-emailsent-capture": "Un mesaj de resetare a parolei a fost trimis, fiind afișat mai jos.",
-       "passwordreset-emailerror-capture": "Un mesaj de resetare a parolei a fost generat (fiind afișat mai jos), dar trimiterea sa către {{GENDER:$2|utilizator}} a eșuat: $1",
        "passwordreset-invalideamil": "Adresă de e-mail nevalidă",
        "passwordreset-nodata": "Nu au fost furnizate un nume de utilizator sau o adresă de e-mail",
        "changeemail": "Modificare sau înlăturare adresă de e-mail",
        "changeemail-header": "Completați acest formular pentru a vă schimba adresa de e-mail. Dacă doriți să înlăturați orice asociere a unei adrese de e-mail cu contul dumneavoastră, lăsați necompletat câmpul pentru introducerea unei noi adrese de e-mail atunci când trimiteți formularul.",
-       "changeemail-passwordrequired": "Va trebui să introduceți parola pentru a confirma această schimbare.",
        "changeemail-no-info": "Trebuie să fiți autentificat pentru a accesa această pagină direct.",
        "changeemail-oldemail": "Adresa de e-mail actuală:",
        "changeemail-newemail": "Noua adresă de e-mail:",
        "undo-nochange": "Se pare că această modificare a fost deja anulată.",
        "undo-summary": "Anularea modificării $1 făcute de [[Special:Contributions/$2|$2]] ([[User talk:$2|Discuție]])",
        "undo-summary-username-hidden": "Anularea versiunii $1 a unui utilizator ascuns",
-       "cantcreateaccounttitle": "Crearea contului nu poate fi realizată",
        "cantcreateaccount-text": "Crearea de conturi de la această adresă IP ('''$1''') a fost blocată de [[User:$3|$3]].\n\nMotivul invocat de $3 este ''$2''",
        "cantcreateaccount-range-text": "Crearea de conturi de la adresele IP din gama <strong>$1</strong>, care o include și pe a dumneavoastră (<strong>$4</strong>), a fost blocată de [[User:$3|$3]].\n\nMotivul invocat de $3 este <em>$2</em>",
        "viewpagelogs": "Afișează jurnalele paginii",
index 823d0bb..a9db650 100644 (file)
        "passwordreset-emailtext-user": "L'utende $1 sus a {{SITENAME}} ave richieste 'na mail pe arrecurdarse le dettaglie d'u cunde sue pe {{SITENAME}}\n($4). {{PLURAL:$3|'U cunde utende seguende jè|le cunde utinde seguende sonde}} associate cu st'indirizze e-mail:\n\n$2\n\n{{PLURAL:$3|Sta passuord temboranèe scade|Ste passuord temboranèe scadene}}  'mbrà {{PLURAL:$5|'nu sciurne|$5 sciurne}}.\nTu avissa trasè e scacchià 'na passuord nova. Ce quacchedun'otre ha fatte sta richieste, o ce tu t'è arrecurdate 'a passuord origgenale toje, e non g'a vuè ccu cange cchiù, tu puè ignorà stu messagge e condinuà ausanne 'a passuord vecchie.",
        "passwordreset-emailelement": "Nome utende: \n$1\n\nPassuord temboranèe: \n$2",
        "passwordreset-emailsentemail": "Ce quiste jè 'n'e-mail pu cunde tune, allore 'na password azzerate ha state mannate addà.",
-       "passwordreset-emailsent-capture": "'Na e-mail pe azzeramende d'a passuord ha state mannate, ca jè fatte vedè aqquà sotte.",
-       "passwordreset-emailerror-capture": "'Na e-mail de azzeramende d'a passuord ha state generate, ca jè fatte vedè aqquà sotte, ma 'u 'nvie a {{GENDER:$2|l'utende}} ha fallite: $1",
        "changeemail": "Cange o live 'u 'ndirizze e-mail",
        "changeemail-header": "Comblete stu module pe cangià 'u 'ndirizze email. Ce tu vuè ccu live l'associazione cu ogne indirizze email da 'u cunde tune, lasse 'u 'ndirizze email vacande quanne conferme 'u module.",
        "changeemail-no-info": "Tu a essere collegate pe accedere a sta pàgene direttamende.",
        "undo-nochange": "'U cangiamende pare ca ha state già annullate.",
        "undo-summary": "Repristine 'a revisione $1 da [[Special:Contributions/$2|$2]] ([[User talk:$2|'Ngazzaminde]])",
        "undo-summary-username-hidden": "Annulle 'a revisione $1 da 'n'utende scunnute",
-       "cantcreateaccounttitle": "Non ge puè ccrejà 'nu cunde utende",
        "cantcreateaccount-text": "'A creazione d'u cunde utende da stu 'ndirizze IP ('''$1''') ha state blocchete da [[User:$3|$3]].\n\n'U mutive dete da $3 jè ''$2''",
        "cantcreateaccount-range-text": "'A crejazzione d'u cunde da l'indirizze IP jndr'à l'indervalle \"$1\", 'u quale 'nglude 'u 'ndirizze IP tune (<strong>$4</strong>), ha state bloccate da [[User:$3|$2]].",
        "viewpagelogs": "Vide l'archivie pe sta pàgene",
index 7a266a8..f7b7c94 100644 (file)
        "passwordreset-emailelement": "Имя участника: \n$1\n\nВременный пароль: \n$2",
        "passwordreset-emailsentemail": "Если это адрес электронной почты связан с вашей учётной записью, вам будет отправлено письмо для сброса пароля.",
        "passwordreset-emailsentusername": "Если есть адрес электронной почты, связанный с этим именем участника, то будет отправлено письмо для восстановления пароля.",
-       "passwordreset-emailsent-capture": "Отправлено электронное письмо с информацией о сбросе пароля, текст которого можно увидеть ниже.",
-       "passwordreset-emailerror-capture": "Было создано электронное письмо с информацией о сбросе пароля, текст которого можно увидеть ниже, однако его не удалось отправить {{GENDER:$2|участнику|участнице}} по следующей причине: $1",
        "passwordreset-emailsent-capture2": "{{PLURAL:$1|Письмо|Письма}} для сброса пароля {{PLURAL:$1|было отправлено|были отправлены}}. {{PLURAL:$1|Логин и пароль показаны|Список логинов и паролей показан}} ниже.",
        "passwordreset-emailerror-capture2": "Отправка {{GENDER:$2|участнику}} письма по электронной почте не удалась: $1 В {{PLURAL:$3|логин и пароль показаны|список логинов и паролей показан}} ниже.",
        "passwordreset-nocaller": "Должен быть предоставлен источник вызова",
        "passwordreset-nodata": "Ни имя участника, ни адрес электронной почты не были предоставлены",
        "changeemail": "Изменить или удалить адрес электронной почты",
        "changeemail-header": "Заполните эту форму, чтобы изменить свой адрес электронной почты. Если вы хотите отвязать свой адрес электронной почты от учётной записи, то при заполнении формы оставьте пустым поле нового адреса электронной почты.",
-       "changeemail-passwordrequired": "Чтобы подтвердить это изменение, вам нужно будет ввести свой пароль.",
        "changeemail-no-info": "Чтобы обращаться непосредственно к этой странице, вам следует представиться системе.",
        "changeemail-oldemail": "Текущий адрес электронной почты:",
        "changeemail-newemail": "Новый адрес электронной почты:",
        "undo-nochange": "Правка, похоже, уже была отменена.",
        "undo-summary": "Отмена правки $1, сделанной {{GENDER:$2|участником|участницей}} [[Special:Contribs/$2|$2]] ([[User talk:$2|обс.]])",
        "undo-summary-username-hidden": "Отмена правки $1, сделанной участником, чьё имя скрыто",
-       "cantcreateaccounttitle": "Невозможно создать учётную запись",
        "cantcreateaccount-text": "Создание учётных записей с этого IP-адреса ('''$1''') было заблокировано {{GENDER:$3|участником|участницей|}} [[User:$3|$3]].\n\n$3 {{GENDER:$3|указал|указала}} следующую причину: ''$2''.",
        "cantcreateaccount-range-text": "{{GENDER:$3|Участник|Участница}} [[User:$3|$3]] {{GENDER:$3|установил|установила}} запрет на создание учётных записей из диапазона IP-адресов <strong>$1</strong>, включающего ваш IP-адрес (<strong>$4</strong>). \n\nБыла указана следующая причина: $2.",
        "viewpagelogs": "Показать журналы для этой страницы",
index 39b1992..f4ff3ad 100644 (file)
        "passwordreset-emailtext-user": "$1 सदस्यः {{SITENAME}}($4) जालस्थानस्य  कृते कूटशब्दपरिवर्तनस्य विनतिम् अकरोत् । निम्न{{PLURAL:$3|सदस्यः|सदस्याः}} अनेन वि-पत्रेण सह सल्लग्नः अस्ति/सल्लग्नाः सन्ति ।\n\n$2\n\n{{PLURAL:$3|एषः अल्पकालीनकूटशब्दः|एते अल्पकालीनकूटशब्दाः}} {{PLURAL:$5|चतुर्विंशतिघण्टासु|$5 दिनेषु}} निरस्तः भविष्यति/निरस्ताः भविष्यन्ति ।\nअधुना प्रवेशं सम्प्राप्य कूटशब्दः परिवर्तनीयः एव । \n\nनिम्नकारणानि यदि सन्ति, तर्हि एनं सन्देशम् अवगण्यताम् ।\n\n१ कोऽपि अन्यः अत्र विज्ञप्तिम् अकरोत् । \n२ पूरातनः कूटशब्दः भवतः/भवत्याः स्मरणे अस्ति ।\n३ भवान्/भवती कूटशब्दं परिवर्तयितुं नेच्छिति ।",
        "passwordreset-emailelement": "सदस्यनाम : \n$1\n\nअल्पकालीनकूटशब्दः : \n$2",
        "passwordreset-emailsentemail": "परिवर्तितकूटशब्दस्य वि-पत्रं प्रेषितम् अस्ति ।",
-       "passwordreset-emailsent-capture": "परिवर्तितकूटशब्दस्य वि-पत्रं प्रेषितम् अस्ति । तत् अधः द्रष्टुं शक्यते ।",
-       "passwordreset-emailerror-capture": "परिवर्तितकूटशब्दस्य वि-पत्रं निर्मितम् अस्ति । तत् अधः द्रष्टुं शक्यते । परन्तु {{GENDER:$2|योजकाय}} प्रेषणकाले तत् निरस्तम् अभवत् : $1",
        "changeemail": "वि-पत्रसङ्केतः परिवर्त्यताम्",
        "changeemail-header": "प्रयोक्तृनाम्नः ई-पत्रसङ्केतः परिवर्त्यताम्",
        "changeemail-no-info": "एतत् पृष्ठं सम्पादयितुं प्रवेशः अनिवार्यः ।",
        "minoredit": "इदं लघु सम्पादनम्",
        "watchthis": "इदं पृष्ठं निरीक्षताम्",
        "savearticle": "पृष्ठं रक्ष्यताम्",
+       "publishpage": "पृष्ठं प्रकाश्यताम्",
+       "publishchanges": "परिवर्तनानि प्रकाश्यन्ताम्",
        "preview": "प्राग्दृश्यम्",
        "showpreview": "प्राग्दृश्यं दृश्यताम्",
        "showdiff": "परिवर्तनानि दृश्यन्ताम्",
        "undo-nochange": "पूर्वमेव एतत् सम्पादनं पूर्ववत् कृतं स्यात् ।",
        "undo-summary": "[[Special:Contributions/$2|$2]] ([[User talk:$2|talk]]) द्वारा कृता  $1 पूर्ववत्-प्रक्रिया निरस्तीक्रियताम् ।",
        "undo-summary-username-hidden": "निगूहितयोजकद्वारा कृता  $1 पूर्ववत्-प्रक्रिया निरस्तीक्रियताम् ।",
-       "cantcreateaccounttitle": "सदस्यता प्राप्तुं न शक्यते",
        "cantcreateaccount-text": "(<strong>$1</strong>) इत्यस्य संविदः (IP) कृते सदस्यता प्राप्तुं न शक्यते । कारणं [[User:$3|$3]] द्वारा सा संवित्सङ्ख्या प्रतिबन्धिता अस्ति । \n\n$3 इत्यनेन कारणं दत्तं यत्, <em>$2</em>",
        "cantcreateaccount-range-text": "सदस्यताप्राप्तेः सीमा-आक्रान्तृषु <strong>$1</strong> अन्तर्जालसंवित्सु (IP) भवतः/भवत्याः अन्तर्जालसंवद् (<strong>$4</strong>) अन्तर्भवति । अतः [[User:$3|$3]] द्वारा भवतः/भवत्याः अन्तर्जालसंविद् प्रतिबन्धिता ।\n\n$3 इत्यनेन कारणं दत्तं यत्, <em>$2</em>",
        "viewpagelogs": "अस्य पृष्ठस्य संरक्षिताऽऽवलिः (logs) दृश्यताम्",
        "tooltip-ca-nstab-category": "वर्गाणां पृष्ठं दृश्यताम्",
        "tooltip-minoredit": "लघुसम्पादनत्वेन इदं सम्पादनम् अङ्क्यताम्",
        "tooltip-save": "परिवर्तनानि रक्ष्यन्ताम्",
+       "tooltip-publish": "स्वपरिवर्तनानि प्रकश्यन्ताम्",
        "tooltip-preview": "भवता/भवत्या कृतानां परिवर्तनानां प्राग्दृश्यं दृश्यताम्, रक्षणात्पूर्वं कृपया इदम् उपयुज्यताम्।",
        "tooltip-diff": "भवता/भवत्या कृतानि परिवर्तनानि अत्र द्रष्टुं शक्यते",
        "tooltip-compareselectedversions": "पृष्ठस्य द्वयोः चितयोः आवृत्त्योः भेदः दृश्यताम्",
        "special-characters-title-endash": "en dash",
        "special-characters-title-emdash": "em dash",
        "special-characters-title-minus": "minus sign",
-       "mw-widgets-titleinput-description-new-page": "पृष्ठं न विद्यते",
-       "api-error-blacklisted": "कृपया भिन्नं विवरणपूर्वकं शीर्षकं चीयताम् ।"
+       "mw-widgets-titleinput-description-new-page": "पृष्ठं न विद्यते"
 }
index 985eaa0..152a08a 100644 (file)
        "passwordreset-emailtext-user": "Uiser $1 oan {{SITENAME}} requested ae reset o yer passwaird fer {{SITENAME}}\n($4). The follaein uiser {{PLURAL:$3|accoont is|accoonts ar}} associated wi this wab-mail address:\n\n$2\n\n{{PLURAL:$3|This temperie passwaird|Thir temperie passwairds}} will expire in {{PLURAL:$5|yin day|$5 days}}.\nYe shid log in n chuise ae new password nou. Gif some ither bodie haes makit this request, or gif ye'v mynded yer oreeginal passwaird, n ye nae langer wish tae chynge it, ye can ignore this message n continue uisin yer auld passwaird.",
        "passwordreset-emailelement": "Uisername: \n$1\n\nTemperie passwaird: \n$2",
        "passwordreset-emailsentemail": "Ae passwaird reset wab-mail haes been sent.",
-       "passwordreset-emailsent-capture": "Ae passwaird reset wab-mail haas been sent, this is shawn ablow.",
-       "passwordreset-emailerror-capture": "Ae passwaird reset wab-mail wis generated, (this is shawn ablow), but sendin it til the {{GENDER:$2|uiser}} failed: $1",
        "changeemail": "Chynge wab-mail address",
        "changeemail-header": "Chynge accoont wab-mail address",
        "changeemail-no-info": "Ye maun be loggit in tae access this page directly.",
        "undo-nochange": "The edit appears tae hae awready been ondone.",
        "undo-summary": "Ondae reveesion $1 bi [[Special:Contributions/$2|$2]] ([[User talk:$2|Tauk]])",
        "undo-summary-username-hidden": "Ondae reveesion $1 bi ae skauk't uiser",
-       "cantcreateaccounttitle": "Canna creaut accoont",
        "cantcreateaccount-text": "Accoont cræftin fae this IP address ('''$1''') haes been blockit bi [[User:$3|$3]].\n\nThe raison fer this, gien bi $3 is ''$2''",
        "cantcreateaccount-range-text": "Accoont cræftin fae IP addresses in the range <strong>$1</strong>, that inclædes yer IP address (<strong>$4</strong>), haes been blockit bi [[User:$3|$3]].\n\nThe raison gien bi $3 is <em>$2</em>",
        "viewpagelogs": "Leuk at logs fer this page",
index 4372c78..273c8a6 100644 (file)
        "minoredit": "Mažos pakeitėms",
        "watchthis": "Keravuotė ton poslapė",
        "savearticle": "Ėšsauguotė poslapi",
+       "publishpage": "Padėrbtė ton poslapi",
+       "publishchanges": "Ožrašītė poslapė pamainīmus",
        "preview": "Parveiza",
        "showpreview": "Ruodītė parveiza",
        "showdiff": "Ruodītė skėrtomus",
        "undo-success": "Keitėms gal būtė atšaukts. Prašuom patėkrėntė palīgėnėma, asonti žemiau, kū patvėrtėntomiet, kū Tamsta šėta ė nuorėt padarītė, ė tumet ėšsauguokit pakeitėmos, asontios žemiau, kū ožbėngtomiet keitėma atšaukėma.",
        "undo-failure": "Keitėms nagal būt atšaukts diel konflėktounantiu tarpėniu pakeitėmu.",
        "undo-summary": "Pargrōžėnams pakeitėms $1, padėrbts nauduotuojė [[Special:Contributions/$2|$2]] ([[User talk:$2|aptarėms]])",
-       "cantcreateaccounttitle": "Nie galam padėrbtė nauduotuojė",
        "cantcreateaccount-text": "Paskīrū kūrėma ėš šėta IP adresa ('''$1''') ožbluokava [[User:$3|$3]].\n\n$3 nuruodīta prīžastis īr ''$2''",
        "cantcreateaccount-range-text": "Nauduotuoju dėrbėms nug IP adresū <strong>$1</strong>, terp katrū prėgol ė Tamstas IP adresos (<strong>$4</strong>), bova ožgints nauduotuojė [[User:$3|$3]].\n\n$3 ožrašė tuokė dingstiː <em>$2</em>",
        "viewpagelogs": "Ruodītė ton poslapė īpatingus notėkėmus",
index c146a73..09392ad 100644 (file)
        "passwordreset-emailtext-user": "Korisnik $1 na {{SITENAME}} je zatražio resetiranje vaše lozinke/zaporke za {{SITENAME}}\n($4). Sljedeći {{PLURAL:$3|korisnički račun je|korisnički računi su}} povezani s ovom e-mail adresom:\n\n$2\n\n{{PLURAL:$3|Ova privremena lozinka|Ove privremene lozinke}} će isteći za {{PLURAL:$5|jedan dan|$5 dana}}.\nTrebate se prijaviti i odabrati novu lozinku. Ako je neko drugi napravio ovaj\nzahtjev, ili ako ste se sjetili Vaše originalne lozinke, a ne želite je više promijeniti, \nmožete zanemariti ovu poruku i nastaviti koristiti staru lozinku.",
        "passwordreset-emailelement": "Korisničko ime: \n$1\n\nPrivremena šifra: \n$2",
        "passwordreset-emailsentemail": "Ako je ovo adresa e-pošte s kojom ste registrirali ovaj račun, podsjetnik šifre/lozinke/zaporke će vam biti poslan na vašu adresu e-pošte.",
-       "passwordreset-emailsent-capture": "E-mail za resetiranje lozinke/zaporke je poslan (prikazan dolje).",
-       "passwordreset-emailerror-capture": "E-mail za resetiranje lozinke/zaporke, prikazan dolje, je poslan, ali slanje {{GENDER:$2|korisniku|korisnici|korisniku}} nije uspjelo: $1",
        "changeemail": "Promeni ili ukloni e-adresu",
        "changeemail-header": "Ispunite sljedeći formular da biste promijenili adresu e-pošte. Ako želite ukloniti postojeću adresu e-pošte s vašeg korisničkog računa, pri ispunjavanju formulara, polje nove adrese e-pošte ostavite prazno.",
-       "changeemail-passwordrequired": "Morat ćete unijeti vašu lozinku/zaporku da potvrdite ovu promjenu.",
        "changeemail-no-info": "Morate biti prijavljeni da biste izravno pristupili ovoj stranici.",
        "changeemail-oldemail": "Trenutna e-mail adresa:",
        "changeemail-newemail": "Nova e-mail adresa:",
        "undo-nochange": "Ovo je uređivanje izgleda već bilo poništeno.",
        "undo-summary": "Poništena izmjena $1 [[Special:Contribs/$2|korisnika $2]] ([[User talk:$2|razgovor]])",
        "undo-summary-username-hidden": "Poništi izmjenu $1 od skrivenog korisnika",
-       "cantcreateaccounttitle": "Nije moguće napraviti korisnički račun",
        "cantcreateaccount-text": "Pravljenje korisničkog računa sa ove IP adrese ('''$1''') je blokirano od strane [[User:$3|$3]].\n\nRazlog koji je naveo $3 je ''$2''",
        "cantcreateaccount-range-text": "Stvaranje računa od IP adresa iz pojasa<strong>$1</strong>, koji uključuje vašu IP adresu (<strong>$4</strong>), je blokirao/la [[User:$3|$3]].\n\nRazlog koji je dao/la $3 je <em>$2</em>",
        "viewpagelogs": "Pogledaj protokole ove stranice",
        "tooltip-ca-nstab-category": "Pogledajte stranicu kategorije",
        "tooltip-minoredit": "Označi ovo kao manje uređenje",
        "tooltip-save": "Spremite svoje izmjene",
+       "tooltip-publish": "Objavi svoje izmjene",
        "tooltip-preview": "Pregledajte svoje izmjene. Molimo vas da ovo koristite prije spremanja.",
        "tooltip-diff": "Prikaz izmjena koje ste napravili u tekstu",
        "tooltip-compareselectedversions": "Pogledajte pazlike između dvije selektovane verzije ove stranice.",
index 4f1d008..1142ded 100644 (file)
        "passwordreset-emailelement": "Uporabniško ime: \n$1\n\nZačasno geslo: \n$2",
        "passwordreset-emailsentemail": "Če je e-poštni naslov povezan z vašim računom, vam bomo poslali e-pošto za postavitev gesla.",
        "passwordreset-emailsentusername": "Če obstaja e-poštni naslov, povezan s tem uporabniškim imenom, vam bomo poslali e-pošto za postavitev gesla.",
-       "passwordreset-emailsent-capture": "Poslali smo e-pošto za ponastavitev gesla, ki je prikazana spodaj.",
-       "passwordreset-emailerror-capture": "Ustvarili smo e-pošto za ponastavitev gesla, ki je prikazana spodaj, vendar pa pošiljanje {{GENDER:$2|uporabniku|uporabnici}} ni uspelo: $1",
        "passwordreset-emailsent-capture2": "Poslali smo {{PLURAL:$1|e-pošto|e-pošti|e-pošte}} za ponastavitev gesla. {{PLURAL:$1|Uporabniško ime in geslo sta navedena spodaj.|Seznam uporabniških imen in gesel je naveden spodaj.}}",
        "passwordreset-emailerror-capture2": "Pošiljanje e-pošte {{GENDER:$2|uporabniku|uporabnici}} je spodletelo: $1 {{PLURAL:$3|Uporabniško ime in geslo sta navedena spodaj.|Seznam uporabniških imen in gesel je naveden spodaj.}}",
        "passwordreset-nocaller": "Podati morate klicatelja",
        "passwordreset-nodata": "Navedli niste ne uporabniškega imena ne e-poštnega naslova",
        "changeemail": "Sprememba ali odstranitev e-poštnega naslova",
        "changeemail-header": "Izpolnite obrazec za spremembo vašega e-poštnega naslova. Če želite s svojega računa odstraniti povezavo s katerim koli e-poštnim naslovom, pustite polje za nov e-poštni naslov med potrjevanje obrazca prazno.",
-       "changeemail-passwordrequired": "Za potrditev spremembe boste morali vnesti svoje geslo.",
        "changeemail-no-info": "Za neposredni dostop do strani morate biti prijavljeni.",
        "changeemail-oldemail": "Trenutni e-poštni naslov:",
        "changeemail-newemail": "Novi e-poštni naslov:",
        "undo-nochange": "Zdi se, da je urejanje nekdo že razveljavil.",
        "undo-summary": "Redakcija $1 uporabnika [[Special:Contributions/$2|$2]] ([[User talk:$2|pogovor]]) razveljavljena",
        "undo-summary-username-hidden": "Razveljavi redakcijo $1 skritega uporabnika",
-       "cantcreateaccounttitle": "Računa ni moč ustvariti",
        "cantcreateaccount-text": "Registracije z IP-naslova ('''$1''') je administrator(ka) [[User:$3|$3]] blokiral(a).\n\nRazlog, ki ga je $3 podal(a), je ''$2''.",
        "cantcreateaccount-range-text": "Ustvarjanje računov z IP-naslovov v območju <strong>$1</strong>, ki vključuje vaš IP-naslov (<strong>$4</strong>), je blokiral(-a) [[User:$3|$3]].\n\nRazlog, ki ga je podal(-a) $3, je <em>$2</em>.",
        "viewpagelogs": "Poglej dnevniške zapise o strani",
index 0d938b6..fce5916 100644 (file)
        "passwordreset-emailtext-ip": "(Qof laga yaabo in ee tahay adi, oo ka socdo ciwaanka IP'ka $1)  ayaa  codsaday xasuus faah faahin akoonkaada {{SITENAME}}\n($4). Isticmaaladaan soo socota {{PLURAL:$3|akoonkooda waxee|akoonkooda waxee}} la xiriiraan ciwaankaan e-mailka ah:\n\n$2\n\n{{PLURAL:$3|eraysirkaan kumeel gaarka ah|Eraysiryadaan kumeel gaarka ah}} waxay dhacaayaan {{PLURAL:$5|hal maalin|$5 maalmood}}.\nWaa in aad gudaha gashaa oo e-mail cusub doorataa hadda. Hadii ee qof kale codsigaan sameysay, ama hadii aad soo xasuusatay eraysirkaagii hore, oo aadna u baahneen in aad badashid, iska ilaaw fariintaan siina isticmaal eraysirkaagii duqi ahaa.",
        "passwordreset-emailtext-user": "Isticmaale $1 ee {{SITENAME}} wuxuu codsaday xasuus faah faahin akoonkaada {{SITENAME}}\n($4). Isticmaaladaan soo socota {{PLURAL:$3|akoonkooda waxee|akoonkooda waxee}} la xiriiraan ciwaankaan e-mailka ah:\n\n$2\n\n{{PLURAL:$3|eraysirkaan kumeel gaarka ah|Eraysiryadaan kumeel gaarka ah}} waxay dhacaayaan {{PLURAL:$5|hal maalin|$5 maalmood}}.\nWaa in aad gudaha gashaa oo e-mail cusub doorataa hadda. Hadii ee qof kale codsigaan sameysay, ama hadii aad soo xasuusatay eraysirkaagii hore, oo aadna u baahneen in aad badashid, iska ilaaw fariintaan siina isticmaal eraysirkaagii duqi ahaa.",
        "passwordreset-emailelement": "Magaca gudagalka: \n$1\n\nEreysirka kumeelgaarka ah: \n$2",
-       "passwordreset-emailerror-capture": "E-mail xasuus ah ayaa la sameeyay, oo ka arki kartid hoosta,laakiin wuxuu ku guul dareestay in isticmaalaha loo diro: $1",
        "changeemail": "Bedel ciwaanka E-mailka",
        "changeemail-header": "Bedel ciwaanka e-mailka akoonka",
        "changeemail-oldemail": "Ciwaanka e-mailka hadda jiro:",
        "post-expand-template-inclusion-category": "Boggaga ku xad gudbay weyninka tusmo'da",
        "post-expand-template-argument-warning": "'''Digniin:'''Boggaan waxaa ku jira ugu yaraan hal iyo wixii ka badan oo template ah, waxaana ku xiran kuwa kale.",
        "undo-summary": "Noqay bedelaadka $1 ee sameeyay  [[Special:Contributions/$2|$2]] ([[User talk:$2|hadal]])",
-       "cantcreateaccounttitle": "Ma' sameynkaro gudagal (akoon)",
        "cantcreateaccount-text": "Akoon'ka sameeyaha leh ciwaankaan  IP:ka ('''$1''') waxaa mamnuucay [[User:$3|$3]].\n\nSababta uu qoray $3 waa ''$2''",
        "viewpagelogs": "Fiiri guadagalayaasha boggaan",
        "nohistory": "Boggaan malahan taariikhda bedelaadka",
index 941db3c..02eec73 100644 (file)
        "passwordreset-emailelement": "Användarnamn: \n$1\n\nTillfälligt lösenord: \n$2",
        "passwordreset-emailsentemail": "Om denna e-postadress är associerad med ditt konto kommer en lösenordsåterställning skickas via e-post.",
        "passwordreset-emailsentusername": "Om det finns en e-postadress som associeras med detta användarnamn kommer en lösenordsåterställning skickas via e-post.",
-       "passwordreset-emailsent-capture": "En lösenordsåterställning via e-post har skickats, som visas nedan.",
-       "passwordreset-emailerror-capture": "En lösenordsåterställning via e-post har skapats, som visas nedan, men det gick inte att skicka den till {{GENDER:$2|användaren}}: $1",
        "passwordreset-emailsent-capture2": "{{PLURAL:$1|E-postmeddelande|E-postmeddelanden}} för återställning av lösenord har skickats. {{PLURAL:$1|Användarnamnet och lösenordet|Listan över användarnamn och lösenord}} visas nedan.",
        "passwordreset-emailerror-capture2": "Kunde inte skicka e-post till {{GENDER:$2|användaren}}: $1 {{PLURAL:$3|Användarnamnet och lösenordet|Listan över användarnamn och lösenord}} listas nedan.",
        "passwordreset-nocaller": "En användare måste anges",
        "passwordreset-nodata": "Varken ett användarnamn eller en e-postadress angavs",
        "changeemail": "Ändra eller ta bort e-postadress",
        "changeemail-header": "Fyll i detta formulär för att ändra din e-postadress. Lämna fältet för ny e-postadress tomt när du skickar in formuläret om du vill ta bort en associerad e-postadress från ditt konto.",
-       "changeemail-passwordrequired": "Du måste ange ditt lösenord för att bekräfta denna ändring.",
        "changeemail-no-info": "Du måste vara inloggad för att komma åt den här sidan direkt.",
        "changeemail-oldemail": "Nuvarande e-postadress:",
        "changeemail-newemail": "Ny e-postadress:",
        "undo-nochange": "Det verkar som att redigeringen redan har blivit ogjord.",
        "undo-summary": "Gör version $1 av [[Special:Contributions/$2|$2]] ([[User talk:$2|diskussion]]) ogjord",
        "undo-summary-username-hidden": "Gör version $1 av en dold användare ogjord",
-       "cantcreateaccounttitle": "Kan inte skapa konto",
        "cantcreateaccount-text": "[[User:$3|$3]] har blockerat den här IP-adressen ('''$1''') från att registrera konton.\n\nAnledningen till blockeringen var \"$2\".",
        "cantcreateaccount-range-text": "IP-adresserna i intervallet <strong>$1</strong>, som inkluderar din IP-adress (<strong>$4</strong>), har blockerats från att skapa konton av [[User:$3|$3]].\n\nAnledningen enligt $3 var <em>$2</em>",
        "viewpagelogs": "Visa loggar för denna sida",
index 3f5bf22..3685734 100644 (file)
        "passwordreset-emailtext-ip": "Ftoś (cheba Ty, s IP $1)\npado, aże chce informacyji lo konta do {{GRAMMAR:MS.lp{{SITENAME}}}} ($4).\nZe tym ausdrukym sům powjůnzane kůnta:\n$2\n\n{{PLURAL:$3|Tymczasowygo hasła|Tymczasowych hasył}} możno użyć we {{PLURAL:$5|jedyn dźyń|$5 dńi}}.\n\nJak chćołżeś gynał to zrobjyć, to zaloguj śe terozki a podej swoje hasło.\n\nJak ftoś inkszy chćoł nowe hasło abo jak Ci śe przipůmńoło stare a ńy chcysz nowygo, to zignoruj to a używej starygo hasła.",
        "passwordreset-emailelement": "Mjano sprowjorza: \n$1\n\nTymczasowe hasło: \n$2",
        "passwordreset-emailsentemail": "E-brif posłany.",
-       "passwordreset-emailsent-capture": "E-brif posłony, kerego widać niżej.",
-       "passwordreset-emailerror-capture": "Ńy udoło śe posłać wjadomości lo {{GENDER:$2|używocza|używoczki}}: $1",
        "changeemail": "Pomjyno ausdruka e-mail",
        "changeemail-header": "Pomjyno ausduku e-mail",
        "changeemail-no-info": "Muśisz być zalogowany, coby uzyskać bezpostrzedńi dostymp do tyj zajty.",
        "undo-failure": "Sprowjyńo ńy idźe wycofać skuli kůnflikta ze wersyjůma postrzedńimi.",
        "undo-norev": "Sprowjyńo ńy idźe cofnůńć skuli tego, co ńy istńije abo uostoło wyćepane.",
        "undo-summary": "Wycůfańy wersyji $1 naszkryflanej bez [[Special:Contributions/$2|$2]] ([[User talk:$2|godka]])",
-       "cantcreateaccounttitle": "Ńy do śe utworzić kůnta",
        "cantcreateaccount-text": "Tworzyńy kůnta s tygo adresu IP ('''$1''') uostoło zawarte bez użytkowńika [[User:$3|$3]].\n\nSkuli: ''$2''",
        "viewpagelogs": "Uobocz rejery uoperacyji lo tyj zajty",
        "nohistory": "Ta zajta ńy mo swojij historyje sprowjyń.",
index 1ecf70c..6ff1fdd 100644 (file)
        "passwordreset-emailtext-user": "{{SITENAME}} లోని వాడుకరి $1, {{SITENAME}} ($4) లోని మీ సంకేతపదాన్ని మార్చమంటూ అడిగారు. కింది వాడుకరి {{PLURAL:$3|ఖాతా|ఖాతాలు}}\nఈ ఈమెయిలు అడ్రసుతో అనుసంధింపబడి ఉన్నాయి:\n\n$2\n\n{{PLURAL:$3|ఈ తాత్కాలిక సంకేతపదానికి|ఈ తాత్కాలిక సంకేతపదాలకు}} {{PLURAL:$5|ఒక్క రోజులో|$5 రోజుల్లో}} కాలం చెల్లుతుంది.\nఇప్పుడు మీరు లాగినై కొత్త సంకేతపదాన్ని ఎంచుకోవాల్సి ఉంటుంది. ఈ అభ్యర్ధన చేసింది మరెవరైనా అయినా, లేక మీ అసలు సంకేతపదం మీకు గుర్తొచ్చి దాన్ని మార్చాల్సిన అవసరం లేదని అనుకున్నా, మీరీ సందేశాన్ని పట్టించుకోనక్కర్లేదు. పాత సంకేతపదాన్నే వాడుకోవచ్చు.",
        "passwordreset-emailelement": "వాడుకరిపేరు: \n$1\n\nతాత్కాలిక సంకేతపదం: \n$2",
        "passwordreset-emailsentemail": "సంకేతపదం మార్పు ఈమెయిలును పంపించాం.",
-       "passwordreset-emailsent-capture": "క్రింద చూపిన సంకేతపదం మార్పు ఈమెయిలును పంపించాం.",
-       "passwordreset-emailerror-capture": "కింద చూపిన సంకేతపదం మార్పు ఈమెయిలును తయారుచేసాం. కానీ దాన్ని {{GENDER:$2|వాడుకరికి}} పంపడం విఫలమైంది: $1",
        "changeemail": "ఈ-మెయిలు చిరునామా మార్పు",
        "changeemail-header": "ఖాతా ఈ-మెయిల్ చిరునామాని మార్చండి",
        "changeemail-no-info": "ఈ పేజీని నేరుగా చూడటానికి మీరు లాగినయి వుండాలి.",
        "undo-nochange": "ఆ మార్పును ఈసరికే రద్దు చేసినట్లుగా కనిపిస్తోంది.",
        "undo-summary": "[[Special:Contributions/$2|$2]] ([[User talk:$2|చర్చ]]) యొక్క కూర్పు $1 ను రద్దుచెయ్యి",
        "undo-summary-username-hidden": "దాచబడిన వాడుకరి చేసిన కూర్పు $1 ని వెనక్కి తిప్పండి",
-       "cantcreateaccounttitle": "ఈ ఖాతా తెరవలేము",
        "cantcreateaccount-text": "ఈ ఐపీ అడ్రసు ('''$1''') నుండి ఖాతా సృష్టించడాన్ని [[User:$3|$3]] నిరోధించారు.\n\n$3 చెప్పిన కారణం: ''$2''",
        "cantcreateaccount-range-text": "<strong>$1</strong> శ్రేణిలోని IP చిరునామాల నుండి ఖాతా సృష్టించడాన్ని [[User:$3|$3]] నిషేధించారు. మీ IP చిరునామా (<strong>$4</strong>) ఈ శ్రేణిలోనే ఉంది.\n\n$3 ఇచ్చిన కారణం: <em>$2</em>",
        "viewpagelogs": "ఈ పేజీకి సంబంధించిన లాగ్‌లను చూడండి",
index 70141c2..464655a 100644 (file)
        "passwordreset-emailelement": "ชื่อผู้ใช้: \n$1\n\nรหัสผ่านชั่วคราว: \n$2",
        "passwordreset-emailsentemail": "หากที่อยู่อีเมลนี้สัมพันธ์กับบัญชีของคุณ เช่นนั้นจะส่งอีเมลตั้งรหัสผ่านใหม่",
        "passwordreset-emailsentusername": "หากมีที่อยู่อีเมลที่ลงทะเบียนไว้ด้วยกับชื่อผู้ใช้นี้ เช่นนั้นจะส่งอีเมลตั้งรหัสผ่านใหม่",
-       "passwordreset-emailsent-capture": "อีเมลตั้งรหัสผ่านใหม่ถูกส่งไปแล้ว ซึ่งแสดงด้านล่าง",
-       "passwordreset-emailerror-capture": "อีเมลตั้งรหัสผ่านใหม่ถูกสร้างขึ้นแล้ว ซึ่งแสดงด้านล่าง แต่ไม่สามารถส่งไปยัง{{GENDER:$2|ผู้ใช้}}: $1",
        "changeemail": "เปลี่ยนหรือลบที่อยู่อีเมล",
        "changeemail-header": "กรอกแบบนี้เพื่อเปลี่ยนที่อยู่อีเมลของคุณ หากคุณต้องการลบการเชื่อมโยงของที่อยู่อีเมลใด ๆ จากบัญชีของคุณ ให้เว้นที่อยู่อีเมลใหม่ว่างเมื่อส่งแบบ",
-       "changeemail-passwordrequired": "คุณจะต้องกรอกรหัสผ่านใหม่เพื่อยืนยันการเปลี่ยนแปลงนี้",
        "changeemail-no-info": "คุณจำต้องล็อกอินเพื่อเข้าถึงหน้านี้โดยตรง",
        "changeemail-oldemail": "ที่อยู่อีเมลปัจจุบัน:",
        "changeemail-newemail": "ที่อยู่อีเมลใหม่:",
        "undo-nochange": "ดูเหมือนว่าการแก้ไขดังกล่าวถูกย้อนกลับแล้ว",
        "undo-summary": "ทำกลับรุ่นแก้ไข $1 โดย [[Special:Contributions/$2|$2]] ([[User talk:$2|พูดคุย]])",
        "undo-summary-username-hidden": "ทำกลับรุ่นแก้ไข $1 โดยผู้ใช้ไม่ระบุชื่อ",
-       "cantcreateaccounttitle": "ไม่สามารถสร้างบัญชีได้",
        "cantcreateaccount-text": "การสร้างบัญชีใหม่จากที่อยู่ไอพีนี้ ('''$1''') ถูกระงับโดย [[User:$3|$3]]\n\nเหตุผลที่ $3 ให้ไว้ คือ ''$2''",
        "cantcreateaccount-range-text": "การสร้างบัญชีจากเลขที่อยู่ไอพีในช่วง <strong>$1</strong> ซึ่งรวมเลขที่อยู่ไอพีของคุณ (<strong>$4</strong>) ถูกบล็อกโดย [[User:$3|$3]] \n\nเหตุผลที่ $3 ชี้แจง คือ <em>$2</em>",
        "viewpagelogs": "ดูปูมของหน้านี้",
index 8c0ed14..c2c40dc 100644 (file)
        "passwordreset-emailelement": "Kullanıcı adı: \n$1\n\nGeçici şifre: \n$2",
        "passwordreset-emailsentemail": "Eğer bu e-posta adresi hesabınızın bağlı olduğu adres ise, bir parola sıfırlama e-postası gönderilecektir.",
        "passwordreset-emailsentusername": "Eğer bu e-posta adresi hesabınızın bağlı olduğu adres ise, bir parola sıfırlama e-postası gönderilecektir.",
-       "passwordreset-emailsent-capture": "Aşağıda gözüktüğü gibi bir parola sıfırlama e-postası gönderildi.",
-       "passwordreset-emailerror-capture": "Aşağıda gözüktüğü gibi bir parola sıfırlama e-postası oluşturuldu ancak {{GENDER:$2|kullanıcıya}} gönderme işlemi başarısız oldu: $1",
        "passwordreset-invalideamil": "Geçersiz e-posta adresi",
        "passwordreset-nodata": "Ne bir kullanıcı adı ne de bir e-posta adresi verildi.",
        "changeemail": "E-posta adresini değiştir veya çıkar",
        "changeemail-header": "E-posta adresinizi değiştirmek için bu formu doldurun. Eğer e-posta adresini hesabınızdan kaldırmak istiyorsanız formu gönderirken e-posta adresi bölümünü boş bırakın.",
-       "changeemail-passwordrequired": "Bu değişikliği onaylamak için şifrenizi girmeniz gerekir.",
        "changeemail-no-info": "Bu sayfaya doğrudan erişmek için oturum açmanız gereklidir.",
        "changeemail-oldemail": "Mevcut E-posta adresi:",
        "changeemail-newemail": "Yeni E-posta adresi:",
        "undo-nochange": "Düzeltme zaten geri alınmış.",
        "undo-summary": "$1 değişikliği [[Special:Contributions/$2|$2]] ([[User talk:$2|mesaj]]) tarafından geri alındı.",
        "undo-summary-username-hidden": "Gizli bir kullanıcı tarafından $1 sürümü geri alınıyor",
-       "cantcreateaccounttitle": "Hesap açılamıyor",
        "cantcreateaccount-text": "Bu IP adresinden ('''$1''') kullanıcı hesabı oluşturulması [[User:$3|$3]] tarafından engellenmiştir.\n\n$3 tarafından verilen sebep ''$2''",
        "cantcreateaccount-range-text": "<strong>$1</strong> aralığındaki IP'ler için hesap oluşturma [[User:$3|$3]] tarafından engellendi, bu sizin IP adresinizi de (<strong>$4</strong>) içeriyor.\n\n$3 tarafından verilen gerekçe <em>$2</em>",
        "viewpagelogs": "Bu sayfa ile ilgili kayıtları göster",
index 128db0e..0af6224 100644 (file)
        "passwordreset-emailtext-user": "{{SITENAME}} проектыннан $1 кулланучысы {{SITENAME}} ($4) проектында сезнең серсүзне искә төшерүне сорады.\n{{PLURAL:$3|1=Түбәндәге хисап язмасы|Түбәндәге хисап язмалары}} бу электрон әрҗә адресы белән бәйле:\n\n$2\n\n{{PLURAL:$3|1=Бу вакытлы серсүз|Бу вакытлы серсүзләр}} {{PLURAL:$5|$5 көн}} дәвамында эшлиячәкләр.\nСез системага керергә һәм яңа серсүз сайларга тиешсез.\nӘгәр сез серсүз сорамаган булсагыз яки элеккеге серсүзегезне искә төшерсәгез \nһәм аны үзгәртергә теләмәсәгез, бу хатка җавап бирмәгез\nһәм элеккеге серсүзегезне кулланыгыз.",
        "passwordreset-emailelement": "Кулланучы исеме: \n$1\n\nВакытлыча серсүз: \n$2",
        "passwordreset-emailsentemail": "Әгәрдә бу электрон әрҗәгез сезнең хисап язмагыз белән бәйләнгән булса,сезгә серсүзне яңарту өчен хат җибәреләчәк.",
-       "passwordreset-emailsent-capture": "Серсүзне яңарту турындагы мәгълүмәт электрон хат белән сезгә җибәрелде, аның текстын түбәндә карарга мөмкин.",
-       "passwordreset-emailerror-capture": "Серсүзне яңарту турында хәбәр итече хат ясалды, ләкин аны  {{GENDER:$2|кулланучыга}} түбәндәге сәбәп аркасында җибәре булмады: $1",
        "changeemail": "Электрон әрҗә адресын үзгәртү яисә бетерү",
        "changeemail-header": "Электрон әрҗә адресын үзгәртү өчен әлеге форманы тутырыгыз. Әгәрдә сез электрон әрҗәгезне хисап язмагыздан өзәсегез килмәсә, форманы тутырганда яңа адрес урынын буш калдырыгыз.",
-       "changeemail-passwordrequired": "Әлеге үзгәрешләрне раслау өчен, Сезгә кулланылучы серсүзне язарга кирәк.",
        "changeemail-no-info": "Бу сәхифәгә турыдан-туры мөрәҗәгать итәр өчен, сез системага керергә тиешсез",
        "changeemail-oldemail": "Хәзерге электрон әрҗә адресы:",
        "changeemail-newemail": "Яңа электрон почта адресы:",
        "undo-failure": "Аралыктагы үзгәртүләр туры килмәү сәбәпле, үзгәртүдән баш тартып булмый.",
        "undo-norev": "Үзгәртү юк яисә ул бетерелгән, шуңа аннан баш тартып булмый.",
        "undo-summary": "[[Special:Contributions/$2|$2]] кулланучысының ([[User talk:$2|бәхәс]]) $1 үзгәртүеннән баш тарту",
-       "cantcreateaccounttitle": "Хисап язмасын төзеп булмый",
        "cantcreateaccount-text": "Бу IP адресыннан (<b>$1</b>) хисап язмалары төзү тыела. Тыючы: [[User:$3|$3]].\n\n$3 күрсәткән сәбәп: ''$2''",
        "viewpagelogs": "Бу битнең көндәлекләрен карау",
        "nohistory": "Бу битнең үзгәртүләр тарихы юк.",
index 45a58d2..c0773ee 100644 (file)
        "passwordreset-emailelement": "Ім'я користувача: \n$1\n\nТимчасовий пароль: \n$2",
        "passwordreset-emailsentemail": "Якщо ця електронна адреса асоційована з вашим обліковим записом, то лист для відновлення пароля буде відправлено на неї.",
        "passwordreset-emailsentusername": "Якщо існує електронна адреса, яка асоційована з цим обліковим записом, на неї буде надіслано лист для відновлення пароля.",
-       "passwordreset-emailsent-capture": "Електронний лист скидання пароля було надіслано, як показано нижче.",
-       "passwordreset-emailerror-capture": "Електронний лист для відновлення пароля мав бути надісланий, як показано нижче, але його надсилання {{GENDER:$2|користувачеві|користувачці}} $1 не вдалося.",
        "passwordreset-emailsent-capture2": "{{PLURAL:$1|Електронний лист|Електронні листи}} скидання паролю було надіслано. {{PLURAL:$1|Ім'я користувача і пароль|Список імен користувачів і паролів}} показано нижче.",
        "passwordreset-emailerror-capture2": "Не вдалося надіслати листа {{GENDER:$2|користувачу|користувачці}}: $1 {{PLURAL:$3|Ім'я користувача і пароль|список імен користувачів і паролів}} показано нижче.",
        "passwordreset-nocaller": "Має бути надане джерело виклику",
        "passwordreset-nodata": "Не надано ні імені користувача, ні електронної адреси",
        "changeemail": "Змінити або вилучити адресу електронної пошти",
        "changeemail-header": "Заповніть цю форму, щоб змінити адресу електронної пошти. Якщо Ви хочете взагалі прибрати зв'язок свого облікового запису з адресою електронної пошти, при надсиланні форми залиште поле нової електронної адреси порожнім.",
-       "changeemail-passwordrequired": "Вам потрібно буде ввести пароль, щоб підтвердити цю зміну.",
        "changeemail-no-info": "Ви повинні увійти в систему, щоб отримати безпосередній доступ до цієї сторінки.",
        "changeemail-oldemail": "Поточна адреса електронної пошти:",
        "changeemail-newemail": "Нова адреса електронної пошти:",
        "undo-nochange": "Схоже, редагування вже було скасовано.",
        "undo-summary": "Скасування редагування № $1 користувача [[Special:Contribs/$2|$2]] ([[User talk:$2|обговорення]])",
        "undo-summary-username-hidden": "Скасувати версію $1, виконану прихованим користувачем",
-       "cantcreateaccounttitle": "Неможливо створити обліковий запис",
        "cantcreateaccount-text": "Створення облікових записів із цієї IP-адреси ('''$1''') було заблоковане [[User:$3|користувачем $3]].\n\n$3 зазначив таку причину: ''$2''",
        "cantcreateaccount-range-text": "Створення облікового запису із IP-адрес у діапазоні  <strong>$1</strong>, який включає вашу IP-адресу (<strong>$4</strong>), було заблоковано користувачем [[User:$3|$3]].\n\nКористувач $3 вказав як причину <em>$2</em>",
        "viewpagelogs": "Показати журнали для цієї сторінки",
index 882ea01..42c3a28 100644 (file)
        "passwordreset-emailtext-user": "El utente $1 da {{SITENAME}} (probabilmente ti steso) ga richiesto l'invio de na password nova par {{SITENAME}} ($4). {{PLURAL:$3|El profiło utente asocià|I profiłi utenti asociadi}} a sto indiriso de posta ełetronega łi xe:\n\n$2\n\n{{PLURAL:$3|Sta password tenporanea ła scadarà|Ste password tenporanee łe scadarà}} dopo {{PLURAL:$5|un dì|$5 dì}}.\n\nSarìa mejo acedare e deçidare na nova password sùito. Se no te si stà ti a fare ła richiesta, o se te te ghe ricordà ła password originałe e no te vołi pi canbiarla, te połi ignorare sto mesajo e continuar doparare ła to password vecia.",
        "passwordreset-emailelement": "Nome utente: \n$1\n\nPassword tenporanea: \n$2",
        "passwordreset-emailsentemail": "Xe stà invià na mail de reset password.",
-       "passwordreset-emailsent-capture": "Xe stà invià na mail de reset password: el contegù xe riportà cuà de seguito.",
-       "passwordreset-emailerror-capture": "Xe stà generà na mail de reset password, riportà cuà de seguito. L'invio a {{GENDER:$2|l'utente}} no xe riusido: $1",
        "changeemail": "Canbia indiriso de posta ełetronega",
        "changeemail-header": "Canbia el indiriso de posta ełetronega del account",
        "changeemail-no-info": "Te ghe da aver efetuà l'aceso par acedare a sta pajina diretamente.",
        "minoredit": "Segna come canbiamento picenin",
        "watchthis": "Tien d'ocio sta pagina",
        "savearticle": "Salva sta pagina",
+       "publishpage": "Pùblica la pàjina",
+       "publishchanges": "Pùblica i to canbiamenti",
        "preview": "Anteprima",
        "showpreview": "Varda anteprima",
        "showdiff": "Mostra canbiamenti",
        "undo-failure": "No se pol mìa anular la modifica, par via de un conflito con modifiche intermedie.",
        "undo-norev": "La modifica no la pode vegner anulà parché no la esiste o la xe stà scancelà.",
        "undo-summary": "Anulà la modifica $1 de [[Special:Contributions/$2|$2]] ([[User talk:$2|Discussion]] | [[Special:Contributions/$2|{{MediaWiki:Contribslink}}]])",
-       "cantcreateaccounttitle": "Inpossibile registrar l'utente",
        "cantcreateaccount-text": "La creazion de account novi a partir da sto indirizo IP ('''$1''') la xe stà blocà da [[User:$3|$3]].\n\nLa motivazion del bloco fornìa da $3 la xe sta qua: ''$2''",
        "viewpagelogs": "Varda i registri de sta pagina",
        "nohistory": "La cronołogia de łe version de sta pàxena no la xè reperibiłe.",
        "mw-widgets-dateinput-placeholder-day": "AAAA-MM-GG",
        "mw-widgets-dateinput-placeholder-month": "AAAA-MM",
        "mw-widgets-titleinput-description-redirect": "rimando a $1",
-       "api-error-blacklisted": "Par piaser siełi un titoło difarente e descritivo.",
        "randomrootpage": "Pagina raìsa caxuale"
 }
index 7551378..14059a5 100644 (file)
        "passwordreset-emailelement": "Tên người dùng: \n$1\n\nMật khẩu tạm: \n$2",
        "passwordreset-emailsentemail": "Nếu đây là đúng địa chỉ thư điện tử của tài khoản của bạn, một thư điện tử dùng để tái tạo mật khẩu sẽ được gửi cho bạn.",
        "passwordreset-emailsentusername": "Nếu một địa chỉ thư điện tử đã gắn với tên người dùng này thì một thư điện tử để đặt lại mật khẩu sẽ được gửi đến.",
-       "passwordreset-emailsent-capture": "Thư điện tử để tái tạo mật khẩu đã được gửi, nội dung như sau.",
-       "passwordreset-emailerror-capture": "Chúng tôi đã tạo thư tái tạo mật khẩu dưới đây, nhưng không thể gửi đến {{GENDER:$2}}người dùng: $1",
        "passwordreset-emailsent-capture2": "Đã gửi {{PLURAL:$1|thư điện tử|các thư điện tử}} để đặt lại mật khẩu. {{PLURAL:$1|Tên người dùng và mật khẩu|Các tên người dùng và mật khẩu}} được liệt kê dưới đây.",
        "passwordreset-emailerror-capture2": "Không gửi được thư điện tử đến {{GENDER:$2}}người dùng: $1 {{PLURAL:$3|Tên người dùng và mật khẩu|Các tên người dùng và mật khẩu}} được liệt kê dưới đây.",
        "passwordreset-nocaller": "Yêu cầu hàm gọi",
        "passwordreset-nodata": "Cả tên người dùng và địa chỉ thư điện tử bị thiếu",
        "changeemail": "Đổi hoặc gỡ địa chỉ thư điện tử",
        "changeemail-header": "Điền biểu mẫu này để đổi địa chỉ thư điện tử của bạn. Nếu bạn muốn gỡ địa chỉ thư điện tử nào khỏi tài khoản của bạn, để trống hộp địa chỉ thư điện tử mới và lưu biểu mẫu.",
-       "changeemail-passwordrequired": "Bạn sẽ cần phải nhập mật khẩu của bạn để xác nhận thay đổi này.",
        "changeemail-no-info": "Bạn phải đăng nhập mới có thể truy cập trực tiếp trang này.",
        "changeemail-oldemail": "Địa chỉ thư điện tử hiện tại:",
        "changeemail-newemail": "Địa chỉ thư điện tử mới:",
        "undo-nochange": "Hình như sửa đổi này đã được lùi lại rồi.",
        "undo-summary": "Đã lùi lại sửa đổi $1 của [[Special:Contributions/$2|$2]] ([[User talk:$2|thảo luận]])",
        "undo-summary-username-hidden": "Đã lùi lại sửa đổi $1 của một người dùng ẩn",
-       "cantcreateaccounttitle": "Không thể mở tài khoản",
        "cantcreateaccount-text": "Chức năng tài tạo khoản từ địa chỉ IP này ('''$1''') đã bị [[User:$3|$3]] cấm.\n\nLý do được $3 đưa ra là ''$2''",
        "cantcreateaccount-range-text": "[[User:$3|$3]] đã cấm các địa chỉ IP trong dãy <strong>$1</strong>, bao gồm địa chỉ IP của bạn (<strong>$4</strong>), không được mở tài khoản.\n\nLý do được đưa ra bởi $3 là <em>$2</em>",
        "viewpagelogs": "Xem nhật trình của trang này",
index 036c3e3..eb913d7 100644 (file)
        "passwordreset-emailelement": "באַניצער נאָמען: \n$1\n\nפראוויזארישער פּאַראָל: \n$2",
        "passwordreset-emailsentemail": "טאמער איז דער ע־פאסט אדרעס פארקניפט מיט אייער קאנטע, וועט מען שיקן א פאסווארט צוריקשטעלן ע-פּאָסט.",
        "passwordreset-emailsentusername": "טאמער איז פאראן אן ע־פאסט אדרעס פארקניפט מיט דעם באניצער־נאמען, וועט מען שיקן א פאסווארט צוריקשטעלן ע-פּאָסט.",
-       "passwordreset-emailsent-capture": "מען האט געשיקט א פאסווארט צוריקשטעלן בליצבריוו, וואס ווערט געוויזן אונטן.",
-       "passwordreset-emailerror-capture": "מען האט געשאפן א פאסווארט צוריקשטעלן בליצבריוו, וואס ווערט געוויזן אונטן, אבער שיקן צום {{GENDER:$2|באניצער}}איז דורכגעפאלן: $1",
        "passwordreset-nocaller": "מען דארף פֿארזארגן א רופֿער",
        "passwordreset-invalideamil": "אומגילטיקער ע־פאסט אדרעס",
        "changeemail": "ענדערן אדער אראפנעמען ע-פּאָסט אַדרעס",
        "changeemail-header": "דערגאַנצט די פֿאָרעם צו ענדערן אייער ע-פּאָסט אַדרעס .\nטאמער ווילט איר אראפנעמען די צוארדנונג פון איינעם פון אייערע ע־פאסט אדרעסן פו אייער קאנטע, לאזט ליידיג דעם נייעם ע־פאסט אדרעס ווען איר גיט איין די פֿארעם.",
-       "changeemail-passwordrequired": "איר וועט דארפן איינגעבן אייער פאסווארט צו באשטעטיגן די ענדערונג.",
        "changeemail-no-info": "איר דאַרפֿט זיין אַרײַנלאגירט צוצוקומען גלײַך צו דעם דאָזיגן בלאַט.",
        "changeemail-oldemail": "קראַנטער ע-פּאָסט אַדרעס:",
        "changeemail-newemail": "נײַער בליצפּאָסט אַדרעס:",
        "undo-nochange": "אויבערפלעכטלעך איז די רעדאקטירונג שוין געווארן אנולירט.",
        "undo-summary": "זיי מבטל רי-ווערסיע $1 פון [[Special:Contributions/$2|$2]] ([[User talk:$2|רעדן]])",
        "undo-summary-username-hidden": "זײַט מבטל ווערסיע $1 פון א באהאלטענעם באניצער",
-       "cantcreateaccounttitle": "מען קען נישט באשאפֿן קאנטע",
        "cantcreateaccount-text": "שאפֿן קאנטעס פון דעם IP אדרעס (<b>$1</b>) איז געווארן בלאקירט דורך [[User:$3|$3]]. די סיבה געגעבן פֿון $3 איז \"$2\".",
        "cantcreateaccount-range-text": "שאפן קאנטעס פון IP אדרעסן אינעם אפשטאנד <strong>$1</strong>, וואס נעמט אײַן אײַער IP אדרעס (<strong>$4</strong>), איז בלאקירט געווארן דורך [[User:$3|$3]].\n\nדער גרונט געגעבן פון $3 איז <em>$2</em>",
        "viewpagelogs": "װײַזן לאָג-ביכער פֿאַר דעם בלאַט",
index ba97b7c..4285cee 100644 (file)
        "passwordreset-emailtext-user": "Oníṣe $1 lórí {{SITENAME}} tọrọ àtúntò ọ̀rọ̀ìpamọ́ yín fùn {{SITENAME}} ($4). {{PLURAL:$3|Àkópamọ́|Àwọn àkópamọ́}} oníṣe ìsàlẹ̀ yìí ní ìbáṣe pọ̀ mọ́ àdírẹ̀sì e-mail yìí:\n\n$2\n\n{{PLURAL:$3|Ọ̀rọ̀ìpamọ́ onígbàdíẹ̀ yìí|Àwọn ọ̀rọ̀ìpamọ́ onígbàdíẹ̀ wọ̀nyí}} yíò dópin lẹ́yìn {{PLURAL:$5|ọjọ́ kan|ọjọ́ $5}}.\nẸ gbọ́dọ̀ lọ yan ọ̀rọ̀ìpamọ́ tuntun báyìí. Tóbá jẹ́ pé ẹ̀lòmíràn ló ṣe ìtọrọ yìí, tàbí tọ́bá jẹ́ pé ẹ ti rántí ọ̀rọ̀ìpamọ́ àtètèkọ́ṣe yín, tí ẹ kọ̀ sí fẹ́ yíipadà mọ́, ẹ lé ṣàìkàsí ìránṣẹ́ yìí, kí ẹ sì tẹ̀síwájú ní lo ọ̀rọ̀ìpamọ́ àtijọ́ yín.",
        "passwordreset-emailelement": "Orúkọ oníṣe: \n$1\n\nỌ̀rọ̀ìpamọ́ ìgbàdíẹ̀: \n$2",
        "passwordreset-emailsentemail": "E-mail àtúntò ọ̀rọ̀ìpamọ́ ti jẹ́ fífiránṣẹ́.",
-       "passwordreset-emailsent-capture": "E-mail àtúntò ọ̀rọ̀ìpamọ́ kan ti jẹ́ fífiránṣẹ́. Òhun nìyí nísàlẹ̀.",
-       "passwordreset-emailerror-capture": "E-mail ìyípadà ọ̀rọ̀ìpamọ́ jẹ́ dídá, òhun lóhàn nísàlẹ̀ yìí, sùgbọ́n ìfiránṣẹ́ rẹ̀ sí {{GENDER:$2|oníṣe}} náà kùnà: $1",
        "changeemail": "Ìyípadà àdírẹ̀sì E-mail",
        "changeemail-header": "Ìyípadà àdírẹ̀sì e-mail àkópamọ́",
        "changeemail-no-info": "Ẹ gbódọ̀ wọlé láti bósí ojúewé yìí tààrà.",
        "subject": "Orí ọ̀rọ̀/àkọlé:",
        "minoredit": "Àtúnṣe kékeré nìyí",
        "watchthis": "M'ójútó ojúewé yìí",
-       "savearticle": "Ìmúpamọ́ ojúewé",
+       "savearticle": "Ṣe àtẹ̀jáde ojú ewé",
+       "publishpage": "Ṣàtẹ̀jáde ojú ewé",
+       "publishchanges": "Ṣàtẹ̀jáde àtúnṣe",
        "preview": "Àyẹ̀wò",
        "showpreview": "Àkọ́yẹ̀wò",
        "showdiff": "Ìfihàn àwọn àtúnṣe",
        "undo-failure": "Àtúnṣe náà kò ṣe é múkúrò nítorí títakora àwọn àtúnṣe inú àrin.",
        "undo-norev": "Àtúnṣe náà kò ṣe é múkúrò nítorí pé kò sí tàbí pé ó ti jẹ́ píparẹ́.",
        "undo-summary": "Ìmúkúrò àtúnyẹ̀wò $1 ti [[Special:Contributions/$2|$2]] ([[User talk:$2|ọ̀rọ̀]])",
-       "cantcreateaccounttitle": "Ìforúkọsílẹ̀ kò se é se",
        "cantcreateaccount-text": "[[User:$3|$3]] ti dènà dídá àkópamọ́ láti orí àdírẹ́ẹ̀sì IP yìí ('''$1''').\n\nÌdí tí $3 ṣe ṣèyí ni ''$2''",
        "viewpagelogs": "Ẹ wo àkọsílẹ̀ ìṣẹ̀lẹ̀ fún ojúewé yìí",
        "nohistory": "Kò sí ìtàn àtùnṣe fún ojúewé yìí.",
        "search-external": "Àwárí lóde",
        "searchdisabled": "Ṣíṣàwárí nínú {{SITENAME}} wà ní dídálẹ́kun.\nNí báyìí ná ẹ le ṣàwárí lọ́dọ̀ Google.\nÀkíyèsí pé àwọn atọ́ka wọn fún àkóónú {{SITENAME}} le mọ́ jẹ́ tuntun.",
        "search-error": "Àṣìṣe ṣẹlẹ̀ fún ìwárí: $1",
-       "preferences": "Ã\80wá»\8dn Ã¬fẹÌ\81ràn",
+       "preferences": "Ã\80wá»\8dn Ã Ã yò",
        "mypreferences": "Àwọn ìfẹ́ràn",
        "prefs-edits": "Iye àwọn àtúnṣe:",
        "prefsnologintext2": "Ẹ jọ̀wọ́ ẹ $1 láti ṣe ìyípadà àwọn ìfẹ́ràn yín.",
index 050a780..5a2986f 100644 (file)
        "passwordreset-emailtext-user": "{{SITENAME}}用戶$1請求更改閣下喺{{SITENAME}}道嘅密碼$4。同爾個電子郵件有關聯嘅用戶包括:\n\n$2\n\n{{PLURAL:$3|爾個|爾啲}}臨時密碼會喺{{$5}}日之後失效。\n\n如果係閣下自己請求改密碼嘅,請馬上登錄{{SITENAME}}並且更改密碼。如果閣下諗返起自己個密碼,或者根本無申請過改密碼嘅話,請忽略爾條訊息,繼續用返舊密碼。",
        "passwordreset-emailelement": "用戶名:\n$1\n\n臨時密碼:\n$2",
        "passwordreset-emailsentemail": "若果你個戶口有登記電郵,密碼重設電郵經已送出。",
-       "passwordreset-emailsent-capture": "密碼重設電郵經已送出,下面有顯示。",
-       "passwordreset-emailerror-capture": "密碼重設電郵經已送出,下面有顯示,但送畀{{GENDER:$2|user}}時失敗: $1",
        "changeemail": "改或者剷走電郵地址",
        "changeemail-header": "填好呢份表去改戶口電郵地址。若果你想剷走你戶口個電郵地址,填表時請將電郵地址欄留空。",
-       "changeemail-passwordrequired": "你要入密碼去確認改動。",
        "changeemail-no-info": "你一定要簽到咗去直接入來呢一版。",
        "changeemail-oldemail": "而家個電郵地址:",
        "changeemail-newemail": "新電郵地址:",
        "undo-nochange": "呢個編輯睇嚟經已一早取消咗。",
        "undo-summary": "取消由[[Special:Contributions/$2|$2]] ([[User talk:$2|對話]])所做嘅修訂 $1",
        "undo-summary-username-hidden": "取消匿埋咗嘅用戶嘅修改版本 $1",
-       "cantcreateaccounttitle": "唔可以開新戶口",
        "cantcreateaccount-text": "由呢個IP地址 ('''$1''') 開嘅新戶口已經被[[User:$3|$3]]封鎖。\n\n當中俾$3封鎖嘅原因係''$2''",
        "cantcreateaccount-range-text": "由呢個IP地址範圍<strong>$1</strong>(包括你個IP <strong>$4</strong>)開嘅新戶口已經畀[[User:$3|$3]]封鎖咗。\n\n$3畀嘅理由係<em>$2</em>",
        "viewpagelogs": "睇呢頁嘅日誌",
index 0beedc7..96f806c 100644 (file)
        "passwordreset-emailelement": "用户名:\n$1\n\n临时密码:\n$2",
        "passwordreset-emailsentemail": "如果此邮件地址与您的账户相关联的话,将发送一封密码重置邮件。",
        "passwordreset-emailsentusername": "如果有邮件地址与此用户名相关联的话,将发送一封密码重置邮件。",
-       "passwordreset-emailsent-capture": "密码重设电子邮件已发送,并在下面显示。",
-       "passwordreset-emailerror-capture": "重置密码邮件已生成,但是无法向{{GENDER:$2|下列用户}} 发送:$1",
        "passwordreset-emailsent-capture2": "密码重置{{PLURAL:$1|邮件}}已发送。{{PLURAL:$1|用户名和密码|用户名和密码列表}}在下方显示。",
        "passwordreset-emailerror-capture2": "向{{GENDER:$2|用户}}发送电子邮件失败:$1 {{PLURAL:$3|用户名和密码|用户名和密码列表}}在下方显示。",
        "passwordreset-nocaller": "必须提供一个调用方",
        "passwordreset-nodata": "用户名和电子邮件地址均未提供",
        "changeemail": "更改或移除电子邮件地址",
        "changeemail-header": "完成此表格以更改您的电子邮件地址。如果您希望从您的账户中移除任何关联的电子邮件地址,请在提交表格时将新电子邮件地址留空。",
-       "changeemail-passwordrequired": "您需要输入您的密码以确认此次更改。",
        "changeemail-no-info": "\n您必须登录以直接访问本页。",
        "changeemail-oldemail": "当前电子邮件地址:",
        "changeemail-newemail": "新的电子邮件地址:",
        "undo-nochange": "这次编辑似乎已被撤销。",
        "undo-summary": "撤销[[Special:Contributions/$2|$2]]([[User talk:$2|讨论]])的版本$1",
        "undo-summary-username-hidden": "取消由一匿名用户所作的版本$1",
-       "cantcreateaccounttitle": "无法创建账户",
        "cantcreateaccount-text": "从该IP地址(<strong>$1</strong>)创建账户已被[[User:$3|$3]]禁止。\n\n$3的理由是<em>$2</em>",
        "cantcreateaccount-range-text": "从该IP地址段<strong>$1</strong>的账户创建已被[[User:$3|$3]]禁止,而这也包括了您的IP地址(<strong>$4</strong>)。\n\n$3给出的原因是<em>$2</em>",
        "viewpagelogs": "查看该页面的日志",
index 99518b6..310d8dc 100644 (file)
        "passwordreset-emailelement": "使用者名稱:\n$1\n\n臨時密碼:\n$2",
        "passwordreset-emailsentemail": "若此確實為您帳號所登記的電子郵件地址,將會寄出重設密碼的信件給您。",
        "passwordreset-emailsentusername": "若此確實為您使用者名稱所登記的電子郵件地址,將會寄出重設密碼的信件給您。",
-       "passwordreset-emailsent-capture": "已寄出重設密碼的電子郵件,並於下方顯示。",
-       "passwordreset-emailerror-capture": "下列為重設密碼的電子郵件內容,傳送給{{GENDER:$2|使用者}}失敗:$1",
        "passwordreset-emailsent-capture2": "密碼重設{{PLURAL:$1|郵件|郵件}}已寄出,{{PLURAL:$1|使用者名稱與密碼|使用者名稱與密碼}}如下顯示。",
        "passwordreset-emailerror-capture2": "寄發電子郵件給{{GENDER:$2|使用者}}失敗:$1,{{PLURAL:$3|使用者名稱與密碼|使用者名稱與密碼}}如下顯示。",
        "passwordreset-nocaller": "必須提供 caller",
        "passwordreset-nodata": "未提供使用者名稱或是電子郵件地址",
        "changeemail": "變更或移除電子郵件地址",
        "changeemail-header": "請填寫此表單來變更您的電子郵件地址,若您想要移除您帳號所連結的所有電子郵件地址,請於新電子郵件地址欄位留空。",
-       "changeemail-passwordrequired": "您須要輸入您的密碼來確認此次變更。",
        "changeemail-no-info": "您必須登入方可直接存取此頁面。",
        "changeemail-oldemail": "目前的電子郵件地址:",
        "changeemail-newemail": "新的電子郵件地址:",
        "undo-nochange": "此編輯已被還原。",
        "undo-summary": "取消由 [[Special:Contributions/$2|$2]] ([[User talk:$2|對話]]) 所作出的修訂 $1",
        "undo-summary-username-hidden": "還原隱藏使用者的修訂 $1",
-       "cantcreateaccounttitle": "無法建立帳號",
        "cantcreateaccount-text": "自這個 IP 位址 (<strong>$1</strong>) 建立帳號已經被 [[User:$3|$3]] 封鎖。\n\n$3 封鎖的原因是 <em>$2</em>",
        "cantcreateaccount-range-text": "來自 IP 位址範圍 <strong>$1</strong>,包含您的 IP 位址 (<strong>$4</strong>) 所建立的帳號已經被 [[User:$3|$3]] 封鎖。\n\n$3 封鎖的原因是 <em>$2</em>",
        "viewpagelogs": "檢視此頁面的日誌",
diff --git a/maintenance/archives/patch-add-rc_name_type_patrolled_timestamp_index.sql b/maintenance/archives/patch-add-rc_name_type_patrolled_timestamp_index.sql
new file mode 100644 (file)
index 0000000..aa54e75
--- /dev/null
@@ -0,0 +1,2 @@
+-- @since 1.28
+CREATE INDEX /*i*/rc_name_type_patrolled_timestamp ON /*_*/recentchanges (rc_namespace, rc_type, rc_patrolled, rc_timestamp);
index a550d12..9fa6632 100644 (file)
@@ -41,8 +41,6 @@ class ChangePassword extends Maintenance {
        }
 
        public function execute() {
-               global $wgDisableAuthManager;
-
                if ( $this->hasOption( "user" ) ) {
                        $user = User::newFromName( $this->getOption( 'user' ) );
                } elseif ( $this->hasOption( "userid" ) ) {
@@ -55,17 +53,13 @@ class ChangePassword extends Maintenance {
                }
                $password = $this->getOption( 'password' );
                try {
-                       if ( $wgDisableAuthManager ) {
-                               $user->setPassword( $password );
-                       } else {
-                               $status = $user->changeAuthenticationData( [
-                                       'username' => $user->getName(),
-                                       'password' => $password,
-                                       'retype' => $password,
-                               ] );
-                               if ( !$status->isGood() ) {
-                                       throw new PasswordError( $status->getWikiText( null, null, 'en' ) );
-                               }
+                       $status = $user->changeAuthenticationData( [
+                               'username' => $user->getName(),
+                               'password' => $password,
+                               'retype' => $password,
+                       ] );
+                       if ( !$status->isGood() ) {
+                               throw new PasswordError( $status->getWikiText( null, null, 'en' ) );
                        }
                        $user->saveSettings();
                        $this->output( "Password set for " . $user->getName() . "\n" );
index e83d7c6..0554949 100644 (file)
@@ -66,7 +66,7 @@ class ConvertExtensionToRegistration extends Maintenance {
                $processor = new ReflectionClass( 'ExtensionProcessor' );
                $settings = $processor->getProperty( 'globalSettings' );
                $settings->setAccessible( true );
-               return $settings->getValue() + $this->formerGlobals;
+               return array_merge( $settings->getValue(), $this->formerGlobals );
        }
 
        public function execute() {
index 3591b9c..1872716 100644 (file)
@@ -56,8 +56,6 @@ class CreateAndPromote extends Maintenance {
        }
 
        public function execute() {
-               global $wgDisableAuthManager;
-
                $username = $this->getArg( 0 );
                $password = $this->getArg( 1 );
                $force = $this->hasOption( 'force' );
@@ -122,17 +120,13 @@ class CreateAndPromote extends Maintenance {
                if ( $password ) {
                        # Try to set the password
                        try {
-                               if ( $wgDisableAuthManager ) {
-                                       $user->setPassword( $password );
-                               } else {
-                                       $status = $user->changeAuthenticationData( [
-                                               'username' => $user->getName(),
-                                               'password' => $password,
-                                               'retype' => $password,
-                                       ] );
-                                       if ( !$status->isGood() ) {
-                                               throw new PasswordError( $status->getWikiText( null, null, 'en' ) );
-                                       }
+                               $status = $user->changeAuthenticationData( [
+                                       'username' => $user->getName(),
+                                       'password' => $password,
+                                       'retype' => $password,
+                               ] );
+                               if ( !$status->isGood() ) {
+                                       throw new PasswordError( $status->getWikiText( null, null, 'en' ) );
                                }
                                if ( $exists ) {
                                        $this->output( "Password set.\n" );
index c219b9b..50a4018 100644 (file)
@@ -32,8 +32,7 @@ class InitEditCount extends Maintenance {
                avoids locking tables or lagging slaves with large updates;
                calculates counts on a slave if possible.
 
-Background mode will be automatically used if the server is MySQL 4.0
-(which does not support subqueries) or if multiple servers are listed
+Background mode will be automatically used if multiple servers are listed
 in the load balancer, usually indicating a replication environment.' );
                $this->addDescription( 'Batch-recalculate user_editcount fields from the revision table' );
        }
@@ -46,13 +45,12 @@ in the load balancer, usually indicating a replication environment.' );
                $dbver = $dbw->getServerVersion();
 
                // Autodetect mode...
-               $backgroundMode = wfGetLB()->getServerCount() > 1 ||
-                       ( $dbw instanceof DatabaseMysql );
-
                if ( $this->hasOption( 'background' ) ) {
                        $backgroundMode = true;
                } elseif ( $this->hasOption( 'quick' ) ) {
                        $backgroundMode = false;
+               } else {
+                       $backgroundMode = wfGetLB()->getServerCount() > 1;
                }
 
                if ( $backgroundMode ) {
@@ -96,7 +94,6 @@ in the load balancer, usually indicating a replication environment.' );
                                wfWaitForSlaves();
                        }
                } else {
-                       // Subselect should work on modern MySQLs etc
                        $this->output( "Using single-query mode...\n" );
                        $sql = "UPDATE $user SET user_editcount=(SELECT COUNT(*) FROM $revision WHERE rev_user=user_id)";
                        $dbw->query( $sql );
index 48b2250..ea087a6 100644 (file)
@@ -861,6 +861,7 @@ CREATE INDEX /*i*/new_name_timestamp ON /*_*/recentchanges (rc_new,rc_namespace,
 CREATE INDEX /*i*/rc_ip ON /*_*/recentchanges (rc_ip);
 CREATE INDEX /*i*/rc_ns_usertext ON /*_*/recentchanges (rc_namespace, rc_user_text);
 CREATE INDEX /*i*/rc_user_text ON /*_*/recentchanges (rc_user_text, rc_timestamp);
+CREATE INDEX /*i*/rc_name_type_patrolled_timestamp ON /*_*/recentchanges (rc_namespace, rc_type, rc_patrolled, rc_timestamp);
 
 
 CREATE TABLE /*_*/watchlist (
diff --git a/maintenance/oracle/archives/patch-add-rc_name_type_patrolled_timestamp_index.sql b/maintenance/oracle/archives/patch-add-rc_name_type_patrolled_timestamp_index.sql
new file mode 100644 (file)
index 0000000..cd0d396
--- /dev/null
@@ -0,0 +1,4 @@
+define mw_prefix='{$wgDBprefix}';
+
+CREATE INDEX &mw_prefix.recentchanges_i08 ON &mw_prefix.recentchanges (rc_namespace, rc_type, rc_patrolled, rc_timestamp);
+
index 27c3030..d9369c9 100644 (file)
@@ -434,6 +434,7 @@ CREATE INDEX &mw_prefix.recentchanges_i04 ON &mw_prefix.recentchanges (rc_new,rc
 CREATE INDEX &mw_prefix.recentchanges_i05 ON &mw_prefix.recentchanges (rc_ip);
 CREATE INDEX &mw_prefix.recentchanges_i06 ON &mw_prefix.recentchanges (rc_namespace, rc_user_text);
 CREATE INDEX &mw_prefix.recentchanges_i07 ON &mw_prefix.recentchanges (rc_user_text, rc_timestamp);
+CREATE INDEX &mw_prefix.recentchanges_i08 ON &mw_prefix.recentchanges (rc_namespace, rc_type, rc_patrolled, rc_timestamp);
 
 CREATE TABLE &mw_prefix.watchlist (
   wl_id                     NUMBER     NOT NULL,
index 61cb198..95c87c0 100644 (file)
@@ -446,6 +446,7 @@ CREATE INDEX rc_namespace_title ON recentchanges (rc_namespace, rc_title);
 CREATE INDEX rc_cur_id          ON recentchanges (rc_cur_id);
 CREATE INDEX new_name_timestamp ON recentchanges (rc_new, rc_namespace, rc_timestamp);
 CREATE INDEX rc_ip              ON recentchanges (rc_ip);
+CREATE INDEX rc_name_type_patrolled_timestamp ON recentchanges (rc_namespace, rc_type, rc_patrolled, rc_timestamp);
 
 
 CREATE SEQUENCE watchlist_wl_id_seq;
index 5b035e1..70a26cb 100644 (file)
@@ -164,8 +164,12 @@ class PurgeChangedFiles extends Maintenance {
                                        continue;
                                }
 
-                               // Purge current version and any versions in oldimage table
+                               // Purge current version and its thumbnails
                                $file->purgeCache();
+                               // Purge the old versions and their thumbnails
+                               foreach ( $file->getHistory() as $oldFile ) {
+                                       $oldFile->purgeCache();
+                               }
 
                                if ( $logType === 'delete' ) {
                                        // If there is an orphaned storage file... delete it
index 0ea52ca..94335cf 100644 (file)
@@ -57,10 +57,8 @@ class FixBug20757 extends Maintenance {
 
                $totalRevs = $dbr->selectField( 'text', 'MAX(old_id)', false, __METHOD__ );
 
-               if ( $dbr->getType() == 'mysql' ) {
-                       // In MySQL 4.1+, the binary field old_text has a non-working LOWER() function
-                       $lowerLeft = 'LOWER(CONVERT(LEFT(old_text,22) USING latin1))';
-               }
+               // In MySQL 4.1+, the binary field old_text has a non-working LOWER() function
+               $lowerLeft = 'LOWER(CONVERT(LEFT(old_text,22) USING latin1))';
 
                while ( true ) {
                        print "ID: $startId / $totalRevs\r";
index 9c9bdfb..40506bf 100644 (file)
@@ -1136,6 +1136,7 @@ CREATE INDEX /*i*/new_name_timestamp ON /*_*/recentchanges (rc_new,rc_namespace,
 CREATE INDEX /*i*/rc_ip ON /*_*/recentchanges (rc_ip);
 CREATE INDEX /*i*/rc_ns_usertext ON /*_*/recentchanges (rc_namespace, rc_user_text);
 CREATE INDEX /*i*/rc_user_text ON /*_*/recentchanges (rc_user_text, rc_timestamp);
+CREATE INDEX /*i*/rc_name_type_patrolled_timestamp ON /*_*/recentchanges (rc_namespace, rc_type, rc_patrolled, rc_timestamp);
 
 
 CREATE TABLE /*_*/watchlist (
index 07c7d76..6c63957 100644 (file)
@@ -9,7 +9,11 @@
        $( function () {
                var idleTimeout = 3000,
                        api = new mw.Api(),
-                       pending = null,
+                       timer,
+                       pending,
+                       lastText,
+                       lastSummary,
+                       lastTextHash,
                        $form = $( '#editform' ),
                        $text = $form.find( '#wpTextbox1' ),
                        $summary = $form.find( '#wpSummary' ),
                        model = $form.find( '[name=model]' ).val(),
                        format = $form.find( '[name=format]' ).val(),
                        revId = $form.find( '[name=parentRevId]' ).val(),
-                       lastText = $text.textSelection( 'getContents' ),
-                       timer = null;
+                       lastPriority = 0,
+                       PRIORITY_LOW = 1,
+                       PRIORITY_HIGH = 2;
 
                // Send a request to stash the edit to the API.
                // If a request is in progress, abort it since its payload is stale and the API
                // may limit concurrent stash parses.
                function stashEdit() {
-                       if ( pending ) {
-                               pending.abort();
-                       }
-
                        api.getToken( 'csrf' ).then( function ( token ) {
-                               lastText = $text.textSelection( 'getContents' );
+                               var req, params,
+                                       textChanged = isTextChanged(),
+                                       priority = textChanged ? PRIORITY_HIGH : PRIORITY_LOW;
+
+                               if ( pending ) {
+                                       if ( lastPriority > priority ) {
+                                               // Stash request for summary change should wait on pending text change stash
+                                               pending.then( checkStash );
+                                               return;
+                                       }
+                                       pending.abort();
+                               }
 
-                               pending = api.post( {
+                               // Update the "last" tracking variables
+                               lastSummary = $summary.textSelection( 'getContents' );
+                               lastPriority = priority;
+                               if ( textChanged ) {
+                                       lastText = $text.textSelection( 'getContents' );
+                                       // Reset hash
+                                       lastTextHash = null;
+                               }
+
+                               params = {
                                        action: 'stashedit',
                                        token: token,
                                        title: mw.config.get( 'wgPageName' ),
                                        section: section,
                                        sectiontitle: '',
-                                       text: lastText,
-                                       summary: $summary.textSelection( 'getContents' ),
+                                       summary: lastSummary,
                                        contentmodel: model,
                                        contentformat: format,
                                        baserevid: revId
+                               };
+                               if ( lastTextHash ) {
+                                       params.stashedtexthash = lastTextHash;
+                               } else {
+                                       params.text = lastText;
+                               }
+
+                               req = api.post( params );
+                               pending = req;
+                               req.then( function ( data ) {
+                                       if ( req === pending ) {
+                                               pending = null;
+                                       }
+                                       if ( data.stashedit && data.stashedit.texthash ) {
+                                               lastTextHash = data.stashedit.texthash;
+                                       } else {
+                                               // Request failed or text hash expired;
+                                               // include the text in a future stash request.
+                                               lastTextHash = null;
+                                       }
                                } );
                        } );
                }
 
-               // Check if edit body text changed since the last stashEdit() call or if no edit
-               // stash calls have yet been made
-               function isChanged() {
-                       var newText = $text.textSelection( 'getContents' );
-                       return newText !== lastText;
+               // Whether the body text content changed since the last stashEdit()
+               function isTextChanged() {
+                       return lastText !== $text.textSelection( 'getContents' );
+               }
+
+               // Whether the edit summary has changed since the last stashEdit()
+               function isSummaryChanged() {
+                       return lastSummary !== $summary.textSelection( 'getContents' );
                }
 
-               function onEditorIdle() {
-                       if ( !isChanged() ) {
+               // Check whether text or summary have changed and call stashEdit()
+               function checkStash() {
+                       if ( !isTextChanged() && !isSummaryChanged() ) {
                                return;
                        }
 
                        stashEdit();
                }
 
-               function onTextKeyUp( e ) {
+               function onKeyUp( e ) {
                        // Ignore keystrokes that don't modify text, like cursor movements.
                        // See <http://www.javascripter.net/faq/keycodes.htm> and
                        // <http://www.quirksmode.org/js/keys.html>. We don't have to be exhaustive,
                        }
 
                        clearTimeout( timer );
-                       timer = setTimeout( onEditorIdle, idleTimeout );
+                       timer = setTimeout( checkStash, idleTimeout );
+               }
+
+               function onSummaryFocus() {
+                       // Summary typing is usually near the end of the workflow and involves less pausing.
+                       // Re-stash more frequently in hopes of capturing the final summary before submission.
+                       idleTimeout = 1000;
+                       // Stash now since the text is likely the final version. The re-stashes based on the
+                       // summary are targeted at caching edit checks that need the final summary.
+                       checkStash();
+               }
+
+               function onTextFocus() {
+                       // User returned to the text field... reset stash rate to default
+                       idleTimeout = 3000;
                }
 
                function onFormLoaded() {
                                // probably save the page soon
                                || $.inArray( $form.find( '#mw-edit-mode' ).val(), [ 'preview', 'diff' ] ) > -1
                        ) {
-                               stashEdit();
+                               checkStash();
                        }
                }
 
-               // We don't attempt to stash new section edits because in such cases
-               // the parser output varies on the edit summary (since it determines
-               // the new section's name).
+               // We don't attempt to stash new section edits because in such cases the parser output
+               // varies on the edit summary (since it determines the new section's name).
                if ( $form.find( 'input[name=wpSection]' ).val() === 'new' ) {
                        return;
                }
 
-               $text.on( { change: onEditorIdle, keyup: onTextKeyUp } );
-               $summary.on( { focus: onEditorIdle } );
+               $text.on( {
+                       change: checkStash,
+                       keyup: onKeyUp,
+                       focus: onTextFocus
+               } );
+               $summary.on( {
+                       focus: onSummaryFocus,
+                       focusout: checkStash,
+                       keyup: onKeyUp
+               } );
                onFormLoaded();
-
        } );
 }( mediaWiki, jQuery ) );
index ef4f6df..11784fb 100644 (file)
                                 * The reason css strings are not concatenated anymore is bug 31676. We now check
                                 * whether it's safe to extend the stylesheet.
                                 *
+                                * @protected
                                 * @param {Object} [messages] List of key/value pairs to be added to mw#messages.
                                 * @param {Object} [templates] List of key/value pairs to be added to mw#templates.
                                 */
                                 *         OO.compare( [ 1 ], [ 1 ] );
                                 *     } );
                                 *
+                                * Since MediaWiki 1.23 this also returns a promise.
+                                *
+                                * Since MediaWiki 1.28 the promise is resolved with a `require` function.
+                                *
                                 * @param {string|Array} dependencies Module name or array of modules names the
                                 *  callback depends on to be ready before executing
                                 * @param {Function} [ready] Callback to execute when all dependencies are ready
                                 * @param {Function} [error] Callback to execute if one or more dependencies failed
-                                * @return {jQuery.Promise}
-                                * @since 1.23 this returns a promise
+                                * @return {jQuery.Promise} With a `require` function
                                 */
                                using: function ( dependencies, ready, error ) {
                                        var deferred = $.Deferred();
                                        dependencies = resolve( dependencies );
                                        if ( allReady( dependencies ) ) {
                                                // Run ready immediately
-                                               deferred.resolve();
+                                               deferred.resolve( mw.loader.require );
                                        } else if ( anyFailed( dependencies ) ) {
                                                // Execute error immediately if any dependencies have errors
                                                deferred.reject(
                                                );
                                        } else {
                                                // Not all dependencies are ready: queue up a request
-                                               request( dependencies, deferred.resolve, deferred.reject );
+                                               request( dependencies, function () {
+                                                       deferred.resolve( mw.loader.require );
+                                               }, deferred.reject );
                                        }
 
                                        return deferred.promise();
                                 *
                                 * @protected
                                 * @since 1.27
-                                * @return {Array}
                                 */
                                require: function ( moduleName ) {
                                        var state = mw.loader.getState( moduleName );
index 155a9dd..487ab84 100644 (file)
@@ -13,8 +13,6 @@ class ApiLoginTest extends ApiTestCase {
         * Test result of attempted login with an empty username
         */
        public function testApiLoginNoName() {
-               global $wgDisableAuthManager;
-
                $session = [
                        'wsTokenSecrets' => [ 'login' => 'foobar' ],
                ];
@@ -22,11 +20,11 @@ class ApiLoginTest extends ApiTestCase {
                        'lgname' => '', 'lgpassword' => self::$users['sysop']->getPassword(),
                        'lgtoken' => (string)( new MediaWiki\Session\Token( 'foobar', '' ) )
                ], $session );
-               $this->assertEquals( $wgDisableAuthManager ? 'NoName' : 'Failed', $data[0]['login']['result'] );
+               $this->assertEquals( 'Failed', $data[0]['login']['result'] );
        }
 
        public function testApiLoginBadPass() {
-               global $wgServer, $wgDisableAuthManager;
+               global $wgServer;
 
                $user = self::$users['sysop'];
                $userName = $user->getUser()->getName();
@@ -64,7 +62,7 @@ class ApiLoginTest extends ApiTestCase {
                $this->assertNotInternalType( "bool", $result );
                $a = $result["login"]["result"];
 
-               $this->assertEquals( $wgDisableAuthManager ? 'WrongPass' : 'Failed', $a );
+               $this->assertEquals( 'Failed', $a );
        }
 
        public function testApiLoginGoodPass() {
index ac4d2c9..7e1f9d8 100644 (file)
@@ -9,7 +9,7 @@ abstract class ApiTestCase extends MediaWikiLangTestCase {
        protected $apiContext;
 
        protected function setUp() {
-               global $wgServer, $wgDisableAuthManager;
+               global $wgServer;
 
                parent::setUp();
                self::$apiUrl = $wgServer . wfScript( 'api' );
@@ -22,7 +22,7 @@ abstract class ApiTestCase extends MediaWikiLangTestCase {
                ];
 
                $this->setMwGlobals( [
-                       'wgAuth' => $wgDisableAuthManager ? new AuthPlugin : new MediaWiki\Auth\AuthManagerAuthPlugin,
+                       'wgAuth' => new MediaWiki\Auth\AuthManagerAuthPlugin,
                        'wgRequest' => new FauxRequest( [] ),
                        'wgUser' => self::$users['sysop']->getUser(),
                ] );
index 1ded0df..89e48f7 100644 (file)
@@ -7,15 +7,6 @@ namespace MediaWiki\Auth;
  * @covers MediaWiki\Auth\AbstractAuthenticationProvider
  */
 class AbstractAuthenticationProviderTest extends \MediaWikiTestCase {
-       protected function setUp() {
-               global $wgDisableAuthManager;
-
-               parent::setUp();
-               if ( $wgDisableAuthManager ) {
-                       $this->markTestSkipped( '$wgDisableAuthManager is set' );
-               }
-       }
-
        public function testAbstractAuthenticationProvider() {
                $provider = $this->getMockForAbstractClass( AbstractAuthenticationProvider::class );
                $providerPriv = \TestingAccessWrapper::newFromObject( $provider );
index ecce932..a1cdf7e 100644 (file)
@@ -7,15 +7,6 @@ namespace MediaWiki\Auth;
  * @covers MediaWiki\Auth\AbstractPasswordPrimaryAuthenticationProvider
  */
 class AbstractPasswordPrimaryAuthenticationProviderTest extends \MediaWikiTestCase {
-       protected function setUp() {
-               global $wgDisableAuthManager;
-
-               parent::setUp();
-               if ( $wgDisableAuthManager ) {
-                       $this->markTestSkipped( '$wgDisableAuthManager is set' );
-               }
-       }
-
        public function testConstructor() {
                $provider = $this->getMockForAbstractClass(
                        AbstractPasswordPrimaryAuthenticationProvider::class
index c35430e..9638451 100644 (file)
@@ -7,15 +7,6 @@ namespace MediaWiki\Auth;
  * @covers MediaWiki\Auth\AbstractPreAuthenticationProvider
  */
 class AbstractPreAuthenticationProviderTest extends \MediaWikiTestCase {
-       protected function setUp() {
-               global $wgDisableAuthManager;
-
-               parent::setUp();
-               if ( $wgDisableAuthManager ) {
-                       $this->markTestSkipped( '$wgDisableAuthManager is set' );
-               }
-       }
-
        public function testAbstractPreAuthenticationProvider() {
                $user = \User::newFromName( 'UTSysop' );
 
index 420a330..d8588d5 100644 (file)
@@ -7,15 +7,6 @@ namespace MediaWiki\Auth;
  * @covers MediaWiki\Auth\AbstractPrimaryAuthenticationProvider
  */
 class AbstractPrimaryAuthenticationProviderTest extends \MediaWikiTestCase {
-       protected function setUp() {
-               global $wgDisableAuthManager;
-
-               parent::setUp();
-               if ( $wgDisableAuthManager ) {
-                       $this->markTestSkipped( '$wgDisableAuthManager is set' );
-               }
-       }
-
        public function testAbstractPrimaryAuthenticationProvider() {
                $user = \User::newFromName( 'UTSysop' );
 
index 9cdc051..bb90dd9 100644 (file)
@@ -7,15 +7,6 @@ namespace MediaWiki\Auth;
  * @covers MediaWiki\Auth\AbstractSecondaryAuthenticationProvider
  */
 class AbstractSecondaryAuthenticationProviderTest extends \MediaWikiTestCase {
-       protected function setUp() {
-               global $wgDisableAuthManager;
-
-               parent::setUp();
-               if ( $wgDisableAuthManager ) {
-                       $this->markTestSkipped( '$wgDisableAuthManager is set' );
-               }
-       }
-
        public function testAbstractSecondaryAuthenticationProvider() {
                $user = \User::newFromName( 'UTSysop' );
 
index 82608b0..99b9029 100644 (file)
@@ -30,12 +30,7 @@ class AuthManagerTest extends \MediaWikiTestCase {
        protected $managerPriv;
 
        protected function setUp() {
-               global $wgDisableAuthManager;
-
                parent::setUp();
-               if ( $wgDisableAuthManager ) {
-                       $this->markTestSkipped( '$wgDisableAuthManager is set' );
-               }
 
                $this->setMwGlobals( [ 'wgAuth' => null ] );
                $this->stashMwGlobals( [ 'wgHooks' ] );
@@ -200,14 +195,6 @@ class AuthManagerTest extends \MediaWikiTestCase {
                        \RequestContext::getMain()->getConfig(),
                        \TestingAccessWrapper::newFromObject( $singleton )->config
                );
-
-               $this->setMwGlobals( [ 'wgDisableAuthManager' => true ] );
-               try {
-                       AuthManager::singleton();
-                       $this->fail( 'Expected exception not thrown' );
-               } catch ( \BadMethodCallException $ex ) {
-                       $this->assertSame( '$wgDisableAuthManager is set', $ex->getMessage() );
-               }
        }
 
        public function testCanAuthenticateNow() {
index 44f2743..96e50e0 100644 (file)
@@ -7,15 +7,6 @@ namespace MediaWiki\Auth;
  * @covers MediaWiki\Auth\AuthPluginPrimaryAuthenticationProvider
  */
 class AuthPluginPrimaryAuthenticationProviderTest extends \MediaWikiTestCase {
-       protected function setUp() {
-               global $wgDisableAuthManager;
-
-               parent::setUp();
-               if ( $wgDisableAuthManager ) {
-                       $this->markTestSkipped( '$wgDisableAuthManager is set' );
-               }
-       }
-
        public function testConstruction() {
                $plugin = new AuthManagerAuthPlugin();
                try {
index cac031c..a7df221 100644 (file)
@@ -7,15 +7,6 @@ namespace MediaWiki\Auth;
  * @covers MediaWiki\Auth\AuthenticationRequest
  */
 class AuthenticationRequestTest extends \MediaWikiTestCase {
-       protected function setUp() {
-               global $wgDisableAuthManager;
-
-               parent::setUp();
-               if ( $wgDisableAuthManager ) {
-                       $this->markTestSkipped( '$wgDisableAuthManager is set' );
-               }
-       }
-
        public function testBasics() {
                $mock = $this->getMockForAbstractClass( AuthenticationRequest::class );
 
index aafcd09..aa0e3c7 100644 (file)
@@ -6,15 +6,6 @@ namespace MediaWiki\Auth;
  * @group AuthManager
  */
 abstract class AuthenticationRequestTestCase extends \MediaWikiTestCase {
-       protected function setUp() {
-               global $wgDisableAuthManager;
-
-               parent::setUp();
-               if ( $wgDisableAuthManager ) {
-                       $this->markTestSkipped( '$wgDisableAuthManager is set' );
-               }
-       }
-
        abstract protected function getInstance( array $args = [] );
 
        /**
index 58ff8b6..477b161 100644 (file)
@@ -7,15 +7,6 @@ namespace MediaWiki\Auth;
  * @covers MediaWiki\Auth\AuthenticationResponse
  */
 class AuthenticationResponseTest extends \MediaWikiTestCase {
-       protected function setUp() {
-               global $wgDisableAuthManager;
-
-               parent::setUp();
-               if ( $wgDisableAuthManager ) {
-                       $this->markTestSkipped( '$wgDisableAuthManager is set' );
-               }
-       }
-
        /**
         * @dataProvider provideConstructors
         * @param string $constructor
index f2341bc..e6d3ecf 100644 (file)
@@ -8,15 +8,6 @@ namespace MediaWiki\Auth;
  * @covers MediaWiki\Auth\CheckBlocksSecondaryAuthenticationProvider
  */
 class CheckBlocksSecondaryAuthenticationProviderTest extends \MediaWikiTestCase {
-       protected function setUp() {
-               global $wgDisableAuthManager;
-
-               parent::setUp();
-               if ( $wgDisableAuthManager ) {
-                       $this->markTestSkipped( '$wgDisableAuthManager is set' );
-               }
-       }
-
        public function testConstructor() {
                $provider = new CheckBlocksSecondaryAuthenticationProvider();
                $providerPriv = \TestingAccessWrapper::newFromObject( $provider );
index 580ef6c..3fc45a4 100644 (file)
@@ -7,15 +7,6 @@ namespace MediaWiki\Auth;
  * @covers MediaWiki\Auth\ConfirmLinkSecondaryAuthenticationProvider
  */
 class ConfirmLinkSecondaryAuthenticationProviderTest extends \MediaWikiTestCase {
-       protected function setUp() {
-               global $wgDisableAuthManager;
-
-               parent::setUp();
-               if ( $wgDisableAuthManager ) {
-                       $this->markTestSkipped( '$wgDisableAuthManager is set' );
-               }
-       }
-
        /**
         * @dataProvider provideGetAuthenticationRequests
         * @param string $action
index 3548002..d482453 100644 (file)
@@ -8,15 +8,6 @@ namespace MediaWiki\Auth;
  * @covers MediaWiki\Auth\LegacyHookPreAuthenticationProvider
  */
 class LegacyHookPreAuthenticationProviderTest extends \MediaWikiTestCase {
-       protected function setUp() {
-               global $wgDisableAuthManager;
-
-               parent::setUp();
-               if ( $wgDisableAuthManager ) {
-                       $this->markTestSkipped( '$wgDisableAuthManager is set' );
-               }
-       }
-
        /**
         * Get an instance of the provider
         * @return LegacyHookPreAuthenticationProvider
index 713c27e..088dd00 100644 (file)
@@ -13,15 +13,6 @@ class LocalPasswordPrimaryAuthenticationProviderTest extends \MediaWikiTestCase
        private $config = null;
        private $validity = null;
 
-       protected function setUp() {
-               global $wgDisableAuthManager;
-
-               parent::setUp();
-               if ( $wgDisableAuthManager ) {
-                       $this->markTestSkipped( '$wgDisableAuthManager is set' );
-               }
-       }
-
        /**
         * Get an instance of the provider
         *
index 79c138b..90ed542 100644 (file)
@@ -7,15 +7,6 @@ namespace MediaWiki\Auth;
  * @covers MediaWiki\Auth\ResetPasswordSecondaryAuthenticationProvider
  */
 class ResetPasswordSecondaryAuthenticationProviderTest extends \MediaWikiTestCase {
-       protected function setUp() {
-               global $wgDisableAuthManager;
-
-               parent::setUp();
-               if ( $wgDisableAuthManager ) {
-                       $this->markTestSkipped( '$wgDisableAuthManager is set' );
-               }
-       }
-
        /**
         * @dataProvider provideGetAuthenticationRequests
         * @param string $action
index 8d0bf96..515a5b3 100644 (file)
@@ -13,15 +13,6 @@ class TemporaryPasswordPrimaryAuthenticationProviderTest extends \MediaWikiTestC
        private $config = null;
        private $validity = null;
 
-       protected function setUp() {
-               global $wgDisableAuthManager;
-
-               parent::setUp();
-               if ( $wgDisableAuthManager ) {
-                       $this->markTestSkipped( '$wgDisableAuthManager is set' );
-               }
-       }
-
        /**
         * Get an instance of the provider
         *
index 8b273b5..aa6f0e8 100644 (file)
@@ -8,15 +8,6 @@ namespace MediaWiki\Auth;
  * @covers MediaWiki\Auth\ThrottlePreAuthenticationProvider
  */
 class ThrottlePreAuthenticationProviderTest extends \MediaWikiTestCase {
-       protected function setUp() {
-               global $wgDisableAuthManager;
-
-               parent::setUp();
-               if ( $wgDisableAuthManager ) {
-                       $this->markTestSkipped( '$wgDisableAuthManager is set' );
-               }
-       }
-
        public function testConstructor() {
                $provider = new ThrottlePreAuthenticationProvider();
                $providerPriv = \TestingAccessWrapper::newFromObject( $provider );
index dba748b..5806003 100644 (file)
@@ -14,15 +14,6 @@ use Psr\Log\NullLogger;
  * @covers MediaWiki\Auth\Throttler
  */
 class ThrottlerTest extends \MediaWikiTestCase {
-       protected function setUp() {
-               global $wgDisableAuthManager;
-
-               parent::setUp();
-               if ( $wgDisableAuthManager ) {
-                       $this->markTestSkipped( '$wgDisableAuthManager is set' );
-               }
-       }
-
        public function testConstructor() {
                $cache = new \HashBagOStuff();
                $logger = $this->getMockBuilder( AbstractLogger::class )
index bb7eb79..bc7542a 100644 (file)
@@ -76,9 +76,6 @@ class FakeDatabaseMysqlBase extends DatabaseMysqlBase {
        protected function mysqlFetchField( $res, $n ) {
        }
 
-       protected function mysqlPing() {
-       }
-
        protected function mysqlRealEscapeString( $s ) {
 
        }
index e725fee..1ebb07c 100644 (file)
@@ -867,303 +867,6 @@ class SessionManagerTest extends MediaWikiTestCase {
                $this->assertTrue( SessionManager::validateSessionId( $id ), "Generated ID: $id" );
        }
 
-       public function testAutoCreateUser() {
-               global $wgGroupPermissions, $wgDisableAuthManager;
-
-               if ( !$wgDisableAuthManager ) {
-                       $this->markTestSkipped( 'AuthManager is not disabled' );
-               }
-
-               \ObjectCache::$instances[__METHOD__] = new TestBagOStuff();
-               $this->setMwGlobals( [ 'wgMainCacheType' => __METHOD__ ] );
-               $this->setMwGlobals( [
-                       'wgAuth' => new AuthPlugin,
-               ] );
-
-               $this->stashMwGlobals( [ 'wgGroupPermissions' ] );
-               $wgGroupPermissions['*']['createaccount'] = true;
-               $wgGroupPermissions['*']['autocreateaccount'] = false;
-
-               // Replace the global singleton with one configured for testing
-               $manager = $this->getManager();
-               $reset = TestUtils::setSessionManagerSingleton( $manager );
-
-               $logger = new \TestLogger( true, function ( $m ) {
-                       if ( substr( $m, 0, 15 ) === 'SessionBackend ' ) {
-                               // Don't care.
-                               return null;
-                       }
-                       $m = str_replace( 'MediaWiki\Session\SessionManager::autoCreateUser: ', '', $m );
-                       return $m;
-               } );
-               $manager->setLogger( $logger );
-
-               $session = SessionManager::getGlobalSession();
-
-               // Can't create an already-existing user
-               $user = User::newFromName( 'UTSysop' );
-               $id = $user->getId();
-               $this->assertFalse( $manager->autoCreateUser( $user ) );
-               $this->assertSame( $id, $user->getId() );
-               $this->assertSame( 'UTSysop', $user->getName() );
-               $this->assertSame( [], $logger->getBuffer() );
-               $logger->clearBuffer();
-
-               // Sanity check that creation works at all
-               $user = User::newFromName( 'UTSessionAutoCreate1' );
-               $this->assertSame( 0, $user->getId(), 'sanity check' );
-               $this->assertTrue( $manager->autoCreateUser( $user ) );
-               $this->assertNotEquals( 0, $user->getId() );
-               $this->assertSame( 'UTSessionAutoCreate1', $user->getName() );
-               $this->assertEquals(
-                       $user->getId(), User::idFromName( 'UTSessionAutoCreate1', User::READ_LATEST )
-               );
-               $this->assertSame( [
-                       [ LogLevel::INFO, 'creating new user ({username}) - from: {url}' ],
-               ], $logger->getBuffer() );
-               $logger->clearBuffer();
-
-               // Check lack of permissions
-               $wgGroupPermissions['*']['createaccount'] = false;
-               $wgGroupPermissions['*']['autocreateaccount'] = false;
-               $user = User::newFromName( 'UTDoesNotExist' );
-               $this->assertFalse( $manager->autoCreateUser( $user ) );
-               $this->assertSame( 0, $user->getId() );
-               $this->assertNotSame( 'UTDoesNotExist', $user->getName() );
-               $this->assertEquals( 0, User::idFromName( 'UTDoesNotExist', User::READ_LATEST ) );
-               $session->clear();
-               $this->assertSame( [
-                       [
-                               LogLevel::DEBUG,
-                               'user is blocked from this wiki, blacklisting',
-                       ],
-               ], $logger->getBuffer() );
-               $logger->clearBuffer();
-
-               // Check other permission
-               $wgGroupPermissions['*']['createaccount'] = false;
-               $wgGroupPermissions['*']['autocreateaccount'] = true;
-               $user = User::newFromName( 'UTSessionAutoCreate2' );
-               $this->assertSame( 0, $user->getId(), 'sanity check' );
-               $this->assertTrue( $manager->autoCreateUser( $user ) );
-               $this->assertNotEquals( 0, $user->getId() );
-               $this->assertSame( 'UTSessionAutoCreate2', $user->getName() );
-               $this->assertEquals(
-                       $user->getId(), User::idFromName( 'UTSessionAutoCreate2', User::READ_LATEST )
-               );
-               $this->assertSame( [
-                       [ LogLevel::INFO, 'creating new user ({username}) - from: {url}' ],
-               ], $logger->getBuffer() );
-               $logger->clearBuffer();
-
-               // Test account-creation block
-               $anon = new User;
-               $block = new \Block( [
-                       'address' => $anon->getName(),
-                       'user' => $id,
-                       'reason' => __METHOD__,
-                       'expiry' => time() + 100500,
-                       'createAccount' => true,
-               ] );
-               $block->insert();
-               $this->assertInstanceOf( 'Block', $anon->isBlockedFromCreateAccount(), 'sanity check' );
-               $reset2 = new \ScopedCallback( [ $block, 'delete' ] );
-               $user = User::newFromName( 'UTDoesNotExist' );
-               $this->assertFalse( $manager->autoCreateUser( $user ) );
-               $this->assertSame( 0, $user->getId() );
-               $this->assertNotSame( 'UTDoesNotExist', $user->getName() );
-               $this->assertEquals( 0, User::idFromName( 'UTDoesNotExist', User::READ_LATEST ) );
-               \ScopedCallback::consume( $reset2 );
-               $session->clear();
-               $this->assertSame( [
-                       [ LogLevel::DEBUG, 'user is blocked from this wiki, blacklisting' ],
-               ], $logger->getBuffer() );
-               $logger->clearBuffer();
-
-               // Sanity check that creation still works
-               $user = User::newFromName( 'UTSessionAutoCreate3' );
-               $this->assertSame( 0, $user->getId(), 'sanity check' );
-               $this->assertTrue( $manager->autoCreateUser( $user ) );
-               $this->assertNotEquals( 0, $user->getId() );
-               $this->assertSame( 'UTSessionAutoCreate3', $user->getName() );
-               $this->assertEquals(
-                       $user->getId(), User::idFromName( 'UTSessionAutoCreate3', User::READ_LATEST )
-               );
-               $this->assertSame( [
-                       [ LogLevel::INFO, 'creating new user ({username}) - from: {url}' ],
-               ], $logger->getBuffer() );
-               $logger->clearBuffer();
-
-               // Test prevention by AuthPlugin
-               global $wgAuth;
-               $oldWgAuth = $wgAuth;
-               $mockWgAuth = $this->getMock( 'AuthPlugin', [ 'autoCreate' ] );
-               $mockWgAuth->expects( $this->once() )->method( 'autoCreate' )
-                       ->will( $this->returnValue( false ) );
-               $this->setMwGlobals( [
-                       'wgAuth' => $mockWgAuth,
-               ] );
-               $user = User::newFromName( 'UTDoesNotExist' );
-               $this->assertFalse( $manager->autoCreateUser( $user ) );
-               $this->assertSame( 0, $user->getId() );
-               $this->assertNotSame( 'UTDoesNotExist', $user->getName() );
-               $this->assertEquals( 0, User::idFromName( 'UTDoesNotExist', User::READ_LATEST ) );
-               $this->setMwGlobals( [
-                       'wgAuth' => $oldWgAuth,
-               ] );
-               $session->clear();
-               $this->assertSame( [
-                       [ LogLevel::DEBUG, 'denied by AuthPlugin' ],
-               ], $logger->getBuffer() );
-               $logger->clearBuffer();
-
-               // Test prevention by wfReadOnly()
-               $this->setMwGlobals( [
-                       'wgReadOnly' => 'Because',
-               ] );
-               $user = User::newFromName( 'UTDoesNotExist' );
-               $this->assertFalse( $manager->autoCreateUser( $user ) );
-               $this->assertSame( 0, $user->getId() );
-               $this->assertNotSame( 'UTDoesNotExist', $user->getName() );
-               $this->assertEquals( 0, User::idFromName( 'UTDoesNotExist', User::READ_LATEST ) );
-               $this->setMwGlobals( [
-                       'wgReadOnly' => false,
-               ] );
-               $session->clear();
-               $this->assertSame( [
-                       [ LogLevel::DEBUG, 'denied by wfReadOnly()' ],
-               ], $logger->getBuffer() );
-               $logger->clearBuffer();
-
-               // Test prevention by a previous session
-               $session->set( 'MWSession::AutoCreateBlacklist', 'test' );
-               $user = User::newFromName( 'UTDoesNotExist' );
-               $this->assertFalse( $manager->autoCreateUser( $user ) );
-               $this->assertSame( 0, $user->getId() );
-               $this->assertNotSame( 'UTDoesNotExist', $user->getName() );
-               $this->assertEquals( 0, User::idFromName( 'UTDoesNotExist', User::READ_LATEST ) );
-               $session->clear();
-               $this->assertSame( [
-                       [ LogLevel::DEBUG, 'blacklisted in session (test)' ],
-               ], $logger->getBuffer() );
-               $logger->clearBuffer();
-
-               // Test uncreatable name
-               $user = User::newFromName( 'UTDoesNotExist@' );
-               $this->assertFalse( $manager->autoCreateUser( $user ) );
-               $this->assertSame( 0, $user->getId() );
-               $this->assertNotSame( 'UTDoesNotExist@', $user->getName() );
-               $this->assertEquals( 0, User::idFromName( 'UTDoesNotExist', User::READ_LATEST ) );
-               $session->clear();
-               $this->assertSame( [
-                       [ LogLevel::DEBUG, 'Invalid username, blacklisting' ],
-               ], $logger->getBuffer() );
-               $logger->clearBuffer();
-
-               // Test AbortAutoAccount hook
-               $mock = $this->getMock( __CLASS__, [ 'onAbortAutoAccount' ] );
-               $mock->expects( $this->once() )->method( 'onAbortAutoAccount' )
-                       ->will( $this->returnCallback( function ( User $user, &$msg ) {
-                               $msg = 'No way!';
-                               return false;
-                       } ) );
-               $this->mergeMwGlobalArrayValue( 'wgHooks', [ 'AbortAutoAccount' => [ $mock ] ] );
-               $user = User::newFromName( 'UTDoesNotExist' );
-               $this->assertFalse( $manager->autoCreateUser( $user ) );
-               $this->assertSame( 0, $user->getId() );
-               $this->assertNotSame( 'UTDoesNotExist', $user->getName() );
-               $this->assertEquals( 0, User::idFromName( 'UTDoesNotExist', User::READ_LATEST ) );
-               $this->mergeMwGlobalArrayValue( 'wgHooks', [ 'AbortAutoAccount' => [] ] );
-               $session->clear();
-               $this->assertSame( [
-                       [ LogLevel::DEBUG, 'denied by hook: No way!' ],
-               ], $logger->getBuffer() );
-               $logger->clearBuffer();
-
-               // Test AbortAutoAccount hook screwing up the name
-               $mock = $this->getMock( 'stdClass', [ 'onAbortAutoAccount' ] );
-               $mock->expects( $this->once() )->method( 'onAbortAutoAccount' )
-                       ->will( $this->returnCallback( function ( User $user ) {
-                               $user->setName( 'UTDoesNotExistEither' );
-                       } ) );
-               $this->mergeMwGlobalArrayValue( 'wgHooks', [ 'AbortAutoAccount' => [ $mock ] ] );
-               try {
-                       $user = User::newFromName( 'UTDoesNotExist' );
-                       $manager->autoCreateUser( $user );
-                       $this->fail( 'Expected exception not thrown' );
-               } catch ( \UnexpectedValueException $ex ) {
-                       $this->assertSame(
-                               'AbortAutoAccount hook tried to change the user name',
-                               $ex->getMessage()
-                       );
-               }
-               $this->assertSame( 0, $user->getId() );
-               $this->assertNotSame( 'UTDoesNotExist', $user->getName() );
-               $this->assertNotSame( 'UTDoesNotExistEither', $user->getName() );
-               $this->assertEquals( 0, User::idFromName( 'UTDoesNotExist', User::READ_LATEST ) );
-               $this->assertEquals( 0, User::idFromName( 'UTDoesNotExistEither', User::READ_LATEST ) );
-               $this->mergeMwGlobalArrayValue( 'wgHooks', [ 'AbortAutoAccount' => [] ] );
-               $session->clear();
-               $this->assertSame( [], $logger->getBuffer() );
-               $logger->clearBuffer();
-
-               // Test for "exception backoff"
-               $user = User::newFromName( 'UTDoesNotExist' );
-               $cache = \ObjectCache::getLocalClusterInstance();
-               $backoffKey = wfMemcKey( 'MWSession', 'autocreate-failed', md5( $user->getName() ) );
-               $cache->set( $backoffKey, 1, 60 * 10 );
-               $this->assertFalse( $manager->autoCreateUser( $user ) );
-               $this->assertSame( 0, $user->getId() );
-               $this->assertNotSame( 'UTDoesNotExist', $user->getName() );
-               $this->assertEquals( 0, User::idFromName( 'UTDoesNotExist', User::READ_LATEST ) );
-               $cache->delete( $backoffKey );
-               $session->clear();
-               $this->assertSame( [
-                       [ LogLevel::DEBUG, 'denied by prior creation attempt failures' ],
-               ], $logger->getBuffer() );
-               $logger->clearBuffer();
-
-               // Sanity check that creation still works, and test completion hook
-               $cb = $this->callback( function ( User $user ) {
-                       $this->assertNotEquals( 0, $user->getId() );
-                       $this->assertSame( 'UTSessionAutoCreate4', $user->getName() );
-                       $this->assertEquals(
-                               $user->getId(), User::idFromName( 'UTSessionAutoCreate4', User::READ_LATEST )
-                       );
-                       return true;
-               } );
-               $mock = $this->getMock( 'stdClass',
-                       [ 'onAuthPluginAutoCreate', 'onLocalUserCreated' ] );
-               $mock->expects( $this->once() )->method( 'onAuthPluginAutoCreate' )
-                       ->with( $cb );
-               $mock->expects( $this->once() )->method( 'onLocalUserCreated' )
-                       ->with( $cb, $this->identicalTo( true ) );
-               $this->mergeMwGlobalArrayValue( 'wgHooks', [
-                       'AuthPluginAutoCreate' => [ $mock ],
-                       'LocalUserCreated' => [ $mock ],
-               ] );
-               $user = User::newFromName( 'UTSessionAutoCreate4' );
-               $this->assertSame( 0, $user->getId(), 'sanity check' );
-               $this->assertTrue( $manager->autoCreateUser( $user ) );
-               $this->assertNotEquals( 0, $user->getId() );
-               $this->assertSame( 'UTSessionAutoCreate4', $user->getName() );
-               $this->assertEquals(
-                       $user->getId(),
-                       User::idFromName( 'UTSessionAutoCreate4', User::READ_LATEST )
-               );
-               $this->mergeMwGlobalArrayValue( 'wgHooks', [
-                       'AuthPluginAutoCreate' => [],
-                       'LocalUserCreated' => [],
-               ] );
-               $this->assertSame( [
-                       [ LogLevel::INFO, 'creating new user ({username}) - from: {url}' ],
-               ], $logger->getBuffer() );
-               $logger->clearBuffer();
-       }
-
-       public function onAbortAutoAccount( User $user, &$msg ) {
-       }
-
        public function testPreventSessionsForUser() {
                $manager = $this->getManager();
 
index baaa66b..a70946a 100755 (executable)
@@ -77,7 +77,7 @@ class PHPUnitMaintClass extends Maintenance {
                global $wgDevelopmentWarnings;
                global $wgSessionProviders, $wgSessionPbkdf2Iterations;
                global $wgJobTypeConf;
-               global $wgAuthManagerConfig, $wgAuth, $wgDisableAuthManager;
+               global $wgAuthManagerConfig, $wgAuth;
 
                // Inject test autoloader
                require_once __DIR__ . '/../TestsAutoLoader.php';
@@ -147,7 +147,7 @@ class PHPUnitMaintClass extends Maintenance {
                        ],
                        'secondaryauth' => [],
                ];
-               $wgAuth = $wgDisableAuthManager ? new AuthPlugin : new MediaWiki\Auth\AuthManagerAuthPlugin();
+               $wgAuth = new MediaWiki\Auth\AuthManagerAuthPlugin();
 
                // Bug 44192 Do not attempt to send a real e-mail
                Hooks::clear( 'AlternateUserMailer' );
index dd43c55..baec37c 100644 (file)
                );
        }
 
-       QUnit.asyncTest( 'mw.loader', 2, function ( assert ) {
+       QUnit.test( 'mw.loader', 2, function ( assert ) {
                var isAwesomeDone;
 
                mw.loader.testCallback = function () {
-                       QUnit.start();
                        assert.strictEqual( isAwesomeDone, undefined, 'Implementing module is.awesome: isAwesomeDone should still be undefined' );
                        isAwesomeDone = true;
                };
 
                mw.loader.implement( 'test.callback', [ QUnit.fixurl( mw.config.get( 'wgScriptPath' ) + '/tests/qunit/data/callMwLoaderTestCallback.js' ) ] );
 
-               mw.loader.using( 'test.callback', function () {
-
-                       // /sample/awesome.js declares the "mw.loader.testCallback" function
-                       // which contains a call to start() and ok()
+               return mw.loader.using( 'test.callback', function () {
                        assert.strictEqual( isAwesomeDone, true, 'test.callback module should\'ve caused isAwesomeDone to be true' );
                        delete mw.loader.testCallback;
 
                }, function () {
-                       QUnit.start();
                        assert.ok( false, 'Error callback fired while loader.using "test.callback" module' );
                } );
        } );
 
-       QUnit.asyncTest( 'mw.loader with Object method as module name', 2, function ( assert ) {
+       QUnit.test( 'mw.loader with Object method as module name', 2, function ( assert ) {
                var isAwesomeDone;
 
                mw.loader.testCallback = function () {
-                       QUnit.start();
                        assert.strictEqual( isAwesomeDone, undefined, 'Implementing module hasOwnProperty: isAwesomeDone should still be undefined' );
                        isAwesomeDone = true;
                };
 
                mw.loader.implement( 'hasOwnProperty', [ QUnit.fixurl( mw.config.get( 'wgScriptPath' ) + '/tests/qunit/data/callMwLoaderTestCallback.js' ) ], {}, {} );
 
-               mw.loader.using( 'hasOwnProperty', function () {
-
-                       // /sample/awesome.js declares the "mw.loader.testCallback" function
-                       // which contains a call to start() and ok()
+               return mw.loader.using( 'hasOwnProperty', function () {
                        assert.strictEqual( isAwesomeDone, true, 'hasOwnProperty module should\'ve caused isAwesomeDone to be true' );
                        delete mw.loader.testCallback;
 
                }, function () {
-                       QUnit.start();
                        assert.ok( false, 'Error callback fired while loader.using "hasOwnProperty" module' );
                } );
        } );
 
-       QUnit.asyncTest( 'mw.loader.using( .. ) Promise', 2, function ( assert ) {
+       QUnit.test( 'mw.loader.using( .. ) Promise', 2, function ( assert ) {
                var isAwesomeDone;
 
                mw.loader.testCallback = function () {
-                       QUnit.start();
                        assert.strictEqual( isAwesomeDone, undefined, 'Implementing module is.awesome: isAwesomeDone should still be undefined' );
                        isAwesomeDone = true;
                };
 
                mw.loader.implement( 'test.promise', [ QUnit.fixurl( mw.config.get( 'wgScriptPath' ) + '/tests/qunit/data/callMwLoaderTestCallback.js' ) ] );
 
-               mw.loader.using( 'test.promise' )
+               return mw.loader.using( 'test.promise' )
                .done( function () {
-
-                       // /sample/awesome.js declares the "mw.loader.testCallback" function
-                       // which contains a call to start() and ok()
                        assert.strictEqual( isAwesomeDone, true, 'test.promise module should\'ve caused isAwesomeDone to be true' );
                        delete mw.loader.testCallback;
 
                } )
                .fail( function () {
-                       QUnit.start();
                        assert.ok( false, 'Error callback fired while loader.using "test.promise" module' );
                } );
        } );
 
-       QUnit.asyncTest( 'mw.loader.implement( styles={ "css": [text, ..] } )', 2, function ( assert ) {
+       QUnit.test( 'mw.loader.implement( styles={ "css": [text, ..] } )', 2, function ( assert ) {
                var $element = $( '<div class="mw-test-implement-a"></div>' ).appendTo( '#qunit-fixture' );
 
                assert.notEqual(
                                        'right',
                                        'style is applied'
                                );
-                               QUnit.start();
                        },
                        {
                                all: '.mw-test-implement-a { float: right; }'
                        }
                );
 
-               mw.loader.load( [
-                       'test.implement.a'
-               ] );
+               return mw.loader.using( 'test.implement.a' );
        } );
 
-       QUnit.asyncTest( 'mw.loader.implement( styles={ "url": { <media>: [url, ..] } } )', 7, function ( assert ) {
+       QUnit.test( 'mw.loader.implement( styles={ "url": { <media>: [url, ..] } } )', 7, function ( assert ) {
                var $element1 = $( '<div class="mw-test-implement-b1"></div>' ).appendTo( '#qunit-fixture' ),
                        $element2 = $( '<div class="mw-test-implement-b2"></div>' ).appendTo( '#qunit-fixture' ),
-                       $element3 = $( '<div class="mw-test-implement-b3"></div>' ).appendTo( '#qunit-fixture' );
+                       $element3 = $( '<div class="mw-test-implement-b3"></div>' ).appendTo( '#qunit-fixture' ),
+                       done = assert.async();
 
                assert.notEqual(
                        $element1.css( 'text-align' ),
                mw.loader.implement(
                        'test.implement.b',
                        function () {
-                               // Note: QUnit.start() must only be called when the entire test is
+                               // Note: done() must only be called when the entire test is
                                // complete. So, make sure that we don't start until *both*
                                // assertStyleAsync calls have completed.
                                var pending = 2;
 
                                        pending--;
                                        if ( pending === 0 ) {
-                                               QUnit.start();
+                                               done();
                                        }
                                } );
                                assertStyleAsync( assert, $element3, 'float', 'right', function () {
 
                                        pending--;
                                        if ( pending === 0 ) {
-                                               QUnit.start();
+                                               done();
                                        }
                                } );
                        },
                        }
                );
 
-               mw.loader.load( [
-                       'test.implement.b'
-               ] );
+               mw.loader.load( 'test.implement.b' );
        } );
 
        // Backwards compatibility
-       QUnit.asyncTest( 'mw.loader.implement( styles={ <media>: text } ) (back-compat)', 2, function ( assert ) {
+       QUnit.test( 'mw.loader.implement( styles={ <media>: text } ) (back-compat)', 2, function ( assert ) {
                var $element = $( '<div class="mw-test-implement-c"></div>' ).appendTo( '#qunit-fixture' );
 
                assert.notEqual(
                                        'right',
                                        'style is applied'
                                );
-                               QUnit.start();
                        },
                        {
                                all: '.mw-test-implement-c { float: right; }'
                        }
                );
 
-               mw.loader.load( [
-                       'test.implement.c'
-               ] );
+               return mw.loader.using( 'test.implement.c' );
        } );
 
        // Backwards compatibility
-       QUnit.asyncTest( 'mw.loader.implement( styles={ <media>: [url, ..] } ) (back-compat)', 4, function ( assert ) {
+       QUnit.test( 'mw.loader.implement( styles={ <media>: [url, ..] } ) (back-compat)', 4, function ( assert ) {
                var $element = $( '<div class="mw-test-implement-d"></div>' ).appendTo( '#qunit-fixture' ),
-                       $element2 = $( '<div class="mw-test-implement-d2"></div>' ).appendTo( '#qunit-fixture' );
+                       $element2 = $( '<div class="mw-test-implement-d2"></div>' ).appendTo( '#qunit-fixture' ),
+                       done = assert.async();
 
                assert.notEqual(
                        $element.css( 'float' ),
                        'test.implement.d',
                        function () {
                                assertStyleAsync( assert, $element, 'float', 'right', function () {
-
                                        assert.notEqual( $element2.css( 'text-align' ), 'center', 'print style is not applied (bug 40500)' );
-
-                                       QUnit.start();
+                                       done();
                                } );
                        },
                        {
                        }
                );
 
-               mw.loader.load( [
-                       'test.implement.d'
-               ] );
+               mw.loader.load( 'test.implement.d' );
        } );
 
        // @import (bug 31676)
-       QUnit.asyncTest( 'mw.loader.implement( styles has @import )', 7, function ( assert ) {
-               var isJsExecuted, $element;
+       QUnit.test( 'mw.loader.implement( styles has @import )', 7, function ( assert ) {
+               var isJsExecuted, $element,
+                       done = assert.async();
 
                mw.loader.implement(
                        'test.implement.import',
                                                'CSS styles after the @import rule are working'
                                        );
 
-                                       QUnit.start();
+                                       done();
                                } );
                        },
                        {
                } );
        } );
 
-       QUnit.asyncTest( 'mw.loader.implement( dependency with styles )', 4, function ( assert ) {
+       QUnit.test( 'mw.loader.implement( dependency with styles )', 4, function ( assert ) {
                var $element = $( '<div class="mw-test-implement-e"></div>' ).appendTo( '#qunit-fixture' ),
                        $element2 = $( '<div class="mw-test-implement-e2"></div>' ).appendTo( '#qunit-fixture' );
 
                                        'right',
                                        'Depending module\'s style is applied'
                                );
-                               QUnit.start();
                        },
                        {
                                all: '.mw-test-implement-e { float: right; }'
                        }
                );
 
-               mw.loader.load( [
-                       'test.implement.e'
-               ] );
+               return mw.loader.using( 'test.implement.e' );
        } );
 
        QUnit.test( 'mw.loader.implement( only scripts )', 1, function ( assert ) {
                assert.strictEqual( mw.loader.getState( 'test.onlyscripts' ), 'ready' );
        } );
 
-       QUnit.asyncTest( 'mw.loader.implement( only messages )', 2, function ( assert ) {
+       QUnit.test( 'mw.loader.implement( only messages )', 2, function ( assert ) {
                assert.assertFalse( mw.messages.exists( 'bug_29107' ), 'Verify that the test message doesn\'t exist yet' );
 
                // jscs: disable requireCamelCaseOrUpperCaseIdentifiers
                mw.loader.implement( 'test.implement.msgs', [], {}, { bug_29107: 'loaded' } );
                // jscs: enable requireCamelCaseOrUpperCaseIdentifiers
-               mw.loader.using( 'test.implement.msgs', function () {
-                       QUnit.start();
+
+               return mw.loader.using( 'test.implement.msgs', function () {
                        assert.ok( mw.messages.exists( 'bug_29107' ), 'Bug 29107: messages-only module should implement ok' );
                }, function () {
-                       QUnit.start();
                        assert.ok( false, 'Error callback fired while implementing "test.implement.msgs" module' );
                } );
        } );
                );
        } );
 
-       QUnit.asyncTest( 'mw.loader dependency handling', 5, function ( assert ) {
+       QUnit.test( 'mw.loader dependency handling', 5, function ( assert ) {
+               var done = assert.async();
                mw.loader.register( [
                        // [module, version, dependencies, group, source]
                        [ 'testMissing', '1', [], null, 'testloader' ],
 
                                verifyModuleStates();
 
-                               QUnit.start();
+                               done();
                        },
                        function ( e, badmodules ) {
                                assert.ok( true, 'Error handler should be invoked.' );
 
                                verifyModuleStates();
 
-                               QUnit.start();
+                               done();
                        }
                );
        } );
 
-       QUnit.asyncTest( 'mw.loader skin-function handling', 5, function ( assert ) {
+       QUnit.test( 'mw.loader skin-function handling', 5, function ( assert ) {
                mw.loader.register( [
                        // [module, version, dependencies, group, source, skip]
                        [ 'testSkipped', '1', [], null, 'testloader', 'return true;' ],
                        assert.equal( mw.loader.getState( 'testUsesSkippable' ), 'ready', 'Module is ready when skippable dependencies are ready' );
                }
 
-               mw.loader.using( [ 'testUsesSkippable' ],
+               return mw.loader.using( [ 'testUsesSkippable' ],
                        function () {
                                assert.ok( true, 'Success handler should be invoked.' );
                                assert.ok( true ); // Dummy to match error handler and reach QUnit expect()
 
                                verifyModuleStates();
-
-                               QUnit.start();
                        },
                        function ( e, badmodules ) {
                                assert.ok( false, 'Error handler should not be invoked.' );
                                assert.deepEqual( badmodules, [], 'Bad modules as expected.' );
 
                                verifyModuleStates();
-
-                               QUnit.start();
                        }
                );
        } );
                mw.loader.load( target );
        } );
 
-       QUnit.asyncTest( 'mw.loader() executing race (T112232)', 2, function ( assert ) {
+       QUnit.test( 'mw.loader() executing race (T112232)', 2, function ( assert ) {
                var done = false;
 
                // The red herring schedules its CSS buffer first. In T112232, a bug in the
                );
 
                mw.loader.load( [ 'testRaceRedHerring', 'testRaceLoadMe' ] );
-               mw.loader.using( 'testRaceLoadMe', function () {
+               return mw.loader.using( 'testRaceLoadMe', function () {
                        assert.strictEqual( done, true, 'script ran' );
                        assert.strictEqual( mw.loader.getState( 'testRaceLoadMe' ), 'ready', 'state' );
-               } ).always( QUnit.start );
+               } );
        } );
 
        QUnit.test( 'mw.hook', 13, function ( assert ) {
                );
        } );
 
-       QUnit.test( 'mw.loader.require', 6, function ( assert ) {
-               var module1, module2, module3, module4;
-
+       QUnit.test( 'mw.loader require()', 6, function ( assert ) {
                mw.loader.register( [
-                       [ 'test.module.require1', '0' ],
-                       [ 'test.module.require2', '0' ],
-                       [ 'test.module.require3', '0' ],
-                       [ 'test.module.require4', '0', [ 'test.module.require3' ] ]
+                       [ 'test.require1', '0' ],
+                       [ 'test.require2', '0' ],
+                       [ 'test.require3', '0' ],
+                       [ 'test.require4', '0', [ 'test.require3' ] ]
                ] );
-               mw.loader.implement( 'test.module.require1', function () {} );
-               mw.loader.implement( 'test.module.require2', function ( $, jQuery, require, module ) {
+               mw.loader.implement( 'test.require1', function () {} );
+               mw.loader.implement( 'test.require2', function ( $, jQuery, require, module ) {
                        module.exports = 1;
                } );
-               mw.loader.implement( 'test.module.require3', function ( $, jQuery, require, module ) {
+               mw.loader.implement( 'test.require3', function ( $, jQuery, require, module ) {
                        module.exports = function () {
                                return 'hello world';
                        };
                } );
-               mw.loader.implement( 'test.module.require4', function ( $, jQuery, require, module ) {
-                       var other = require( 'test.module.require3' );
+               mw.loader.implement( 'test.require4', function ( $, jQuery, require, module ) {
+                       var other = require( 'test.require3' );
                        module.exports = {
                                pizza: function () {
                                        return other();
                                }
                        };
                } );
-               module1 = mw.loader.require( 'test.module.require1' );
-               module2 = mw.loader.require( 'test.module.require2' );
-               module3 = mw.loader.require( 'test.module.require3' );
-               module4 = mw.loader.require( 'test.module.require4' );
-
-               assert.strictEqual( typeof module1, 'object', 'export of module with no export' );
-               assert.strictEqual( module2, 1, 'export a number' );
-               assert.strictEqual( module3(), 'hello world', 'export a function' );
-               assert.strictEqual( typeof module4.pizza, 'function', 'export an object' );
-               assert.strictEqual( module4.pizza(), 'hello world', 'module can require other modules' );
-
-               assert.throws( function () {
-                       mw.loader.require( '_badmodule' );
-               }, /is not loaded/, 'Requesting non-existent modules throws error.' );
+               return mw.loader.using( [ 'test.require1', 'test.require2', 'test.require3', 'test.require4' ] )
+               .then( function ( require ) {
+                       var module1, module2, module3, module4;
+
+                       module1 = require( 'test.require1' );
+                       module2 = require( 'test.require2' );
+                       module3 = require( 'test.require3' );
+                       module4 = require( 'test.require4' );
+
+                       assert.strictEqual( typeof module1, 'object', 'export of module with no export' );
+                       assert.strictEqual( module2, 1, 'export a number' );
+                       assert.strictEqual( module3(), 'hello world', 'export a function' );
+                       assert.strictEqual( typeof module4.pizza, 'function', 'export an object' );
+                       assert.strictEqual( module4.pizza(), 'hello world', 'module can require other modules' );
+
+                       assert.throws( function () {
+                               require( '_badmodule' );
+                       }, /is not loaded/, 'Requesting non-existent modules throws error.' );
+               } );
        } );
 
-       QUnit.asyncTest( 'mw.loader require in debug mode', 1, function ( assert ) {
+       QUnit.test( 'mw.loader require() in debug mode', 1, function ( assert ) {
                var path = mw.config.get( 'wgScriptPath' );
                mw.loader.register( [
                        [ 'test.require.define', '0' ],
                mw.loader.implement( 'test.require.callback', [ QUnit.fixurl( path + '/tests/qunit/data/requireCallMwLoaderTestCallback.js' ) ] );
                mw.loader.implement( 'test.require.define', [ QUnit.fixurl( path + '/tests/qunit/data/defineCallMwLoaderTestCallback.js' ) ] );
 
-               mw.loader.using( 'test.require.callback', function () {
-                       QUnit.start();
-                       var exported = mw.loader.require( 'test.require.callback' );
+               return mw.loader.using( 'test.require.callback' ).then( function ( require ) {
+                       var exported = require( 'test.require.callback' );
                        assert.strictEqual( exported, 'Require worked.Define worked.',
                                'module.exports worked in debug mode' );
                }, function () {
-                       QUnit.start();
                        assert.ok( false, 'Error callback fired while loader.using "test.require.callback" module' );
                } );
        } );