Merge "resourceloader: Include global LESS variables in LESS cache key"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Mon, 28 May 2018 11:36:32 +0000 (11:36 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Mon, 28 May 2018 11:36:32 +0000 (11:36 +0000)
121 files changed:
.phpcs.xml
RELEASE-NOTES-1.31
RELEASE-NOTES-1.32
autoload.php
composer.json
docs/hooks.txt
docs/skin.txt
includes/AutoLoader.php
includes/DefaultSettings.php
includes/Defines.php
includes/EditPage.php
includes/GlobalFunctions.php
includes/Hooks.php
includes/PHPVersionCheck.php
includes/Preferences.php
includes/Setup.php
includes/api/ApiQuery.php
includes/api/ApiQueryUserContribs.php [new file with mode: 0644]
includes/api/ApiQueryUserContributions.php [deleted file]
includes/api/i18n/de.json
includes/api/i18n/es.json
includes/api/i18n/fr.json
includes/api/i18n/pt-br.json
includes/api/i18n/pt.json
includes/api/i18n/ru.json
includes/api/i18n/zh-hant.json
includes/auth/Throttler.php
includes/collation/IcuCollation.php
includes/compat/Timestamp.php [deleted file]
includes/compat/normal/UtfNormal.php
includes/compat/normal/UtfNormalDefines.php [deleted file]
includes/compat/normal/UtfNormalUtil.php [deleted file]
includes/installer/i18n/ar.json
includes/installer/i18n/cs.json
includes/installer/i18n/de.json
includes/installer/i18n/es.json
includes/installer/i18n/hu.json
includes/installer/i18n/pt-br.json
includes/installer/i18n/pt.json
includes/installer/i18n/sv.json
includes/libs/rdbms/database/DBConnRef.php
includes/parser/Parser.php
includes/preferences/DefaultPreferencesFactory.php
includes/resourceloader/ResourceLoader.php
includes/resourceloader/ResourceLoaderClientHtml.php
includes/skins/BaseTemplate.php
includes/skins/Skin.php
includes/specials/SpecialPreferences.php
includes/specials/SpecialVersion.php
includes/specials/forms/PreferencesForm.php [deleted file]
includes/specials/forms/PreferencesFormLegacy.php
includes/specials/forms/PreferencesFormOOUI.php
includes/utils/AutoloadGenerator.php
languages/Language.php
languages/classes/LanguageAr.php
languages/classes/LanguageMl.php
languages/data/normalize-ar.php [new file with mode: 0644]
languages/data/normalize-ml.php [new file with mode: 0644]
languages/i18n/ace.json
languages/i18n/as.json
languages/i18n/be-tarask.json
languages/i18n/bn.json
languages/i18n/ca.json
languages/i18n/ce.json
languages/i18n/cv.json
languages/i18n/da.json
languages/i18n/en-gb.json
languages/i18n/es.json
languages/i18n/eu.json
languages/i18n/fr.json
languages/i18n/hak.json
languages/i18n/he.json
languages/i18n/hu.json
languages/i18n/ia.json
languages/i18n/inh.json
languages/i18n/io.json
languages/i18n/ko.json
languages/i18n/lb.json
languages/i18n/lfn.json
languages/i18n/my.json
languages/i18n/nap.json
languages/i18n/nb.json
languages/i18n/nl.json
languages/i18n/nn.json
languages/i18n/oc.json
languages/i18n/pl.json
languages/i18n/pt-br.json
languages/i18n/pt.json
languages/i18n/qqq.json
languages/i18n/roa-tara.json
languages/i18n/ru.json
languages/i18n/sr-ec.json
languages/i18n/sr-el.json
languages/i18n/tt-cyrl.json
languages/i18n/yue.json
languages/i18n/zh-hant.json
maintenance/cleanupTitles.php
maintenance/language/generateCollationData.php
maintenance/language/generateNormalizerDataAr.php
maintenance/language/generateNormalizerDataMl.php
resources/src/mediawiki.Uri/Uri.js
resources/src/mediawiki.action/mediawiki.action.edit.stash.js
resources/src/mediawiki.legacy/oldshared.css
resources/src/mediawiki.page.gallery.js
resources/src/mediawiki.page.image.pagination.js
resources/src/mediawiki/mediawiki.js
serialized/.gitignore
serialized/Makefile
serialized/normalize-ar.ser [deleted file]
serialized/normalize-ml.ser [deleted file]
tests/parser/ParserTestRunner.php
tests/parser/parserTests.txt
tests/phpunit/data/autoloader/psr4/TestFooBar.php [new file with mode: 0644]
tests/phpunit/includes/AutoLoaderTest.php [new file with mode: 0644]
tests/phpunit/includes/HooksTest.php
tests/phpunit/includes/api/query/ApiQueryUserContribsTest.php [new file with mode: 0644]
tests/phpunit/includes/api/query/ApiQueryUserContributionsTest.php [deleted file]
tests/phpunit/includes/auth/ThrottlerTest.php
tests/phpunit/includes/resourceloader/ResourceLoaderTest.php
tests/phpunit/structure/AutoLoaderStructureTest.php [new file with mode: 0644]
tests/phpunit/structure/AutoLoaderTest.php [deleted file]

index d36d80d..62fa853 100644 (file)
@@ -72,7 +72,6 @@
                        Whitelist existing violations, but enable the sniff to prevent
                        any new occurrences.
                -->
-               <exclude-pattern>*/includes/api/ApiQueryUserContributions\.php</exclude-pattern>
                <exclude-pattern>*/includes/api/ApiMessage\.php</exclude-pattern>
                <exclude-pattern>*/includes/api/ApiUsageException\.php</exclude-pattern>
                <exclude-pattern>*/includes/media/XCF\.php</exclude-pattern>
                <exclude-pattern>*/includes/search/SearchEngine\.php</exclude-pattern>
                <exclude-pattern>*/includes/specialpage/LoginSignupSpecialPage\.php</exclude-pattern>
                <exclude-pattern>*/includes/specialpage/RedirectSpecialPage\.php</exclude-pattern>
+               <exclude-pattern>*/includes/specials/forms/PreferencesFormLegacy\.php</exclude-pattern>
                <exclude-pattern>*/includes/specials/SpecialListusers\.php</exclude-pattern>
                <exclude-pattern>*/includes/specials/SpecialMyRedirectPages\.php</exclude-pattern>
                <exclude-pattern>*/includes/specials/SpecialUploadStash\.php</exclude-pattern>
index 740535a..bf038a7 100644 (file)
@@ -383,6 +383,9 @@ changes to languages because of Phabricator reports.
   used instead.
 * The function wfShellWikiCmd() has been deprecated, use
   MediaWiki\Shell::makeScriptCommand().
+* In the future, the hooks 'PreferencesFormPreSave' and 'PreferencesGetLegend'
+  will be allowed to provide any HTMLForm object rather than PreferencesForm.
+
 === Other changes in 1.31 ===
 * Browser support for Internet Explorer 10 was lowered from Grade A to Grade C.
 * Browser support for Opera 12 and older was dropped entirely. Opera 15+
index 00e43c5..c1b579a 100644 (file)
@@ -109,6 +109,15 @@ because of Phabricator reports.
 * The jquery.farbtastic module, unused since 1.18, was removed.
 * (T181318) The $wgStyleVersion setting and its appendage to various script and
   style URLs in OutputPage, deprecated in 1.31, was removed.
+* The hooks 'PreferencesFormPreSave' and 'PreferencesGetLegend' may provide
+  any HTMLForm object rather than PreferencesForm.
+* The non namespaced TimestampException class, deprecated in 1.29, was removed.
+  Use Wikimedia\Timestamp\TimestampException instead.
+* The global functions codepointToUtf8, hexSequenceToUtf8, utf8ToHexSequence,
+  utf8ToCodepoint, and escapeSingleString (deprecated in 1.25) were removed.
+  The UtfNormal\Utils class from the utfnormal library should be used instead.
+* The deprecated UTF8_ and UNICODE_ constants were removed. The class constants
+  from the UtfNormal\Constants class from the utfnormal library should be used
 
 === Deprecations in 1.32 ===
 * Use of a StartProfiler.php file is deprecated in favour of placing
@@ -133,6 +142,8 @@ because of Phabricator reports.
   to use it.
 * WatchAction::getUnwatchToken is deprecated. Use WatchAction::getWatchToken
   with the 'unwatch' action parameter instead.
+* IcuCollation::getICUVersion() is deprecated, as you can just use the PHP
+  constant INTL_ICU_VERSION directly in all versions that MediaWiki supports.
 
 === Other changes in 1.32 ===
 * Soft hyphens (U+00AD) are now automatically removed from titles; these
index 2006263..9981cab 100644 (file)
@@ -93,7 +93,7 @@ $wgAutoloadLocalClasses = [
        'ApiQueryCategories' => __DIR__ . '/includes/api/ApiQueryCategories.php',
        'ApiQueryCategoryInfo' => __DIR__ . '/includes/api/ApiQueryCategoryInfo.php',
        'ApiQueryCategoryMembers' => __DIR__ . '/includes/api/ApiQueryCategoryMembers.php',
-       'ApiQueryContributions' => __DIR__ . '/includes/api/ApiQueryUserContributions.php',
+       'ApiQueryContributions' => __DIR__ . '/includes/api/ApiQueryUserContribs.php',
        'ApiQueryContributors' => __DIR__ . '/includes/api/ApiQueryContributors.php',
        'ApiQueryDeletedRevisions' => __DIR__ . '/includes/api/ApiQueryDeletedRevisions.php',
        'ApiQueryDeletedrevs' => __DIR__ . '/includes/api/ApiQueryDeletedrevs.php',
@@ -129,6 +129,7 @@ $wgAutoloadLocalClasses = [
        'ApiQueryStashImageInfo' => __DIR__ . '/includes/api/ApiQueryStashImageInfo.php',
        'ApiQueryTags' => __DIR__ . '/includes/api/ApiQueryTags.php',
        'ApiQueryTokens' => __DIR__ . '/includes/api/ApiQueryTokens.php',
+       'ApiQueryUserContribs' => __DIR__ . '/includes/api/ApiQueryUserContribs.php',
        'ApiQueryUserInfo' => __DIR__ . '/includes/api/ApiQueryUserInfo.php',
        'ApiQueryUsers' => __DIR__ . '/includes/api/ApiQueryUsers.php',
        'ApiQueryWatchlist' => __DIR__ . '/includes/api/ApiQueryWatchlist.php',
@@ -853,6 +854,41 @@ $wgAutoloadLocalClasses = [
        'MediaWikiSite' => __DIR__ . '/includes/site/MediaWikiSite.php',
        'MediaWikiTitleCodec' => __DIR__ . '/includes/title/MediaWikiTitleCodec.php',
        'MediaWikiVersionFetcher' => __DIR__ . '/includes/MediaWikiVersionFetcher.php',
+       'MediaWiki\\Auth\\AbstractAuthenticationProvider' => __DIR__ . '/includes/auth/AbstractAuthenticationProvider.php',
+       'MediaWiki\\Auth\\AbstractPasswordPrimaryAuthenticationProvider' => __DIR__ . '/includes/auth/AbstractPasswordPrimaryAuthenticationProvider.php',
+       'MediaWiki\\Auth\\AbstractPreAuthenticationProvider' => __DIR__ . '/includes/auth/AbstractPreAuthenticationProvider.php',
+       'MediaWiki\\Auth\\AbstractPrimaryAuthenticationProvider' => __DIR__ . '/includes/auth/AbstractPrimaryAuthenticationProvider.php',
+       'MediaWiki\\Auth\\AbstractSecondaryAuthenticationProvider' => __DIR__ . '/includes/auth/AbstractSecondaryAuthenticationProvider.php',
+       'MediaWiki\\Auth\\AuthManager' => __DIR__ . '/includes/auth/AuthManager.php',
+       'MediaWiki\\Auth\\AuthManagerAuthPlugin' => __DIR__ . '/includes/auth/AuthManagerAuthPlugin.php',
+       'MediaWiki\\Auth\\AuthManagerAuthPluginUser' => __DIR__ . '/includes/auth/AuthManagerAuthPlugin.php',
+       'MediaWiki\\Auth\\AuthPluginPrimaryAuthenticationProvider' => __DIR__ . '/includes/auth/AuthPluginPrimaryAuthenticationProvider.php',
+       'MediaWiki\\Auth\\AuthenticationProvider' => __DIR__ . '/includes/auth/AuthenticationProvider.php',
+       'MediaWiki\\Auth\\AuthenticationRequest' => __DIR__ . '/includes/auth/AuthenticationRequest.php',
+       'MediaWiki\\Auth\\AuthenticationResponse' => __DIR__ . '/includes/auth/AuthenticationResponse.php',
+       'MediaWiki\\Auth\\ButtonAuthenticationRequest' => __DIR__ . '/includes/auth/ButtonAuthenticationRequest.php',
+       'MediaWiki\\Auth\\CheckBlocksSecondaryAuthenticationProvider' => __DIR__ . '/includes/auth/CheckBlocksSecondaryAuthenticationProvider.php',
+       'MediaWiki\\Auth\\ConfirmLinkAuthenticationRequest' => __DIR__ . '/includes/auth/ConfirmLinkAuthenticationRequest.php',
+       'MediaWiki\\Auth\\ConfirmLinkSecondaryAuthenticationProvider' => __DIR__ . '/includes/auth/ConfirmLinkSecondaryAuthenticationProvider.php',
+       'MediaWiki\\Auth\\CreateFromLoginAuthenticationRequest' => __DIR__ . '/includes/auth/CreateFromLoginAuthenticationRequest.php',
+       'MediaWiki\\Auth\\CreatedAccountAuthenticationRequest' => __DIR__ . '/includes/auth/CreatedAccountAuthenticationRequest.php',
+       'MediaWiki\\Auth\\CreationReasonAuthenticationRequest' => __DIR__ . '/includes/auth/CreationReasonAuthenticationRequest.php',
+       'MediaWiki\\Auth\\EmailNotificationSecondaryAuthenticationProvider' => __DIR__ . '/includes/auth/EmailNotificationSecondaryAuthenticationProvider.php',
+       'MediaWiki\\Auth\\LegacyHookPreAuthenticationProvider' => __DIR__ . '/includes/auth/LegacyHookPreAuthenticationProvider.php',
+       'MediaWiki\\Auth\\LocalPasswordPrimaryAuthenticationProvider' => __DIR__ . '/includes/auth/LocalPasswordPrimaryAuthenticationProvider.php',
+       'MediaWiki\\Auth\\PasswordAuthenticationRequest' => __DIR__ . '/includes/auth/PasswordAuthenticationRequest.php',
+       'MediaWiki\\Auth\\PasswordDomainAuthenticationRequest' => __DIR__ . '/includes/auth/PasswordDomainAuthenticationRequest.php',
+       'MediaWiki\\Auth\\PreAuthenticationProvider' => __DIR__ . '/includes/auth/PreAuthenticationProvider.php',
+       'MediaWiki\\Auth\\PrimaryAuthenticationProvider' => __DIR__ . '/includes/auth/PrimaryAuthenticationProvider.php',
+       'MediaWiki\\Auth\\RememberMeAuthenticationRequest' => __DIR__ . '/includes/auth/RememberMeAuthenticationRequest.php',
+       'MediaWiki\\Auth\\ResetPasswordSecondaryAuthenticationProvider' => __DIR__ . '/includes/auth/ResetPasswordSecondaryAuthenticationProvider.php',
+       'MediaWiki\\Auth\\SecondaryAuthenticationProvider' => __DIR__ . '/includes/auth/SecondaryAuthenticationProvider.php',
+       'MediaWiki\\Auth\\TemporaryPasswordAuthenticationRequest' => __DIR__ . '/includes/auth/TemporaryPasswordAuthenticationRequest.php',
+       'MediaWiki\\Auth\\TemporaryPasswordPrimaryAuthenticationProvider' => __DIR__ . '/includes/auth/TemporaryPasswordPrimaryAuthenticationProvider.php',
+       'MediaWiki\\Auth\\ThrottlePreAuthenticationProvider' => __DIR__ . '/includes/auth/ThrottlePreAuthenticationProvider.php',
+       'MediaWiki\\Auth\\Throttler' => __DIR__ . '/includes/auth/Throttler.php',
+       'MediaWiki\\Auth\\UserDataAuthenticationRequest' => __DIR__ . '/includes/auth/UserDataAuthenticationRequest.php',
+       'MediaWiki\\Auth\\UsernameAuthenticationRequest' => __DIR__ . '/includes/auth/UsernameAuthenticationRequest.php',
        'MediaWiki\\Diff\\ComplexityException' => __DIR__ . '/includes/diff/ComplexityException.php',
        'MediaWiki\\Diff\\WordAccumulator' => __DIR__ . '/includes/diff/WordAccumulator.php',
        'MediaWiki\\HeaderCallback' => __DIR__ . '/includes/HeaderCallback.php',
@@ -882,72 +918,10 @@ $wgAutoloadLocalClasses = [
        'MediaWiki\\Logger\\Spi' => __DIR__ . '/includes/debug/logger/Spi.php',
        'MediaWiki\\MediaWikiServices' => __DIR__ . '/includes/MediaWikiServices.php',
        'MediaWiki\\OutputHandler' => __DIR__ . '/includes/OutputHandler.php',
-       'MediaWiki\\Preferences\\DefaultPreferencesFactory' => __DIR__ . '/includes/preferences/DefaultPreferencesFactory.php',
-       'MediaWiki\\Preferences\\PreferencesFactory' => __DIR__ . '/includes/preferences/PreferencesFactory.php',
        'MediaWiki\\ProcOpenError' => __DIR__ . '/includes/exception/ProcOpenError.php',
        'MediaWiki\\Search\\ParserOutputSearchDataExtractor' => __DIR__ . '/includes/search/ParserOutputSearchDataExtractor.php',
-       'MediaWiki\\Services\\CannotReplaceActiveServiceException' => __DIR__ . '/includes/services/CannotReplaceActiveServiceException.php',
-       'MediaWiki\\Services\\ContainerDisabledException' => __DIR__ . '/includes/services/ContainerDisabledException.php',
-       'MediaWiki\\Services\\DestructibleService' => __DIR__ . '/includes/services/DestructibleService.php',
-       'MediaWiki\\Services\\NoSuchServiceException' => __DIR__ . '/includes/services/NoSuchServiceException.php',
-       'MediaWiki\\Services\\SalvageableService' => __DIR__ . '/includes/services/SalvageableService.php',
-       'MediaWiki\\Services\\ServiceAlreadyDefinedException' => __DIR__ . '/includes/services/ServiceAlreadyDefinedException.php',
-       'MediaWiki\\Services\\ServiceContainer' => __DIR__ . '/includes/services/ServiceContainer.php',
-       'MediaWiki\\Services\\ServiceDisabledException' => __DIR__ . '/includes/services/ServiceDisabledException.php',
-       'MediaWiki\\Session\\BotPasswordSessionProvider' => __DIR__ . '/includes/session/BotPasswordSessionProvider.php',
-       'MediaWiki\\Session\\CookieSessionProvider' => __DIR__ . '/includes/session/CookieSessionProvider.php',
-       'MediaWiki\\Session\\ImmutableSessionProviderWithCookie' => __DIR__ . '/includes/session/ImmutableSessionProviderWithCookie.php',
-       'MediaWiki\\Session\\MetadataMergeException' => __DIR__ . '/includes/session/MetadataMergeException.php',
-       'MediaWiki\\Session\\PHPSessionHandler' => __DIR__ . '/includes/session/PHPSessionHandler.php',
-       'MediaWiki\\Session\\Session' => __DIR__ . '/includes/session/Session.php',
-       'MediaWiki\\Session\\SessionBackend' => __DIR__ . '/includes/session/SessionBackend.php',
-       'MediaWiki\\Session\\SessionId' => __DIR__ . '/includes/session/SessionId.php',
-       'MediaWiki\\Session\\SessionInfo' => __DIR__ . '/includes/session/SessionInfo.php',
-       'MediaWiki\\Session\\SessionManager' => __DIR__ . '/includes/session/SessionManager.php',
-       'MediaWiki\\Session\\SessionManagerInterface' => __DIR__ . '/includes/session/SessionManagerInterface.php',
-       'MediaWiki\\Session\\SessionProvider' => __DIR__ . '/includes/session/SessionProvider.php',
-       'MediaWiki\\Session\\SessionProviderInterface' => __DIR__ . '/includes/session/SessionProviderInterface.php',
-       'MediaWiki\\Session\\Token' => __DIR__ . '/includes/session/Token.php',
-       'MediaWiki\\Session\\UserInfo' => __DIR__ . '/includes/session/UserInfo.php',
        'MediaWiki\\ShellDisabledError' => __DIR__ . '/includes/exception/ShellDisabledError.php',
-       'MediaWiki\\Shell\\Command' => __DIR__ . '/includes/shell/Command.php',
-       'MediaWiki\\Shell\\CommandFactory' => __DIR__ . '/includes/shell/CommandFactory.php',
-       'MediaWiki\\Shell\\FirejailCommand' => __DIR__ . '/includes/shell/FirejailCommand.php',
-       'MediaWiki\\Shell\\Result' => __DIR__ . '/includes/shell/Result.php',
-       'MediaWiki\\Shell\\Shell' => __DIR__ . '/includes/shell/Shell.php',
        'MediaWiki\\Site\\MediaWikiPageNameNormalizer' => __DIR__ . '/includes/site/MediaWikiPageNameNormalizer.php',
-       'MediaWiki\\Sparql\\SparqlClient' => __DIR__ . '/includes/sparql/SparqlClient.php',
-       'MediaWiki\\Sparql\\SparqlException' => __DIR__ . '/includes/sparql/SparqlException.php',
-       'MediaWiki\\Storage\\BlobAccessException' => __DIR__ . '/includes/Storage/BlobAccessException.php',
-       'MediaWiki\\Storage\\BlobStore' => __DIR__ . '/includes/Storage/BlobStore.php',
-       'MediaWiki\\Storage\\BlobStoreFactory' => __DIR__ . '/includes/Storage/BlobStoreFactory.php',
-       'MediaWiki\\Storage\\IncompleteRevisionException' => __DIR__ . '/includes/Storage/IncompleteRevisionException.php',
-       'MediaWiki\\Storage\\MutableRevisionRecord' => __DIR__ . '/includes/Storage/MutableRevisionRecord.php',
-       'MediaWiki\\Storage\\MutableRevisionSlots' => __DIR__ . '/includes/Storage/MutableRevisionSlots.php',
-       'MediaWiki\\Storage\\NameTableAccessException' => __DIR__ . '/includes/Storage/NameTableAccessException.php',
-       'MediaWiki\\Storage\\NameTableStore' => __DIR__ . '/includes/Storage/NameTableStore.php',
-       'MediaWiki\\Storage\\RevisionAccessException' => __DIR__ . '/includes/Storage/RevisionAccessException.php',
-       'MediaWiki\\Storage\\RevisionArchiveRecord' => __DIR__ . '/includes/Storage/RevisionArchiveRecord.php',
-       'MediaWiki\\Storage\\RevisionFactory' => __DIR__ . '/includes/Storage/RevisionFactory.php',
-       'MediaWiki\\Storage\\RevisionLookup' => __DIR__ . '/includes/Storage/RevisionLookup.php',
-       'MediaWiki\\Storage\\RevisionRecord' => __DIR__ . '/includes/Storage/RevisionRecord.php',
-       'MediaWiki\\Storage\\RevisionSlots' => __DIR__ . '/includes/Storage/RevisionSlots.php',
-       'MediaWiki\\Storage\\RevisionSlotsUpdate' => __DIR__ . '/includes/Storage/RevisionSlotsUpdate.php',
-       'MediaWiki\\Storage\\RevisionStore' => __DIR__ . '/includes/Storage/RevisionStore.php',
-       'MediaWiki\\Storage\\RevisionStoreRecord' => __DIR__ . '/includes/Storage/RevisionStoreRecord.php',
-       'MediaWiki\\Storage\\SlotRecord' => __DIR__ . '/includes/Storage/SlotRecord.php',
-       'MediaWiki\\Storage\\SqlBlobStore' => __DIR__ . '/includes/Storage/SqlBlobStore.php',
-       'MediaWiki\\Storage\\SuppressedDataException' => __DIR__ . '/includes/Storage/SuppressedDataException.php',
-       'MediaWiki\\Tidy\\RaggettBase' => __DIR__ . '/includes/tidy/RaggettBase.php',
-       'MediaWiki\\Tidy\\RaggettExternal' => __DIR__ . '/includes/tidy/RaggettExternal.php',
-       'MediaWiki\\Tidy\\RaggettInternalHHVM' => __DIR__ . '/includes/tidy/RaggettInternalHHVM.php',
-       'MediaWiki\\Tidy\\RaggettInternalPHP' => __DIR__ . '/includes/tidy/RaggettInternalPHP.php',
-       'MediaWiki\\Tidy\\RaggettWrapper' => __DIR__ . '/includes/tidy/RaggettWrapper.php',
-       'MediaWiki\\Tidy\\RemexCompatFormatter' => __DIR__ . '/includes/tidy/RemexCompatFormatter.php',
-       'MediaWiki\\Tidy\\RemexCompatMunger' => __DIR__ . '/includes/tidy/RemexCompatMunger.php',
-       'MediaWiki\\Tidy\\RemexDriver' => __DIR__ . '/includes/tidy/RemexDriver.php',
-       'MediaWiki\\Tidy\\RemexMungerData' => __DIR__ . '/includes/tidy/RemexMungerData.php',
-       'MediaWiki\\Tidy\\TidyDriverBase' => __DIR__ . '/includes/tidy/TidyDriverBase.php',
        'MediaWiki\\User\\UserIdentity' => __DIR__ . '/includes/user/UserIdentity.php',
        'MediaWiki\\User\\UserIdentityValue' => __DIR__ . '/includes/user/UserIdentityValue.php',
        'MediaWiki\\Widget\\ComplexNamespaceInputWidget' => __DIR__ . '/includes/widget/ComplexNamespaceInputWidget.php',
@@ -1142,7 +1116,7 @@ $wgAutoloadLocalClasses = [
        'PostgresInstaller' => __DIR__ . '/includes/installer/PostgresInstaller.php',
        'PostgresUpdater' => __DIR__ . '/includes/installer/PostgresUpdater.php',
        'Preferences' => __DIR__ . '/includes/Preferences.php',
-       'PreferencesForm' => __DIR__ . '/includes/specials/forms/PreferencesForm.php',
+       'PreferencesForm' => __DIR__ . '/includes/specials/forms/PreferencesFormLegacy.php',
        'PreferencesFormLegacy' => __DIR__ . '/includes/specials/forms/PreferencesFormLegacy.php',
        'PreferencesFormOOUI' => __DIR__ . '/includes/specials/forms/PreferencesFormOOUI.php',
        'PrefixSearch' => __DIR__ . '/includes/PrefixSearch.php',
index d32a207..ce137d1 100644 (file)
                "psr-0": {
                        "ComposerHookHandler": "includes/composer",
                        "ComposerVendorHtaccessCreator": "includes/composer"
-               },
-               "files": [
-                       "includes/compat/Timestamp.php"
-               ]
+               }
        },
        "autoload-dev": {
                "files": [
index 9404e14..349cd4b 100644 (file)
@@ -2716,14 +2716,14 @@ Occurs after signing up or logging in, allows for interception of redirect.
 
 'PreferencesFormPreSave': Override preferences being saved
 $formData: array of user submitted data
-$form: PreferencesForm object, also a ContextSource
+$form: HTMLForm object, also a ContextSource
 $user: User object with preferences to be saved set
 &$result: boolean indicating success
 $oldUserOptions: array with user old options (before save)
 
 'PreferencesGetLegend': Override the text used for the <legend> of a
 preferences section.
-$form: the PreferencesForm object. This is a ContextSource as well
+$form: the HTMLForm object. This is a ContextSource as well
 $key: the section name
 &$legend: the legend text. Defaults to wfMessage( "prefs-$key" )->text() but may
   be overridden
index 0b4e0bd..8dff602 100644 (file)
@@ -58,7 +58,7 @@ These can also be customised on a per-user basis, by editing
 
 Several custom skins are available as of 2014.
 
-https://www.mediawiki.org/wiki/Category:All_skins
+https://www.mediawiki.org/wiki/Special:MyLanguage/Category:All_skins
 
 Installing a skin requires adding its files in a subdirectory under skins/ and
 adding an appropriate require_once line to LocalSettings.php, similarly to how
index d1c11c4..9fc063a 100644 (file)
@@ -123,15 +123,22 @@ class AutoLoader {
         *
         * @see <http://www.php-fig.org/psr/psr-4/>
         * @private Only public for usage in AutoloadGenerator
+        * @codeCoverageIgnore
         * @since 1.31
         * @return string[]
         */
        public static function getAutoloadNamespaces() {
                return [
-                       'MediaWiki\\Auth\\' => __DIR__ . '/auth/',
                        'MediaWiki\\Edit\\' => __DIR__ . '/edit/',
                        'MediaWiki\\EditPage\\' => __DIR__ . '/editpage/',
                        'MediaWiki\\Linker\\' => __DIR__ .'/linker/',
+                       'MediaWiki\\Preferences\\' => __DIR__ .'/preferences/',
+                       'MediaWiki\\Services\\' => __DIR__ .'/services/',
+                       'MediaWiki\\Session\\' => __DIR__ .'/session/',
+                       'MediaWiki\\Shell\\' => __DIR__ .'/shell/',
+                       'MediaWiki\\Sparql\\' => __DIR__ .'/sparql/',
+                       'MediaWiki\\Storage\\' => __DIR__ .'/Storage/',
+                       'MediaWiki\\Tidy\\' => __DIR__ .'/tidy/',
                ];
        }
 }
index e253c83..853315f 100644 (file)
@@ -3227,8 +3227,8 @@ $wgHTMLFormAllowTableFormat = true;
 $wgUseMediaWikiUIEverywhere = false;
 
 /**
- * Temporary variable that determines whether the EditPage class should use OOjs UI or not.
- * This will be removed later and OOjs UI will become the only option.
+ * Temporary variable that determines whether Special:Preferences should use OOUI or not.
+ * This will be removed later and OOUI will become the only option.
  *
  * @since 1.32
  */
index 087af39..e5261e7 100644 (file)
@@ -22,7 +22,6 @@
 
 require_once __DIR__ . '/libs/mime/defines.php';
 require_once __DIR__ . '/libs/rdbms/defines.php';
-require_once __DIR__ . '/compat/normal/UtfNormalDefines.php';
 
 use Wikimedia\Rdbms\IDatabase;
 
index 67ce1f3..87fb711 100644 (file)
@@ -4111,14 +4111,12 @@ ERROR;
 
                $script .= '});';
 
-               $nonce = $wgOut->getCSPNonce();
-               $wgOut->addScript( ResourceLoader::makeInlineScript( $script, $nonce ) );
-
                $toolbar = '<div id="toolbar"></div>';
 
                if ( Hooks::run( 'EditPageBeforeEditToolbar', [ &$toolbar ] ) ) {
                        // Only add the old toolbar cruft to the page payload if the toolbar has not
                        // been over-written by a hook caller
+                       $nonce = $wgOut->getCSPNonce();
                        $wgOut->addScript( ResourceLoader::makeInlineScript( $script, $nonce ) );
                };
 
index 2ad626c..6f49a14 100644 (file)
@@ -1446,7 +1446,7 @@ function wfHostname() {
  * hostname of the server handling the request.
  *
  * @param string $nonce Value from OutputPage::getCSPNonce
- * @return string
+ * @return string|WrappedString HTML
  */
 function wfReportTime( $nonce = null ) {
        global $wgShowHostnames;
@@ -2670,6 +2670,28 @@ function wfGetPrecompiledData( $name ) {
        return false;
 }
 
+/**
+ * @since 1.32
+ * @param string[] $data Array with string keys/values to export
+ * @param string $header
+ * @return string PHP code
+ */
+function wfMakeStaticArrayFile( array $data, $header = 'Automatically generated' ) {
+       $format = "\t%s => %s,\n";
+       $code = "<?php\n"
+               . "// " . implode( "\n// ", explode( "\n", $header ) ) . "\n"
+               . "return [\n";
+       foreach ( $data as $key => $value ) {
+               $code .= sprintf(
+                       $format,
+                       var_export( $key, true ),
+                       var_export( $value, true )
+               );
+       }
+       $code .= "];\n";
+       return $code;
+}
+
 /**
  * Make a cache key for the local wiki.
  *
index c22dc97..d434120 100644 (file)
@@ -47,10 +47,6 @@ class Hooks {
         * @since 1.18
         */
        public static function register( $name, $callback ) {
-               if ( !isset( self::$handlers[$name] ) ) {
-                       self::$handlers[$name] = [];
-               }
-
                self::$handlers[$name][] = $callback;
        }
 
@@ -62,6 +58,7 @@ class Hooks {
         *
         * @since 1.21
         * @throws MWException If not in testing mode.
+        * @codeCoverageIgnore
         */
        public static function clear( $name ) {
                if ( !defined( 'MW_PHPUNIT_TEST' ) && !defined( 'MW_PARSER_TEST' ) ) {
index e612d3f..8eda14a 100644 (file)
@@ -134,7 +134,7 @@ class PHPVersionCheck {
                        If for some reason you are unable to upgrade your {$phpInfo['implementation']} version,
                        you will need to <a href="https://www.mediawiki.org/wiki/Download">download</a> an
                        older version of MediaWiki from our website.
-                       See our<a href="https://www.mediawiki.org/wiki/Compatibility#PHP">compatibility page</a>
+                       See our <a href="https://www.mediawiki.org/wiki/Compatibility#PHP">compatibility page</a>
                        for details of which versions are compatible with prior versions of {$phpInfo['implementation']}.
 HTML;
                        // phpcs:enable Generic.Files.LineLength
index 26e28ba..035b494 100644 (file)
@@ -306,7 +306,7 @@ class Preferences {
         * @deprecated since 1.31, use PreferencesFactory
         *
         * @param array $formData
-        * @param PreferencesForm $form
+        * @param HTMLForm $form
         * @return bool|Status|string
         */
        public static function tryFormSubmit( $formData, $form ) {
@@ -316,7 +316,7 @@ class Preferences {
 
        /**
         * @param array $formData
-        * @param PreferencesForm $form
+        * @param HTMLForm $form
         * @return Status
         */
        public static function tryUISubmit( $formData, $form ) {
index 9d7a155..f73e686 100644 (file)
@@ -627,8 +627,6 @@ define( 'MW_SERVICE_BOOTSTRAP_COMPLETE', 1 );
 
 MWExceptionHandler::installHandler();
 
-require_once "$IP/includes/compat/normal/UtfNormalUtil.php";
-
 // T48998: Bail out early if $wgArticlePath is non-absolute
 foreach ( [ 'wgArticlePath', 'wgVariantArticlePath' ] as $varName ) {
        if ( $$varName && !preg_match( '/^(https?:\/\/|\/)/', $$varName ) ) {
index e49024d..c68ec2b 100644 (file)
@@ -98,7 +98,7 @@ class ApiQuery extends ApiBase {
                'recentchanges' => ApiQueryRecentChanges::class,
                'search' => ApiQuerySearch::class,
                'tags' => ApiQueryTags::class,
-               'usercontribs' => ApiQueryContributions::class,
+               'usercontribs' => ApiQueryUserContribs::class,
                'users' => ApiQueryUsers::class,
                'watchlist' => ApiQueryWatchlist::class,
                'watchlistraw' => ApiQueryWatchlistRaw::class,
diff --git a/includes/api/ApiQueryUserContribs.php b/includes/api/ApiQueryUserContribs.php
new file mode 100644 (file)
index 0000000..4c6672b
--- /dev/null
@@ -0,0 +1,835 @@
+<?php
+/**
+ * Copyright © 2006 Yuri Astrakhan "<Firstname><Lastname>@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
+ */
+
+/**
+ * This query action adds a list of a specified user's contributions to the output.
+ *
+ * @ingroup API
+ */
+class ApiQueryUserContribs extends ApiQueryBase {
+
+       public function __construct( ApiQuery $query, $moduleName ) {
+               parent::__construct( $query, $moduleName, 'uc' );
+       }
+
+       private $params, $multiUserMode, $orderBy, $parentLens, $commentStore;
+
+       private $fld_ids = false, $fld_title = false, $fld_timestamp = false,
+               $fld_comment = false, $fld_parsedcomment = false, $fld_flags = false,
+               $fld_patrolled = false, $fld_tags = false, $fld_size = false, $fld_sizediff = false;
+
+       public function execute() {
+               global $wgActorTableSchemaMigrationStage;
+
+               // Parse some parameters
+               $this->params = $this->extractRequestParams();
+
+               $this->commentStore = CommentStore::getStore();
+
+               $prop = array_flip( $this->params['prop'] );
+               $this->fld_ids = isset( $prop['ids'] );
+               $this->fld_title = isset( $prop['title'] );
+               $this->fld_comment = isset( $prop['comment'] );
+               $this->fld_parsedcomment = isset( $prop['parsedcomment'] );
+               $this->fld_size = isset( $prop['size'] );
+               $this->fld_sizediff = isset( $prop['sizediff'] );
+               $this->fld_flags = isset( $prop['flags'] );
+               $this->fld_timestamp = isset( $prop['timestamp'] );
+               $this->fld_patrolled = isset( $prop['patrolled'] );
+               $this->fld_tags = isset( $prop['tags'] );
+
+               // Most of this code will use the 'contributions' group DB, which can map to replica DBs
+               // with extra user based indexes or partioning by user. The additional metadata
+               // queries should use a regular replica DB since the lookup pattern is not all by user.
+               $dbSecondary = $this->getDB(); // any random replica DB
+
+               // TODO: if the query is going only against the revision table, should this be done?
+               $this->selectNamedDB( 'contributions', DB_REPLICA, 'contributions' );
+
+               $sort = ( $this->params['dir'] == 'newer' ? '' : ' DESC' );
+               $op = ( $this->params['dir'] == 'older' ? '<' : '>' );
+
+               // Create an Iterator that produces the UserIdentity objects we need, depending
+               // on which of the 'userprefix', 'userids', or 'user' params was
+               // specified.
+               $this->requireOnlyOneParameter( $this->params, 'userprefix', 'userids', 'user' );
+               if ( isset( $this->params['userprefix'] ) ) {
+                       $this->multiUserMode = true;
+                       $this->orderBy = 'name';
+                       $fname = __METHOD__;
+
+                       // Because 'userprefix' might produce a huge number of users (e.g.
+                       // a wiki with users "Test00000001" to "Test99999999"), use a
+                       // generator with batched lookup and continuation.
+                       $userIter = call_user_func( function () use ( $dbSecondary, $sort, $op, $fname ) {
+                               global $wgActorTableSchemaMigrationStage;
+
+                               $fromName = false;
+                               if ( !is_null( $this->params['continue'] ) ) {
+                                       $continue = explode( '|', $this->params['continue'] );
+                                       $this->dieContinueUsageIf( count( $continue ) != 4 );
+                                       $this->dieContinueUsageIf( $continue[0] !== 'name' );
+                                       $fromName = $continue[1];
+                               }
+                               $like = $dbSecondary->buildLike( $this->params['userprefix'], $dbSecondary->anyString() );
+
+                               $limit = 501;
+
+                               do {
+                                       $from = $fromName ? "$op= " . $dbSecondary->addQuotes( $fromName ) : false;
+
+                                       // For the new schema, pull from the actor table. For the
+                                       // old, pull from rev_user. For migration a FULL [OUTER]
+                                       // JOIN would be what we want, except MySQL doesn't support
+                                       // that so we have to UNION instead.
+                                       if ( $wgActorTableSchemaMigrationStage === MIGRATION_NEW ) {
+                                               $res = $dbSecondary->select(
+                                                       'actor',
+                                                       [ 'actor_id', 'user_id' => 'COALESCE(actor_user,0)', 'user_name' => 'actor_name' ],
+                                                       array_merge( [ "actor_name$like" ], $from ? [ "actor_name $from" ] : [] ),
+                                                       $fname,
+                                                       [ 'ORDER BY' => [ "user_name $sort" ], 'LIMIT' => $limit ]
+                                               );
+                                       } elseif ( $wgActorTableSchemaMigrationStage === MIGRATION_OLD ) {
+                                               $res = $dbSecondary->select(
+                                                       'revision',
+                                                       [ 'actor_id' => 'NULL', 'user_id' => 'rev_user', 'user_name' => 'rev_user_text' ],
+                                                       array_merge( [ "rev_user_text$like" ], $from ? [ "rev_user_text $from" ] : [] ),
+                                                       $fname,
+                                                       [ 'DISTINCT', 'ORDER BY' => [ "rev_user_text $sort" ], 'LIMIT' => $limit ]
+                                               );
+                                       } else {
+                                               // There are three queries we have to combine to be sure of getting all results:
+                                               //  - actor table (any rows that have been migrated will have empty rev_user_text)
+                                               //  - revision+actor by user id
+                                               //  - revision+actor by name for anons
+                                               $options = $dbSecondary->unionSupportsOrderAndLimit()
+                                                       ? [ 'ORDER BY' => [ "user_name $sort" ], 'LIMIT' => $limit ] : [];
+                                               $subsql = [];
+                                               $subsql[] = $dbSecondary->selectSQLText(
+                                                       'actor',
+                                                       [ 'actor_id', 'user_id' => 'COALESCE(actor_user,0)', 'user_name' => 'actor_name' ],
+                                                       array_merge( [ "actor_name$like" ], $from ? [ "actor_name $from" ] : [] ),
+                                                       $fname,
+                                                       $options
+                                               );
+                                               $subsql[] = $dbSecondary->selectSQLText(
+                                                       [ 'revision', 'actor' ],
+                                                       [ 'actor_id', 'user_id' => 'rev_user', 'user_name' => 'rev_user_text' ],
+                                                       array_merge(
+                                                               [ "rev_user_text$like", 'rev_user != 0' ],
+                                                               $from ? [ "rev_user_text $from" ] : []
+                                                       ),
+                                                       $fname,
+                                                       array_merge( [ 'DISTINCT' ], $options ),
+                                                       [ 'actor' => [ 'LEFT JOIN', 'rev_user = actor_user' ] ]
+                                               );
+                                               $subsql[] = $dbSecondary->selectSQLText(
+                                                       [ 'revision', 'actor' ],
+                                                       [ 'actor_id', 'user_id' => 'rev_user', 'user_name' => 'rev_user_text' ],
+                                                       array_merge(
+                                                               [ "rev_user_text$like", 'rev_user = 0' ],
+                                                               $from ? [ "rev_user_text $from" ] : []
+                                                       ),
+                                                       $fname,
+                                                       array_merge( [ 'DISTINCT' ], $options ),
+                                                       [ 'actor' => [ 'LEFT JOIN', 'rev_user_text = actor_name' ] ]
+                                               );
+                                               $sql = $dbSecondary->unionQueries( $subsql, false ) . " ORDER BY user_name $sort";
+                                               $sql = $dbSecondary->limitResult( $sql, $limit );
+                                               $res = $dbSecondary->query( $sql, $fname );
+                                       }
+
+                                       $count = 0;
+                                       $fromName = false;
+                                       foreach ( $res as $row ) {
+                                               if ( ++$count >= $limit ) {
+                                                       $fromName = $row->user_name;
+                                                       break;
+                                               }
+                                               yield User::newFromRow( $row );
+                                       }
+                               } while ( $fromName !== false );
+                       } );
+                       // Do the actual sorting client-side, because otherwise
+                       // prepareQuery might try to sort by actor and confuse everything.
+                       $batchSize = 1;
+               } elseif ( isset( $this->params['userids'] ) ) {
+                       if ( !count( $this->params['userids'] ) ) {
+                               $encParamName = $this->encodeParamName( 'userids' );
+                               $this->dieWithError( [ 'apierror-paramempty', $encParamName ], "paramempty_$encParamName" );
+                       }
+
+                       $ids = [];
+                       foreach ( $this->params['userids'] as $uid ) {
+                               if ( $uid <= 0 ) {
+                                       $this->dieWithError( [ 'apierror-invaliduserid', $uid ], 'invaliduserid' );
+                               }
+                               $ids[] = $uid;
+                       }
+
+                       $this->orderBy = 'id';
+                       $this->multiUserMode = count( $ids ) > 1;
+
+                       $from = $fromId = false;
+                       if ( $this->multiUserMode && !is_null( $this->params['continue'] ) ) {
+                               $continue = explode( '|', $this->params['continue'] );
+                               $this->dieContinueUsageIf( count( $continue ) != 4 );
+                               $this->dieContinueUsageIf( $continue[0] !== 'id' && $continue[0] !== 'actor' );
+                               $fromId = (int)$continue[1];
+                               $this->dieContinueUsageIf( $continue[1] !== (string)$fromId );
+                               $from = "$op= $fromId";
+                       }
+
+                       // For the new schema, just select from the actor table. For the
+                       // old and transitional schemas, select from user and left join
+                       // actor if it exists.
+                       if ( $wgActorTableSchemaMigrationStage === MIGRATION_NEW ) {
+                               $res = $dbSecondary->select(
+                                       'actor',
+                                       [ 'actor_id', 'user_id' => 'actor_user', 'user_name' => 'actor_name' ],
+                                       array_merge( [ 'actor_user' => $ids ], $from ? [ "actor_id $from" ] : [] ),
+                                       __METHOD__,
+                                       [ 'ORDER BY' => "user_id $sort" ]
+                               );
+                       } elseif ( $wgActorTableSchemaMigrationStage === MIGRATION_OLD ) {
+                               $res = $dbSecondary->select(
+                                       'user',
+                                       [ 'actor_id' => 'NULL', 'user_id' => 'user_id', 'user_name' => 'user_name' ],
+                                       array_merge( [ 'user_id' => $ids ], $from ? [ "user_id $from" ] : [] ),
+                                       __METHOD__,
+                                       [ 'ORDER BY' => "user_id $sort" ]
+                               );
+                       } else {
+                               $res = $dbSecondary->select(
+                                       [ 'user', 'actor' ],
+                                       [ 'actor_id', 'user_id', 'user_name' ],
+                                       array_merge( [ 'user_id' => $ids ], $from ? [ "user_id $from" ] : [] ),
+                                       __METHOD__,
+                                       [ 'ORDER BY' => "user_id $sort" ],
+                                       [ 'actor' => [ 'LEFT JOIN', 'actor_user = user_id' ] ]
+                               );
+                       }
+                       $userIter = UserArray::newFromResult( $res );
+                       $batchSize = count( $ids );
+               } else {
+                       $names = [];
+                       if ( !count( $this->params['user'] ) ) {
+                               $encParamName = $this->encodeParamName( 'user' );
+                               $this->dieWithError(
+                                       [ 'apierror-paramempty', $encParamName ], "paramempty_$encParamName"
+                               );
+                       }
+                       foreach ( $this->params['user'] as $u ) {
+                               if ( $u === '' ) {
+                                       $encParamName = $this->encodeParamName( 'user' );
+                                       $this->dieWithError(
+                                               [ 'apierror-paramempty', $encParamName ], "paramempty_$encParamName"
+                                       );
+                               }
+
+                               if ( User::isIP( $u ) || ExternalUserNames::isExternal( $u ) ) {
+                                       $names[$u] = null;
+                               } else {
+                                       $name = User::getCanonicalName( $u, 'valid' );
+                                       if ( $name === false ) {
+                                               $encParamName = $this->encodeParamName( 'user' );
+                                               $this->dieWithError(
+                                                       [ 'apierror-baduser', $encParamName, wfEscapeWikiText( $u ) ], "baduser_$encParamName"
+                                               );
+                                       }
+                                       $names[$name] = null;
+                               }
+                       }
+
+                       $this->orderBy = 'name';
+                       $this->multiUserMode = count( $names ) > 1;
+
+                       $from = $fromName = false;
+                       if ( $this->multiUserMode && !is_null( $this->params['continue'] ) ) {
+                               $continue = explode( '|', $this->params['continue'] );
+                               $this->dieContinueUsageIf( count( $continue ) != 4 );
+                               $this->dieContinueUsageIf( $continue[0] !== 'name' && $continue[0] !== 'actor' );
+                               $fromName = $continue[1];
+                               $from = "$op= " . $dbSecondary->addQuotes( $fromName );
+                       }
+
+                       // For the new schema, just select from the actor table. For the
+                       // old and transitional schemas, select from user and left join
+                       // actor if it exists then merge in any unknown users (IPs and imports).
+                       if ( $wgActorTableSchemaMigrationStage === MIGRATION_NEW ) {
+                               $res = $dbSecondary->select(
+                                       'actor',
+                                       [ 'actor_id', 'user_id' => 'actor_user', 'user_name' => 'actor_name' ],
+                                       array_merge( [ 'actor_name' => array_keys( $names ) ], $from ? [ "actor_id $from" ] : [] ),
+                                       __METHOD__,
+                                       [ 'ORDER BY' => "actor_name $sort" ]
+                               );
+                               $userIter = UserArray::newFromResult( $res );
+                       } else {
+                               if ( $wgActorTableSchemaMigrationStage === MIGRATION_OLD ) {
+                                       $res = $dbSecondary->select(
+                                               'user',
+                                               [ 'actor_id' => 'NULL', 'user_id', 'user_name' ],
+                                               array_merge( [ 'user_name' => array_keys( $names ) ], $from ? [ "user_name $from" ] : [] ),
+                                               __METHOD__
+                                       );
+                               } else {
+                                       $res = $dbSecondary->select(
+                                               [ 'user', 'actor' ],
+                                               [ 'actor_id', 'user_id', 'user_name' ],
+                                               array_merge( [ 'user_name' => array_keys( $names ) ], $from ? [ "user_name $from" ] : [] ),
+                                               __METHOD__,
+                                               [],
+                                               [ 'actor' => [ 'LEFT JOIN', 'actor_user = user_id' ] ]
+                                       );
+                               }
+                               foreach ( $res as $row ) {
+                                       $names[$row->user_name] = $row;
+                               }
+                               call_user_func_array(
+                                       $this->params['dir'] == 'newer' ? 'ksort' : 'krsort', [ &$names, SORT_STRING ]
+                               );
+                               $neg = $op === '>' ? -1 : 1;
+                               $userIter = call_user_func( function () use ( $names, $fromName, $neg ) {
+                                       foreach ( $names as $name => $row ) {
+                                               if ( $fromName === false || $neg * strcmp( $name, $fromName ) <= 0 ) {
+                                                       $user = $row ? User::newFromRow( $row ) : User::newFromName( $name, false );
+                                                       yield $user;
+                                               }
+                                       }
+                               } );
+                       }
+                       $batchSize = count( $names );
+               }
+
+               // During migration, force ordering on the client side because we're
+               // having to combine multiple queries that would otherwise have
+               // different sort orders.
+               if ( $wgActorTableSchemaMigrationStage === MIGRATION_WRITE_BOTH ||
+                       $wgActorTableSchemaMigrationStage === MIGRATION_WRITE_NEW
+               ) {
+                       $batchSize = 1;
+               }
+
+               // With the new schema, the DB query will order by actor so update $this->orderBy to match.
+               if ( $batchSize > 1 && $wgActorTableSchemaMigrationStage === MIGRATION_NEW ) {
+                       $this->orderBy = 'actor';
+               }
+
+               $count = 0;
+               $limit = $this->params['limit'];
+               $userIter->rewind();
+               while ( $userIter->valid() ) {
+                       $users = [];
+                       while ( count( $users ) < $batchSize && $userIter->valid() ) {
+                               $users[] = $userIter->current();
+                               $userIter->next();
+                       }
+
+                       // Ugh. We have to run the query three times, once for each
+                       // possible 'orcond' from ActorMigration, and then merge them all
+                       // together in the proper order. And preserving the correct
+                       // $hookData for each one.
+                       // @todo When ActorMigration is removed, this can go back to a
+                       //  single prepare and select.
+                       $merged = [];
+                       foreach ( [ 'actor', 'userid', 'username' ] as $which ) {
+                               if ( $this->prepareQuery( $users, $limit - $count, $which ) ) {
+                                       $hookData = [];
+                                       $res = $this->select( __METHOD__, [], $hookData );
+                                       foreach ( $res as $row ) {
+                                               $merged[] = [ $row, &$hookData ];
+                                       }
+                               }
+                       }
+                       $neg = $this->params['dir'] == 'newer' ? 1 : -1;
+                       usort( $merged, function ( $a, $b ) use ( $neg, $batchSize ) {
+                               if ( $batchSize === 1 ) { // One user, can't be different
+                                       $ret = 0;
+                               } elseif ( $this->orderBy === 'id' ) {
+                                       $ret = $a[0]->rev_user - $b[0]->rev_user;
+                               } elseif ( $this->orderBy === 'name' ) {
+                                       $ret = strcmp( $a[0]->rev_user_text, $b[0]->rev_user_text );
+                               } else {
+                                       $ret = $a[0]->rev_actor - $b[0]->rev_actor;
+                               }
+
+                               if ( !$ret ) {
+                                       $ret = strcmp(
+                                               wfTimestamp( TS_MW, $a[0]->rev_timestamp ),
+                                               wfTimestamp( TS_MW, $b[0]->rev_timestamp )
+                                       );
+                               }
+
+                               if ( !$ret ) {
+                                       $ret = $a[0]->rev_id - $b[0]->rev_id;
+                               }
+
+                               return $neg * $ret;
+                       } );
+                       $merged = array_slice( $merged, 0, $limit - $count + 1 );
+                       // (end "Ugh")
+
+                       if ( $this->fld_sizediff ) {
+                               $revIds = [];
+                               foreach ( $merged as $data ) {
+                                       if ( $data[0]->rev_parent_id ) {
+                                               $revIds[] = $data[0]->rev_parent_id;
+                                       }
+                               }
+                               $this->parentLens = Revision::getParentLengths( $dbSecondary, $revIds );
+                       }
+
+                       foreach ( $merged as $data ) {
+                               $row = $data[0];
+                               $hookData = &$data[1];
+                               if ( ++$count > $limit ) {
+                                       // We've reached the one extra which shows that there are
+                                       // additional pages to be had. Stop here...
+                                       $this->setContinueEnumParameter( 'continue', $this->continueStr( $row ) );
+                                       break 2;
+                               }
+
+                               $vals = $this->extractRowInfo( $row );
+                               $fit = $this->processRow( $row, $vals, $hookData ) &&
+                                       $this->getResult()->addValue( [ 'query', $this->getModuleName() ], null, $vals );
+                               if ( !$fit ) {
+                                       $this->setContinueEnumParameter( 'continue', $this->continueStr( $row ) );
+                                       break 2;
+                               }
+                       }
+               }
+
+               $this->getResult()->addIndexedTagName( [ 'query', $this->getModuleName() ], 'item' );
+       }
+
+       /**
+        * Prepares the query and returns the limit of rows requested
+        * @param User[] $users
+        * @param int $limit
+        * @param string $which 'actor', 'userid', or 'username'
+        * @return bool
+        */
+       private function prepareQuery( array $users, $limit, $which ) {
+               global $wgActorTableSchemaMigrationStage;
+
+               $this->resetQueryParams();
+               $db = $this->getDB();
+
+               $revQuery = Revision::getQueryInfo( [ 'page' ] );
+               $this->addTables( $revQuery['tables'] );
+               $this->addJoinConds( $revQuery['joins'] );
+               $this->addFields( $revQuery['fields'] );
+
+               $revWhere = ActorMigration::newMigration()->getWhere( $db, 'rev_user', $users );
+               if ( !isset( $revWhere['orconds'][$which] ) ) {
+                       return false;
+               }
+               $this->addWhere( $revWhere['orconds'][$which] );
+
+               if ( $wgActorTableSchemaMigrationStage === MIGRATION_NEW ) {
+                       $orderUserField = 'rev_actor';
+                       $userField = $this->orderBy === 'actor' ? 'revactor_actor' : 'actor_name';
+               } else {
+                       $orderUserField = $this->orderBy === 'id' ? 'rev_user' : 'rev_user_text';
+                       $userField = $revQuery['fields'][$orderUserField];
+               }
+               if ( $which === 'actor' ) {
+                       $tsField = 'revactor_timestamp';
+                       $idField = 'revactor_rev';
+               } else {
+                       $tsField = 'rev_timestamp';
+                       $idField = 'rev_id';
+               }
+
+               // Handle continue parameter
+               if ( !is_null( $this->params['continue'] ) ) {
+                       $continue = explode( '|', $this->params['continue'] );
+                       if ( $this->multiUserMode ) {
+                               $this->dieContinueUsageIf( count( $continue ) != 4 );
+                               $modeFlag = array_shift( $continue );
+                               $this->dieContinueUsageIf( $modeFlag !== $this->orderBy );
+                               $encUser = $db->addQuotes( array_shift( $continue ) );
+                       } else {
+                               $this->dieContinueUsageIf( count( $continue ) != 2 );
+                       }
+                       $encTS = $db->addQuotes( $db->timestamp( $continue[0] ) );
+                       $encId = (int)$continue[1];
+                       $this->dieContinueUsageIf( $encId != $continue[1] );
+                       $op = ( $this->params['dir'] == 'older' ? '<' : '>' );
+                       if ( $this->multiUserMode ) {
+                               $this->addWhere(
+                                       "$userField $op $encUser OR " .
+                                       "($userField = $encUser AND " .
+                                       "($tsField $op $encTS OR " .
+                                       "($tsField = $encTS AND " .
+                                       "$idField $op= $encId)))"
+                               );
+                       } else {
+                               $this->addWhere(
+                                       "$tsField $op $encTS OR " .
+                                       "($tsField = $encTS AND " .
+                                       "$idField $op= $encId)"
+                               );
+                       }
+               }
+
+               // Don't include any revisions where we're not supposed to be able to
+               // see the username.
+               $user = $this->getUser();
+               if ( !$user->isAllowed( 'deletedhistory' ) ) {
+                       $bitmask = Revision::DELETED_USER;
+               } elseif ( !$user->isAllowedAny( 'suppressrevision', 'viewsuppressed' ) ) {
+                       $bitmask = Revision::DELETED_USER | Revision::DELETED_RESTRICTED;
+               } else {
+                       $bitmask = 0;
+               }
+               if ( $bitmask ) {
+                       $this->addWhere( $db->bitAnd( 'rev_deleted', $bitmask ) . " != $bitmask" );
+               }
+
+               // Add the user field to ORDER BY if there are multiple users
+               if ( count( $users ) > 1 ) {
+                       $this->addWhereRange( $orderUserField, $this->params['dir'], null, null );
+               }
+
+               // Then timestamp
+               $this->addTimestampWhereRange( $tsField,
+                       $this->params['dir'], $this->params['start'], $this->params['end'] );
+
+               // Then rev_id for a total ordering
+               $this->addWhereRange( $idField, $this->params['dir'], null, null );
+
+               $this->addWhereFld( 'page_namespace', $this->params['namespace'] );
+
+               $show = $this->params['show'];
+               if ( $this->params['toponly'] ) { // deprecated/old param
+                       $show[] = 'top';
+               }
+               if ( !is_null( $show ) ) {
+                       $show = array_flip( $show );
+
+                       if ( ( isset( $show['minor'] ) && isset( $show['!minor'] ) )
+                               || ( isset( $show['patrolled'] ) && isset( $show['!patrolled'] ) )
+                               || ( isset( $show['autopatrolled'] ) && isset( $show['!autopatrolled'] ) )
+                               || ( isset( $show['autopatrolled'] ) && isset( $show['!patrolled'] ) )
+                               || ( isset( $show['top'] ) && isset( $show['!top'] ) )
+                               || ( isset( $show['new'] ) && isset( $show['!new'] ) )
+                       ) {
+                               $this->dieWithError( 'apierror-show' );
+                       }
+
+                       $this->addWhereIf( 'rev_minor_edit = 0', isset( $show['!minor'] ) );
+                       $this->addWhereIf( 'rev_minor_edit != 0', isset( $show['minor'] ) );
+                       $this->addWhereIf(
+                               'rc_patrolled = ' . RecentChange::PRC_UNPATROLLED,
+                               isset( $show['!patrolled'] )
+                       );
+                       $this->addWhereIf(
+                               'rc_patrolled != ' . RecentChange::PRC_UNPATROLLED,
+                               isset( $show['patrolled'] )
+                       );
+                       $this->addWhereIf(
+                               'rc_patrolled != ' . RecentChange::PRC_AUTOPATROLLED,
+                               isset( $show['!autopatrolled'] )
+                       );
+                       $this->addWhereIf(
+                               'rc_patrolled = ' . RecentChange::PRC_AUTOPATROLLED,
+                               isset( $show['autopatrolled'] )
+                       );
+                       $this->addWhereIf( $idField . ' != page_latest', isset( $show['!top'] ) );
+                       $this->addWhereIf( $idField . ' = page_latest', isset( $show['top'] ) );
+                       $this->addWhereIf( 'rev_parent_id != 0', isset( $show['!new'] ) );
+                       $this->addWhereIf( 'rev_parent_id = 0', isset( $show['new'] ) );
+               }
+               $this->addOption( 'LIMIT', $limit + 1 );
+
+               if ( isset( $show['patrolled'] ) || isset( $show['!patrolled'] ) ||
+                       isset( $show['autopatrolled'] ) || isset( $show['!autopatrolled'] ) || $this->fld_patrolled
+               ) {
+                       if ( !$user->useRCPatrol() && !$user->useNPPatrol() ) {
+                               $this->dieWithError( 'apierror-permissiondenied-patrolflag', 'permissiondenied' );
+                       }
+
+                       $isFilterset = isset( $show['patrolled'] ) || isset( $show['!patrolled'] ) ||
+                               isset( $show['autopatrolled'] ) || isset( $show['!autopatrolled'] );
+                       $this->addTables( 'recentchanges' );
+                       $this->addJoinConds( [ 'recentchanges' => [
+                               $isFilterset ? 'JOIN' : 'LEFT JOIN',
+                               [
+                                       // This is a crazy hack. recentchanges has no index on rc_this_oldid, so instead of adding
+                                       // one T19237 did a join using rc_user_text and rc_timestamp instead. Now rc_user_text is
+                                       // probably unavailable, so just do rc_timestamp.
+                                       'rc_timestamp = ' . $tsField,
+                                       'rc_this_oldid = ' . $idField,
+                               ]
+                       ] ] );
+               }
+
+               $this->addFieldsIf( 'rc_patrolled', $this->fld_patrolled );
+
+               if ( $this->fld_tags ) {
+                       $this->addTables( 'tag_summary' );
+                       $this->addJoinConds(
+                               [ 'tag_summary' => [ 'LEFT JOIN', [ $idField . ' = ts_rev_id' ] ] ]
+                       );
+                       $this->addFields( 'ts_tags' );
+               }
+
+               if ( isset( $this->params['tag'] ) ) {
+                       $this->addTables( 'change_tag' );
+                       $this->addJoinConds(
+                               [ 'change_tag' => [ 'INNER JOIN', [ $idField . ' = ct_rev_id' ] ] ]
+                       );
+                       $this->addWhereFld( 'ct_tag', $this->params['tag'] );
+               }
+
+               return true;
+       }
+
+       /**
+        * Extract fields from the database row and append them to a result array
+        *
+        * @param stdClass $row
+        * @return array
+        */
+       private function extractRowInfo( $row ) {
+               $vals = [];
+               $anyHidden = false;
+
+               if ( $row->rev_deleted & Revision::DELETED_TEXT ) {
+                       $vals['texthidden'] = true;
+                       $anyHidden = true;
+               }
+
+               // Any rows where we can't view the user were filtered out in the query.
+               $vals['userid'] = (int)$row->rev_user;
+               $vals['user'] = $row->rev_user_text;
+               if ( $row->rev_deleted & Revision::DELETED_USER ) {
+                       $vals['userhidden'] = true;
+                       $anyHidden = true;
+               }
+               if ( $this->fld_ids ) {
+                       $vals['pageid'] = intval( $row->rev_page );
+                       $vals['revid'] = intval( $row->rev_id );
+                       // $vals['textid'] = intval( $row->rev_text_id ); // todo: Should this field be exposed?
+
+                       if ( !is_null( $row->rev_parent_id ) ) {
+                               $vals['parentid'] = intval( $row->rev_parent_id );
+                       }
+               }
+
+               $title = Title::makeTitle( $row->page_namespace, $row->page_title );
+
+               if ( $this->fld_title ) {
+                       ApiQueryBase::addTitleInfo( $vals, $title );
+               }
+
+               if ( $this->fld_timestamp ) {
+                       $vals['timestamp'] = wfTimestamp( TS_ISO_8601, $row->rev_timestamp );
+               }
+
+               if ( $this->fld_flags ) {
+                       $vals['new'] = $row->rev_parent_id == 0 && !is_null( $row->rev_parent_id );
+                       $vals['minor'] = (bool)$row->rev_minor_edit;
+                       $vals['top'] = $row->page_latest == $row->rev_id;
+               }
+
+               if ( $this->fld_comment || $this->fld_parsedcomment ) {
+                       if ( $row->rev_deleted & Revision::DELETED_COMMENT ) {
+                               $vals['commenthidden'] = true;
+                               $anyHidden = true;
+                       }
+
+                       $userCanView = Revision::userCanBitfield(
+                               $row->rev_deleted,
+                               Revision::DELETED_COMMENT, $this->getUser()
+                       );
+
+                       if ( $userCanView ) {
+                               $comment = $this->commentStore->getComment( 'rev_comment', $row )->text;
+                               if ( $this->fld_comment ) {
+                                       $vals['comment'] = $comment;
+                               }
+
+                               if ( $this->fld_parsedcomment ) {
+                                       $vals['parsedcomment'] = Linker::formatComment( $comment, $title );
+                               }
+                       }
+               }
+
+               if ( $this->fld_patrolled ) {
+                       $vals['patrolled'] = $row->rc_patrolled != RecentChange::PRC_UNPATROLLED;
+                       $vals['autopatrolled'] = $row->rc_patrolled == RecentChange::PRC_AUTOPATROLLED;
+               }
+
+               if ( $this->fld_size && !is_null( $row->rev_len ) ) {
+                       $vals['size'] = intval( $row->rev_len );
+               }
+
+               if ( $this->fld_sizediff
+                       && !is_null( $row->rev_len )
+                       && !is_null( $row->rev_parent_id )
+               ) {
+                       $parentLen = isset( $this->parentLens[$row->rev_parent_id] )
+                               ? $this->parentLens[$row->rev_parent_id]
+                               : 0;
+                       $vals['sizediff'] = intval( $row->rev_len - $parentLen );
+               }
+
+               if ( $this->fld_tags ) {
+                       if ( $row->ts_tags ) {
+                               $tags = explode( ',', $row->ts_tags );
+                               ApiResult::setIndexedTagName( $tags, 'tag' );
+                               $vals['tags'] = $tags;
+                       } else {
+                               $vals['tags'] = [];
+                       }
+               }
+
+               if ( $anyHidden && $row->rev_deleted & Revision::DELETED_RESTRICTED ) {
+                       $vals['suppressed'] = true;
+               }
+
+               return $vals;
+       }
+
+       private function continueStr( $row ) {
+               if ( $this->multiUserMode ) {
+                       switch ( $this->orderBy ) {
+                               case 'id':
+                                       return "id|$row->rev_user|$row->rev_timestamp|$row->rev_id";
+                               case 'name':
+                                       return "name|$row->rev_user_text|$row->rev_timestamp|$row->rev_id";
+                               case 'actor':
+                                       return "actor|$row->rev_actor|$row->rev_timestamp|$row->rev_id";
+                       }
+               } else {
+                       return "$row->rev_timestamp|$row->rev_id";
+               }
+       }
+
+       public function getCacheMode( $params ) {
+               // This module provides access to deleted revisions and patrol flags if
+               // the requester is logged in
+               return 'anon-public-user-private';
+       }
+
+       public function getAllowedParams() {
+               return [
+                       'limit' => [
+                               ApiBase::PARAM_DFLT => 10,
+                               ApiBase::PARAM_TYPE => 'limit',
+                               ApiBase::PARAM_MIN => 1,
+                               ApiBase::PARAM_MAX => ApiBase::LIMIT_BIG1,
+                               ApiBase::PARAM_MAX2 => ApiBase::LIMIT_BIG2
+                       ],
+                       'start' => [
+                               ApiBase::PARAM_TYPE => 'timestamp'
+                       ],
+                       'end' => [
+                               ApiBase::PARAM_TYPE => 'timestamp'
+                       ],
+                       'continue' => [
+                               ApiBase::PARAM_HELP_MSG => 'api-help-param-continue',
+                       ],
+                       'user' => [
+                               ApiBase::PARAM_TYPE => 'user',
+                               ApiBase::PARAM_ISMULTI => true
+                       ],
+                       'userids' => [
+                               ApiBase::PARAM_TYPE => 'integer',
+                               ApiBase::PARAM_ISMULTI => true
+                       ],
+                       'userprefix' => null,
+                       'dir' => [
+                               ApiBase::PARAM_DFLT => 'older',
+                               ApiBase::PARAM_TYPE => [
+                                       'newer',
+                                       'older'
+                               ],
+                               ApiBase::PARAM_HELP_MSG => 'api-help-param-direction',
+                       ],
+                       'namespace' => [
+                               ApiBase::PARAM_ISMULTI => true,
+                               ApiBase::PARAM_TYPE => 'namespace'
+                       ],
+                       'prop' => [
+                               ApiBase::PARAM_ISMULTI => true,
+                               ApiBase::PARAM_DFLT => 'ids|title|timestamp|comment|size|flags',
+                               ApiBase::PARAM_TYPE => [
+                                       'ids',
+                                       'title',
+                                       'timestamp',
+                                       'comment',
+                                       'parsedcomment',
+                                       'size',
+                                       'sizediff',
+                                       'flags',
+                                       'patrolled',
+                                       'tags'
+                               ],
+                               ApiBase::PARAM_HELP_MSG_PER_VALUE => [],
+                       ],
+                       'show' => [
+                               ApiBase::PARAM_ISMULTI => true,
+                               ApiBase::PARAM_TYPE => [
+                                       'minor',
+                                       '!minor',
+                                       'patrolled',
+                                       '!patrolled',
+                                       'autopatrolled',
+                                       '!autopatrolled',
+                                       'top',
+                                       '!top',
+                                       'new',
+                                       '!new',
+                               ],
+                               ApiBase::PARAM_HELP_MSG => [
+                                       'apihelp-query+usercontribs-param-show',
+                                       $this->getConfig()->get( 'RCMaxAge' )
+                               ],
+                       ],
+                       'tag' => null,
+                       'toponly' => [
+                               ApiBase::PARAM_DFLT => false,
+                               ApiBase::PARAM_DEPRECATED => true,
+                       ],
+               ];
+       }
+
+       protected function getExamplesMessages() {
+               return [
+                       'action=query&list=usercontribs&ucuser=Example'
+                               => 'apihelp-query+usercontribs-example-user',
+                       'action=query&list=usercontribs&ucuserprefix=192.0.2.'
+                               => 'apihelp-query+usercontribs-example-ipprefix',
+               ];
+       }
+
+       public function getHelpUrls() {
+               return 'https://www.mediawiki.org/wiki/Special:MyLanguage/API:Usercontribs';
+       }
+}
+
+class_alias( ApiQueryUserContribs::class, 'ApiQueryContributions' );
diff --git a/includes/api/ApiQueryUserContributions.php b/includes/api/ApiQueryUserContributions.php
deleted file mode 100644 (file)
index 12f42ed..0000000
+++ /dev/null
@@ -1,832 +0,0 @@
-<?php
-/**
- * Copyright © 2006 Yuri Astrakhan "<Firstname><Lastname>@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
- */
-
-/**
- * This query action adds a list of a specified user's contributions to the output.
- *
- * @ingroup API
- */
-class ApiQueryContributions extends ApiQueryBase {
-
-       public function __construct( ApiQuery $query, $moduleName ) {
-               parent::__construct( $query, $moduleName, 'uc' );
-       }
-
-       private $params, $multiUserMode, $orderBy, $parentLens;
-       private $fld_ids = false, $fld_title = false, $fld_timestamp = false,
-               $fld_comment = false, $fld_parsedcomment = false, $fld_flags = false,
-               $fld_patrolled = false, $fld_tags = false, $fld_size = false, $fld_sizediff = false;
-
-       public function execute() {
-               global $wgActorTableSchemaMigrationStage;
-
-               // Parse some parameters
-               $this->params = $this->extractRequestParams();
-
-               $this->commentStore = CommentStore::getStore();
-
-               $prop = array_flip( $this->params['prop'] );
-               $this->fld_ids = isset( $prop['ids'] );
-               $this->fld_title = isset( $prop['title'] );
-               $this->fld_comment = isset( $prop['comment'] );
-               $this->fld_parsedcomment = isset( $prop['parsedcomment'] );
-               $this->fld_size = isset( $prop['size'] );
-               $this->fld_sizediff = isset( $prop['sizediff'] );
-               $this->fld_flags = isset( $prop['flags'] );
-               $this->fld_timestamp = isset( $prop['timestamp'] );
-               $this->fld_patrolled = isset( $prop['patrolled'] );
-               $this->fld_tags = isset( $prop['tags'] );
-
-               // Most of this code will use the 'contributions' group DB, which can map to replica DBs
-               // with extra user based indexes or partioning by user. The additional metadata
-               // queries should use a regular replica DB since the lookup pattern is not all by user.
-               $dbSecondary = $this->getDB(); // any random replica DB
-
-               // TODO: if the query is going only against the revision table, should this be done?
-               $this->selectNamedDB( 'contributions', DB_REPLICA, 'contributions' );
-
-               $sort = ( $this->params['dir'] == 'newer' ? '' : ' DESC' );
-               $op = ( $this->params['dir'] == 'older' ? '<' : '>' );
-
-               // Create an Iterator that produces the UserIdentity objects we need, depending
-               // on which of the 'userprefix', 'userids', or 'user' params was
-               // specified.
-               $this->requireOnlyOneParameter( $this->params, 'userprefix', 'userids', 'user' );
-               if ( isset( $this->params['userprefix'] ) ) {
-                       $this->multiUserMode = true;
-                       $this->orderBy = 'name';
-                       $fname = __METHOD__;
-
-                       // Because 'userprefix' might produce a huge number of users (e.g.
-                       // a wiki with users "Test00000001" to "Test99999999"), use a
-                       // generator with batched lookup and continuation.
-                       $userIter = call_user_func( function () use ( $dbSecondary, $sort, $op, $fname ) {
-                               global $wgActorTableSchemaMigrationStage;
-
-                               $fromName = false;
-                               if ( !is_null( $this->params['continue'] ) ) {
-                                       $continue = explode( '|', $this->params['continue'] );
-                                       $this->dieContinueUsageIf( count( $continue ) != 4 );
-                                       $this->dieContinueUsageIf( $continue[0] !== 'name' );
-                                       $fromName = $continue[1];
-                               }
-                               $like = $dbSecondary->buildLike( $this->params['userprefix'], $dbSecondary->anyString() );
-
-                               $limit = 501;
-
-                               do {
-                                       $from = $fromName ? "$op= " . $dbSecondary->addQuotes( $fromName ) : false;
-
-                                       // For the new schema, pull from the actor table. For the
-                                       // old, pull from rev_user. For migration a FULL [OUTER]
-                                       // JOIN would be what we want, except MySQL doesn't support
-                                       // that so we have to UNION instead.
-                                       if ( $wgActorTableSchemaMigrationStage === MIGRATION_NEW ) {
-                                               $res = $dbSecondary->select(
-                                                       'actor',
-                                                       [ 'actor_id', 'user_id' => 'COALESCE(actor_user,0)', 'user_name' => 'actor_name' ],
-                                                       array_merge( [ "actor_name$like" ], $from ? [ "actor_name $from" ] : [] ),
-                                                       $fname,
-                                                       [ 'ORDER BY' => [ "user_name $sort" ], 'LIMIT' => $limit ]
-                                               );
-                                       } elseif ( $wgActorTableSchemaMigrationStage === MIGRATION_OLD ) {
-                                               $res = $dbSecondary->select(
-                                                       'revision',
-                                                       [ 'actor_id' => 'NULL', 'user_id' => 'rev_user', 'user_name' => 'rev_user_text' ],
-                                                       array_merge( [ "rev_user_text$like" ], $from ? [ "rev_user_text $from" ] : [] ),
-                                                       $fname,
-                                                       [ 'DISTINCT', 'ORDER BY' => [ "rev_user_text $sort" ], 'LIMIT' => $limit ]
-                                               );
-                                       } else {
-                                               // There are three queries we have to combine to be sure of getting all results:
-                                               //  - actor table (any rows that have been migrated will have empty rev_user_text)
-                                               //  - revision+actor by user id
-                                               //  - revision+actor by name for anons
-                                               $options = $dbSecondary->unionSupportsOrderAndLimit()
-                                                       ? [ 'ORDER BY' => [ "user_name $sort" ], 'LIMIT' => $limit ] : [];
-                                               $subsql = [];
-                                               $subsql[] = $dbSecondary->selectSQLText(
-                                                       'actor',
-                                                       [ 'actor_id', 'user_id' => 'COALESCE(actor_user,0)', 'user_name' => 'actor_name' ],
-                                                       array_merge( [ "actor_name$like" ], $from ? [ "actor_name $from" ] : [] ),
-                                                       $fname,
-                                                       $options
-                                               );
-                                               $subsql[] = $dbSecondary->selectSQLText(
-                                                       [ 'revision', 'actor' ],
-                                                       [ 'actor_id', 'user_id' => 'rev_user', 'user_name' => 'rev_user_text' ],
-                                                       array_merge(
-                                                               [ "rev_user_text$like", 'rev_user != 0' ],
-                                                               $from ? [ "rev_user_text $from" ] : []
-                                                       ),
-                                                       $fname,
-                                                       array_merge( [ 'DISTINCT' ], $options ),
-                                                       [ 'actor' => [ 'LEFT JOIN', 'rev_user = actor_user' ] ]
-                                               );
-                                               $subsql[] = $dbSecondary->selectSQLText(
-                                                       [ 'revision', 'actor' ],
-                                                       [ 'actor_id', 'user_id' => 'rev_user', 'user_name' => 'rev_user_text' ],
-                                                       array_merge(
-                                                               [ "rev_user_text$like", 'rev_user = 0' ],
-                                                               $from ? [ "rev_user_text $from" ] : []
-                                                       ),
-                                                       $fname,
-                                                       array_merge( [ 'DISTINCT' ], $options ),
-                                                       [ 'actor' => [ 'LEFT JOIN', 'rev_user_text = actor_name' ] ]
-                                               );
-                                               $sql = $dbSecondary->unionQueries( $subsql, false ) . " ORDER BY user_name $sort";
-                                               $sql = $dbSecondary->limitResult( $sql, $limit );
-                                               $res = $dbSecondary->query( $sql, $fname );
-                                       }
-
-                                       $count = 0;
-                                       $fromName = false;
-                                       foreach ( $res as $row ) {
-                                               if ( ++$count >= $limit ) {
-                                                       $fromName = $row->user_name;
-                                                       break;
-                                               }
-                                               yield User::newFromRow( $row );
-                                       }
-                               } while ( $fromName !== false );
-                       } );
-                       // Do the actual sorting client-side, because otherwise
-                       // prepareQuery might try to sort by actor and confuse everything.
-                       $batchSize = 1;
-               } elseif ( isset( $this->params['userids'] ) ) {
-                       if ( !count( $this->params['userids'] ) ) {
-                               $encParamName = $this->encodeParamName( 'userids' );
-                               $this->dieWithError( [ 'apierror-paramempty', $encParamName ], "paramempty_$encParamName" );
-                       }
-
-                       $ids = [];
-                       foreach ( $this->params['userids'] as $uid ) {
-                               if ( $uid <= 0 ) {
-                                       $this->dieWithError( [ 'apierror-invaliduserid', $uid ], 'invaliduserid' );
-                               }
-                               $ids[] = $uid;
-                       }
-
-                       $this->orderBy = 'id';
-                       $this->multiUserMode = count( $ids ) > 1;
-
-                       $from = $fromId = false;
-                       if ( $this->multiUserMode && !is_null( $this->params['continue'] ) ) {
-                               $continue = explode( '|', $this->params['continue'] );
-                               $this->dieContinueUsageIf( count( $continue ) != 4 );
-                               $this->dieContinueUsageIf( $continue[0] !== 'id' && $continue[0] !== 'actor' );
-                               $fromId = (int)$continue[1];
-                               $this->dieContinueUsageIf( $continue[1] !== (string)$fromId );
-                               $from = "$op= $fromId";
-                       }
-
-                       // For the new schema, just select from the actor table. For the
-                       // old and transitional schemas, select from user and left join
-                       // actor if it exists.
-                       if ( $wgActorTableSchemaMigrationStage === MIGRATION_NEW ) {
-                               $res = $dbSecondary->select(
-                                       'actor',
-                                       [ 'actor_id', 'user_id' => 'actor_user', 'user_name' => 'actor_name' ],
-                                       array_merge( [ 'actor_user' => $ids ], $from ? [ "actor_id $from" ] : [] ),
-                                       __METHOD__,
-                                       [ 'ORDER BY' => "user_id $sort" ]
-                               );
-                       } elseif ( $wgActorTableSchemaMigrationStage === MIGRATION_OLD ) {
-                               $res = $dbSecondary->select(
-                                       'user',
-                                       [ 'actor_id' => 'NULL', 'user_id' => 'user_id', 'user_name' => 'user_name' ],
-                                       array_merge( [ 'user_id' => $ids ], $from ? [ "user_id $from" ] : [] ),
-                                       __METHOD__,
-                                       [ 'ORDER BY' => "user_id $sort" ]
-                               );
-                       } else {
-                               $res = $dbSecondary->select(
-                                       [ 'user', 'actor' ],
-                                       [ 'actor_id', 'user_id', 'user_name' ],
-                                       array_merge( [ 'user_id' => $ids ], $from ? [ "user_id $from" ] : [] ),
-                                       __METHOD__,
-                                       [ 'ORDER BY' => "user_id $sort" ],
-                                       [ 'actor' => [ 'LEFT JOIN', 'actor_user = user_id' ] ]
-                               );
-                       }
-                       $userIter = UserArray::newFromResult( $res );
-                       $batchSize = count( $ids );
-               } else {
-                       $names = [];
-                       if ( !count( $this->params['user'] ) ) {
-                               $encParamName = $this->encodeParamName( 'user' );
-                               $this->dieWithError(
-                                       [ 'apierror-paramempty', $encParamName ], "paramempty_$encParamName"
-                               );
-                       }
-                       foreach ( $this->params['user'] as $u ) {
-                               if ( $u === '' ) {
-                                       $encParamName = $this->encodeParamName( 'user' );
-                                       $this->dieWithError(
-                                               [ 'apierror-paramempty', $encParamName ], "paramempty_$encParamName"
-                                       );
-                               }
-
-                               if ( User::isIP( $u ) || ExternalUserNames::isExternal( $u ) ) {
-                                       $names[$u] = null;
-                               } else {
-                                       $name = User::getCanonicalName( $u, 'valid' );
-                                       if ( $name === false ) {
-                                               $encParamName = $this->encodeParamName( 'user' );
-                                               $this->dieWithError(
-                                                       [ 'apierror-baduser', $encParamName, wfEscapeWikiText( $u ) ], "baduser_$encParamName"
-                                               );
-                                       }
-                                       $names[$name] = null;
-                               }
-                       }
-
-                       $this->orderBy = 'name';
-                       $this->multiUserMode = count( $names ) > 1;
-
-                       $from = $fromName = false;
-                       if ( $this->multiUserMode && !is_null( $this->params['continue'] ) ) {
-                               $continue = explode( '|', $this->params['continue'] );
-                               $this->dieContinueUsageIf( count( $continue ) != 4 );
-                               $this->dieContinueUsageIf( $continue[0] !== 'name' && $continue[0] !== 'actor' );
-                               $fromName = $continue[1];
-                               $from = "$op= " . $dbSecondary->addQuotes( $fromName );
-                       }
-
-                       // For the new schema, just select from the actor table. For the
-                       // old and transitional schemas, select from user and left join
-                       // actor if it exists then merge in any unknown users (IPs and imports).
-                       if ( $wgActorTableSchemaMigrationStage === MIGRATION_NEW ) {
-                               $res = $dbSecondary->select(
-                                       'actor',
-                                       [ 'actor_id', 'user_id' => 'actor_user', 'user_name' => 'actor_name' ],
-                                       array_merge( [ 'actor_name' => array_keys( $names ) ], $from ? [ "actor_id $from" ] : [] ),
-                                       __METHOD__,
-                                       [ 'ORDER BY' => "actor_name $sort" ]
-                               );
-                               $userIter = UserArray::newFromResult( $res );
-                       } else {
-                               if ( $wgActorTableSchemaMigrationStage === MIGRATION_OLD ) {
-                                       $res = $dbSecondary->select(
-                                               'user',
-                                               [ 'actor_id' => 'NULL', 'user_id', 'user_name' ],
-                                               array_merge( [ 'user_name' => array_keys( $names ) ], $from ? [ "user_name $from" ] : [] ),
-                                               __METHOD__
-                                       );
-                               } else {
-                                       $res = $dbSecondary->select(
-                                               [ 'user', 'actor' ],
-                                               [ 'actor_id', 'user_id', 'user_name' ],
-                                               array_merge( [ 'user_name' => array_keys( $names ) ], $from ? [ "user_name $from" ] : [] ),
-                                               __METHOD__,
-                                               [],
-                                               [ 'actor' => [ 'LEFT JOIN', 'actor_user = user_id' ] ]
-                                       );
-                               }
-                               foreach ( $res as $row ) {
-                                       $names[$row->user_name] = $row;
-                               }
-                               call_user_func_array(
-                                       $this->params['dir'] == 'newer' ? 'ksort' : 'krsort', [ &$names, SORT_STRING ]
-                               );
-                               $neg = $op === '>' ? -1 : 1;
-                               $userIter = call_user_func( function () use ( $names, $fromName, $neg ) {
-                                       foreach ( $names as $name => $row ) {
-                                               if ( $fromName === false || $neg * strcmp( $name, $fromName ) <= 0 ) {
-                                                       $user = $row ? User::newFromRow( $row ) : User::newFromName( $name, false );
-                                                       yield $user;
-                                               }
-                                       }
-                               } );
-                       }
-                       $batchSize = count( $names );
-               }
-
-               // During migration, force ordering on the client side because we're
-               // having to combine multiple queries that would otherwise have
-               // different sort orders.
-               if ( $wgActorTableSchemaMigrationStage === MIGRATION_WRITE_BOTH ||
-                       $wgActorTableSchemaMigrationStage === MIGRATION_WRITE_NEW
-               ) {
-                       $batchSize = 1;
-               }
-
-               // With the new schema, the DB query will order by actor so update $this->orderBy to match.
-               if ( $batchSize > 1 && $wgActorTableSchemaMigrationStage === MIGRATION_NEW ) {
-                       $this->orderBy = 'actor';
-               }
-
-               $count = 0;
-               $limit = $this->params['limit'];
-               $userIter->rewind();
-               while ( $userIter->valid() ) {
-                       $users = [];
-                       while ( count( $users ) < $batchSize && $userIter->valid() ) {
-                               $users[] = $userIter->current();
-                               $userIter->next();
-                       }
-
-                       // Ugh. We have to run the query three times, once for each
-                       // possible 'orcond' from ActorMigration, and then merge them all
-                       // together in the proper order. And preserving the correct
-                       // $hookData for each one.
-                       // @todo When ActorMigration is removed, this can go back to a
-                       //  single prepare and select.
-                       $merged = [];
-                       foreach ( [ 'actor', 'userid', 'username' ] as $which ) {
-                               if ( $this->prepareQuery( $users, $limit - $count, $which ) ) {
-                                       $hookData = [];
-                                       $res = $this->select( __METHOD__, [], $hookData );
-                                       foreach ( $res as $row ) {
-                                               $merged[] = [ $row, &$hookData ];
-                                       }
-                               }
-                       }
-                       $neg = $this->params['dir'] == 'newer' ? 1 : -1;
-                       usort( $merged, function ( $a, $b ) use ( $neg, $batchSize ) {
-                               if ( $batchSize === 1 ) { // One user, can't be different
-                                       $ret = 0;
-                               } elseif ( $this->orderBy === 'id' ) {
-                                       $ret = $a[0]->rev_user - $b[0]->rev_user;
-                               } elseif ( $this->orderBy === 'name' ) {
-                                       $ret = strcmp( $a[0]->rev_user_text, $b[0]->rev_user_text );
-                               } else {
-                                       $ret = $a[0]->rev_actor - $b[0]->rev_actor;
-                               }
-
-                               if ( !$ret ) {
-                                       $ret = strcmp(
-                                               wfTimestamp( TS_MW, $a[0]->rev_timestamp ),
-                                               wfTimestamp( TS_MW, $b[0]->rev_timestamp )
-                                       );
-                               }
-
-                               if ( !$ret ) {
-                                       $ret = $a[0]->rev_id - $b[0]->rev_id;
-                               }
-
-                               return $neg * $ret;
-                       } );
-                       $merged = array_slice( $merged, 0, $limit - $count + 1 );
-                       // (end "Ugh")
-
-                       if ( $this->fld_sizediff ) {
-                               $revIds = [];
-                               foreach ( $merged as $data ) {
-                                       if ( $data[0]->rev_parent_id ) {
-                                               $revIds[] = $data[0]->rev_parent_id;
-                                       }
-                               }
-                               $this->parentLens = Revision::getParentLengths( $dbSecondary, $revIds );
-                       }
-
-                       foreach ( $merged as $data ) {
-                               $row = $data[0];
-                               $hookData = &$data[1];
-                               if ( ++$count > $limit ) {
-                                       // We've reached the one extra which shows that there are
-                                       // additional pages to be had. Stop here...
-                                       $this->setContinueEnumParameter( 'continue', $this->continueStr( $row ) );
-                                       break 2;
-                               }
-
-                               $vals = $this->extractRowInfo( $row );
-                               $fit = $this->processRow( $row, $vals, $hookData ) &&
-                                       $this->getResult()->addValue( [ 'query', $this->getModuleName() ], null, $vals );
-                               if ( !$fit ) {
-                                       $this->setContinueEnumParameter( 'continue', $this->continueStr( $row ) );
-                                       break 2;
-                               }
-                       }
-               }
-
-               $this->getResult()->addIndexedTagName( [ 'query', $this->getModuleName() ], 'item' );
-       }
-
-       /**
-        * Prepares the query and returns the limit of rows requested
-        * @param User[] $users
-        * @param int $limit
-        * @param string $which 'actor', 'userid', or 'username'
-        * @return bool
-        */
-       private function prepareQuery( array $users, $limit, $which ) {
-               global $wgActorTableSchemaMigrationStage;
-
-               $this->resetQueryParams();
-               $db = $this->getDB();
-
-               $revQuery = Revision::getQueryInfo( [ 'page' ] );
-               $this->addTables( $revQuery['tables'] );
-               $this->addJoinConds( $revQuery['joins'] );
-               $this->addFields( $revQuery['fields'] );
-
-               $revWhere = ActorMigration::newMigration()->getWhere( $db, 'rev_user', $users );
-               if ( !isset( $revWhere['orconds'][$which] ) ) {
-                       return false;
-               }
-               $this->addWhere( $revWhere['orconds'][$which] );
-
-               if ( $wgActorTableSchemaMigrationStage === MIGRATION_NEW ) {
-                       $orderUserField = 'rev_actor';
-                       $userField = $this->orderBy === 'actor' ? 'revactor_actor' : 'actor_name';
-               } else {
-                       $orderUserField = $this->orderBy === 'id' ? 'rev_user' : 'rev_user_text';
-                       $userField = $revQuery['fields'][$orderUserField];
-               }
-               if ( $which === 'actor' ) {
-                       $tsField = 'revactor_timestamp';
-                       $idField = 'revactor_rev';
-               } else {
-                       $tsField = 'rev_timestamp';
-                       $idField = 'rev_id';
-               }
-
-               // Handle continue parameter
-               if ( !is_null( $this->params['continue'] ) ) {
-                       $continue = explode( '|', $this->params['continue'] );
-                       if ( $this->multiUserMode ) {
-                               $this->dieContinueUsageIf( count( $continue ) != 4 );
-                               $modeFlag = array_shift( $continue );
-                               $this->dieContinueUsageIf( $modeFlag !== $this->orderBy );
-                               $encUser = $db->addQuotes( array_shift( $continue ) );
-                       } else {
-                               $this->dieContinueUsageIf( count( $continue ) != 2 );
-                       }
-                       $encTS = $db->addQuotes( $db->timestamp( $continue[0] ) );
-                       $encId = (int)$continue[1];
-                       $this->dieContinueUsageIf( $encId != $continue[1] );
-                       $op = ( $this->params['dir'] == 'older' ? '<' : '>' );
-                       if ( $this->multiUserMode ) {
-                               $this->addWhere(
-                                       "$userField $op $encUser OR " .
-                                       "($userField = $encUser AND " .
-                                       "($tsField $op $encTS OR " .
-                                       "($tsField = $encTS AND " .
-                                       "$idField $op= $encId)))"
-                               );
-                       } else {
-                               $this->addWhere(
-                                       "$tsField $op $encTS OR " .
-                                       "($tsField = $encTS AND " .
-                                       "$idField $op= $encId)"
-                               );
-                       }
-               }
-
-               // Don't include any revisions where we're not supposed to be able to
-               // see the username.
-               $user = $this->getUser();
-               if ( !$user->isAllowed( 'deletedhistory' ) ) {
-                       $bitmask = Revision::DELETED_USER;
-               } elseif ( !$user->isAllowedAny( 'suppressrevision', 'viewsuppressed' ) ) {
-                       $bitmask = Revision::DELETED_USER | Revision::DELETED_RESTRICTED;
-               } else {
-                       $bitmask = 0;
-               }
-               if ( $bitmask ) {
-                       $this->addWhere( $db->bitAnd( 'rev_deleted', $bitmask ) . " != $bitmask" );
-               }
-
-               // Add the user field to ORDER BY if there are multiple users
-               if ( count( $users ) > 1 ) {
-                       $this->addWhereRange( $orderUserField, $this->params['dir'], null, null );
-               }
-
-               // Then timestamp
-               $this->addTimestampWhereRange( $tsField,
-                       $this->params['dir'], $this->params['start'], $this->params['end'] );
-
-               // Then rev_id for a total ordering
-               $this->addWhereRange( $idField, $this->params['dir'], null, null );
-
-               $this->addWhereFld( 'page_namespace', $this->params['namespace'] );
-
-               $show = $this->params['show'];
-               if ( $this->params['toponly'] ) { // deprecated/old param
-                       $show[] = 'top';
-               }
-               if ( !is_null( $show ) ) {
-                       $show = array_flip( $show );
-
-                       if ( ( isset( $show['minor'] ) && isset( $show['!minor'] ) )
-                               || ( isset( $show['patrolled'] ) && isset( $show['!patrolled'] ) )
-                               || ( isset( $show['autopatrolled'] ) && isset( $show['!autopatrolled'] ) )
-                               || ( isset( $show['autopatrolled'] ) && isset( $show['!patrolled'] ) )
-                               || ( isset( $show['top'] ) && isset( $show['!top'] ) )
-                               || ( isset( $show['new'] ) && isset( $show['!new'] ) )
-                       ) {
-                               $this->dieWithError( 'apierror-show' );
-                       }
-
-                       $this->addWhereIf( 'rev_minor_edit = 0', isset( $show['!minor'] ) );
-                       $this->addWhereIf( 'rev_minor_edit != 0', isset( $show['minor'] ) );
-                       $this->addWhereIf(
-                               'rc_patrolled = ' . RecentChange::PRC_UNPATROLLED,
-                               isset( $show['!patrolled'] )
-                       );
-                       $this->addWhereIf(
-                               'rc_patrolled != ' . RecentChange::PRC_UNPATROLLED,
-                               isset( $show['patrolled'] )
-                       );
-                       $this->addWhereIf(
-                               'rc_patrolled != ' . RecentChange::PRC_AUTOPATROLLED,
-                               isset( $show['!autopatrolled'] )
-                       );
-                       $this->addWhereIf(
-                               'rc_patrolled = ' . RecentChange::PRC_AUTOPATROLLED,
-                               isset( $show['autopatrolled'] )
-                       );
-                       $this->addWhereIf( $idField . ' != page_latest', isset( $show['!top'] ) );
-                       $this->addWhereIf( $idField . ' = page_latest', isset( $show['top'] ) );
-                       $this->addWhereIf( 'rev_parent_id != 0', isset( $show['!new'] ) );
-                       $this->addWhereIf( 'rev_parent_id = 0', isset( $show['new'] ) );
-               }
-               $this->addOption( 'LIMIT', $limit + 1 );
-
-               if ( isset( $show['patrolled'] ) || isset( $show['!patrolled'] ) ||
-                       isset( $show['autopatrolled'] ) || isset( $show['!autopatrolled'] ) || $this->fld_patrolled
-               ) {
-                       if ( !$user->useRCPatrol() && !$user->useNPPatrol() ) {
-                               $this->dieWithError( 'apierror-permissiondenied-patrolflag', 'permissiondenied' );
-                       }
-
-                       $isFilterset = isset( $show['patrolled'] ) || isset( $show['!patrolled'] ) ||
-                               isset( $show['autopatrolled'] ) || isset( $show['!autopatrolled'] );
-                       $this->addTables( 'recentchanges' );
-                       $this->addJoinConds( [ 'recentchanges' => [
-                               $isFilterset ? 'JOIN' : 'LEFT JOIN',
-                               [
-                                       // This is a crazy hack. recentchanges has no index on rc_this_oldid, so instead of adding
-                                       // one T19237 did a join using rc_user_text and rc_timestamp instead. Now rc_user_text is
-                                       // probably unavailable, so just do rc_timestamp.
-                                       'rc_timestamp = ' . $tsField,
-                                       'rc_this_oldid = ' . $idField,
-                               ]
-                       ] ] );
-               }
-
-               $this->addFieldsIf( 'rc_patrolled', $this->fld_patrolled );
-
-               if ( $this->fld_tags ) {
-                       $this->addTables( 'tag_summary' );
-                       $this->addJoinConds(
-                               [ 'tag_summary' => [ 'LEFT JOIN', [ $idField . ' = ts_rev_id' ] ] ]
-                       );
-                       $this->addFields( 'ts_tags' );
-               }
-
-               if ( isset( $this->params['tag'] ) ) {
-                       $this->addTables( 'change_tag' );
-                       $this->addJoinConds(
-                               [ 'change_tag' => [ 'INNER JOIN', [ $idField . ' = ct_rev_id' ] ] ]
-                       );
-                       $this->addWhereFld( 'ct_tag', $this->params['tag'] );
-               }
-
-               return true;
-       }
-
-       /**
-        * Extract fields from the database row and append them to a result array
-        *
-        * @param stdClass $row
-        * @return array
-        */
-       private function extractRowInfo( $row ) {
-               $vals = [];
-               $anyHidden = false;
-
-               if ( $row->rev_deleted & Revision::DELETED_TEXT ) {
-                       $vals['texthidden'] = true;
-                       $anyHidden = true;
-               }
-
-               // Any rows where we can't view the user were filtered out in the query.
-               $vals['userid'] = (int)$row->rev_user;
-               $vals['user'] = $row->rev_user_text;
-               if ( $row->rev_deleted & Revision::DELETED_USER ) {
-                       $vals['userhidden'] = true;
-                       $anyHidden = true;
-               }
-               if ( $this->fld_ids ) {
-                       $vals['pageid'] = intval( $row->rev_page );
-                       $vals['revid'] = intval( $row->rev_id );
-                       // $vals['textid'] = intval( $row->rev_text_id ); // todo: Should this field be exposed?
-
-                       if ( !is_null( $row->rev_parent_id ) ) {
-                               $vals['parentid'] = intval( $row->rev_parent_id );
-                       }
-               }
-
-               $title = Title::makeTitle( $row->page_namespace, $row->page_title );
-
-               if ( $this->fld_title ) {
-                       ApiQueryBase::addTitleInfo( $vals, $title );
-               }
-
-               if ( $this->fld_timestamp ) {
-                       $vals['timestamp'] = wfTimestamp( TS_ISO_8601, $row->rev_timestamp );
-               }
-
-               if ( $this->fld_flags ) {
-                       $vals['new'] = $row->rev_parent_id == 0 && !is_null( $row->rev_parent_id );
-                       $vals['minor'] = (bool)$row->rev_minor_edit;
-                       $vals['top'] = $row->page_latest == $row->rev_id;
-               }
-
-               if ( $this->fld_comment || $this->fld_parsedcomment ) {
-                       if ( $row->rev_deleted & Revision::DELETED_COMMENT ) {
-                               $vals['commenthidden'] = true;
-                               $anyHidden = true;
-                       }
-
-                       $userCanView = Revision::userCanBitfield(
-                               $row->rev_deleted,
-                               Revision::DELETED_COMMENT, $this->getUser()
-                       );
-
-                       if ( $userCanView ) {
-                               $comment = $this->commentStore->getComment( 'rev_comment', $row )->text;
-                               if ( $this->fld_comment ) {
-                                       $vals['comment'] = $comment;
-                               }
-
-                               if ( $this->fld_parsedcomment ) {
-                                       $vals['parsedcomment'] = Linker::formatComment( $comment, $title );
-                               }
-                       }
-               }
-
-               if ( $this->fld_patrolled ) {
-                       $vals['patrolled'] = $row->rc_patrolled != RecentChange::PRC_UNPATROLLED;
-                       $vals['autopatrolled'] = $row->rc_patrolled == RecentChange::PRC_AUTOPATROLLED;
-               }
-
-               if ( $this->fld_size && !is_null( $row->rev_len ) ) {
-                       $vals['size'] = intval( $row->rev_len );
-               }
-
-               if ( $this->fld_sizediff
-                       && !is_null( $row->rev_len )
-                       && !is_null( $row->rev_parent_id )
-               ) {
-                       $parentLen = isset( $this->parentLens[$row->rev_parent_id] )
-                               ? $this->parentLens[$row->rev_parent_id]
-                               : 0;
-                       $vals['sizediff'] = intval( $row->rev_len - $parentLen );
-               }
-
-               if ( $this->fld_tags ) {
-                       if ( $row->ts_tags ) {
-                               $tags = explode( ',', $row->ts_tags );
-                               ApiResult::setIndexedTagName( $tags, 'tag' );
-                               $vals['tags'] = $tags;
-                       } else {
-                               $vals['tags'] = [];
-                       }
-               }
-
-               if ( $anyHidden && $row->rev_deleted & Revision::DELETED_RESTRICTED ) {
-                       $vals['suppressed'] = true;
-               }
-
-               return $vals;
-       }
-
-       private function continueStr( $row ) {
-               if ( $this->multiUserMode ) {
-                       switch ( $this->orderBy ) {
-                               case 'id':
-                                       return "id|$row->rev_user|$row->rev_timestamp|$row->rev_id";
-                               case 'name':
-                                       return "name|$row->rev_user_text|$row->rev_timestamp|$row->rev_id";
-                               case 'actor':
-                                       return "actor|$row->rev_actor|$row->rev_timestamp|$row->rev_id";
-                       }
-               } else {
-                       return "$row->rev_timestamp|$row->rev_id";
-               }
-       }
-
-       public function getCacheMode( $params ) {
-               // This module provides access to deleted revisions and patrol flags if
-               // the requester is logged in
-               return 'anon-public-user-private';
-       }
-
-       public function getAllowedParams() {
-               return [
-                       'limit' => [
-                               ApiBase::PARAM_DFLT => 10,
-                               ApiBase::PARAM_TYPE => 'limit',
-                               ApiBase::PARAM_MIN => 1,
-                               ApiBase::PARAM_MAX => ApiBase::LIMIT_BIG1,
-                               ApiBase::PARAM_MAX2 => ApiBase::LIMIT_BIG2
-                       ],
-                       'start' => [
-                               ApiBase::PARAM_TYPE => 'timestamp'
-                       ],
-                       'end' => [
-                               ApiBase::PARAM_TYPE => 'timestamp'
-                       ],
-                       'continue' => [
-                               ApiBase::PARAM_HELP_MSG => 'api-help-param-continue',
-                       ],
-                       'user' => [
-                               ApiBase::PARAM_TYPE => 'user',
-                               ApiBase::PARAM_ISMULTI => true
-                       ],
-                       'userids' => [
-                               ApiBase::PARAM_TYPE => 'integer',
-                               ApiBase::PARAM_ISMULTI => true
-                       ],
-                       'userprefix' => null,
-                       'dir' => [
-                               ApiBase::PARAM_DFLT => 'older',
-                               ApiBase::PARAM_TYPE => [
-                                       'newer',
-                                       'older'
-                               ],
-                               ApiBase::PARAM_HELP_MSG => 'api-help-param-direction',
-                       ],
-                       'namespace' => [
-                               ApiBase::PARAM_ISMULTI => true,
-                               ApiBase::PARAM_TYPE => 'namespace'
-                       ],
-                       'prop' => [
-                               ApiBase::PARAM_ISMULTI => true,
-                               ApiBase::PARAM_DFLT => 'ids|title|timestamp|comment|size|flags',
-                               ApiBase::PARAM_TYPE => [
-                                       'ids',
-                                       'title',
-                                       'timestamp',
-                                       'comment',
-                                       'parsedcomment',
-                                       'size',
-                                       'sizediff',
-                                       'flags',
-                                       'patrolled',
-                                       'tags'
-                               ],
-                               ApiBase::PARAM_HELP_MSG_PER_VALUE => [],
-                       ],
-                       'show' => [
-                               ApiBase::PARAM_ISMULTI => true,
-                               ApiBase::PARAM_TYPE => [
-                                       'minor',
-                                       '!minor',
-                                       'patrolled',
-                                       '!patrolled',
-                                       'autopatrolled',
-                                       '!autopatrolled',
-                                       'top',
-                                       '!top',
-                                       'new',
-                                       '!new',
-                               ],
-                               ApiBase::PARAM_HELP_MSG => [
-                                       'apihelp-query+usercontribs-param-show',
-                                       $this->getConfig()->get( 'RCMaxAge' )
-                               ],
-                       ],
-                       'tag' => null,
-                       'toponly' => [
-                               ApiBase::PARAM_DFLT => false,
-                               ApiBase::PARAM_DEPRECATED => true,
-                       ],
-               ];
-       }
-
-       protected function getExamplesMessages() {
-               return [
-                       'action=query&list=usercontribs&ucuser=Example'
-                               => 'apihelp-query+usercontribs-example-user',
-                       'action=query&list=usercontribs&ucuserprefix=192.0.2.'
-                               => 'apihelp-query+usercontribs-example-ipprefix',
-               ];
-       }
-
-       public function getHelpUrls() {
-               return 'https://www.mediawiki.org/wiki/Special:MyLanguage/API:Usercontribs';
-       }
-}
index 4067704..13d392e 100644 (file)
        "apihelp-query+iwlinks-param-limit": "Wie viele Interwiki-Links zurückgegeben werden sollen.",
        "apihelp-query+iwlinks-param-prefix": "Gibt nur Interwiki-Links mit diesem Präfix zurück.",
        "apihelp-query+iwlinks-param-dir": "Die Auflistungsrichtung.",
+       "apihelp-query+langbacklinks-param-lang": "Sprache für den Sprachlink.",
        "apihelp-query+langbacklinks-param-limit": "Wie viele Gesamtseiten zurückgegeben werden sollen.",
        "apihelp-query+langbacklinks-param-prop": "Zurückzugebende Eigenschaften:",
        "apihelp-query+langbacklinks-paramvalue-prop-lltitle": "Ergänzt den Titel des Sprachlinks.",
index 5d0c27a..8328006 100644 (file)
@@ -30,7 +30,8 @@
                        "Fortega",
                        "Luzcaru",
                        "Javiersanp",
-                       "KATRINE1992"
+                       "KATRINE1992",
+                       "Adjen"
                ]
        },
        "apihelp-main-extended-description": "<div class=\"hlist plainlinks api-main-links\">\n* [[mw:Special:MyLanguage/API:Main_page|Documentation]]\n* [[mw:Special:MyLanguage/API:FAQ|FAQ]]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api Mailing list]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce API Announcements]\n* [https://phabricator.wikimedia.org/maniphest/query/GebfyV4uCaLd/#R Bugs & requests]\n</div>\n<strong>Status:</strong> Todas las funciones mostradas en esta página deberían estar funcionando, pero la API aún está en desarrollo activo, y puede cambiar en cualquier momento. Suscribase a [https://lists.wikimedia.org/pipermail/mediawiki-api-announce/ the mediawiki-api-announce mailing list] para aviso de actualizaciones.\n\n<strong>Erroneous requests:</strong> Cuando se envían solicitudes erróneas a la API, se enviará un encabezado HTTP con la clave \"MediaWiki-API-Error\" y, luego, el valor del encabezado y el código de error devuelto se establecerán en el mismo valor. Para más información ver [[mw:Special:MyLanguage/API:Errors_and_warnings|API: Errors and warnings]].\n\n<strong>Testing:</strong> Para facilitar la comprobación de las solicitudes de API, consulte [[Special:ApiSandbox]].",
        "apihelp-query+recentchanges-param-limit": "Cuántos cambios en total se devolverán.",
        "apihelp-query+recentchanges-param-type": "Cuántos tipos de cambios se mostrarán.",
        "apihelp-query+recentchanges-param-toponly": "Enumerar solo las modificaciones que sean las últimas revisiones.",
+       "apihelp-query+recentchanges-param-title": "Filtrar entradas mostrando solo aquellas relacionadas con una página.",
        "apihelp-query+recentchanges-param-generaterevisions": "Cuando se utilice como generador, genera identificadores de revisión en lugar de títulos. Las entradas en la lista de cambios recientes que no tengan identificador de revisión asociado (por ejemplo, la mayoría de las entradas de registro) no generarán nada.",
        "apihelp-query+recentchanges-example-simple": "Lista de cambios recientes.",
        "apihelp-query+recentchanges-example-generator": "Obtener información de página de cambios recientes no patrullados.",
        "apierror-systemblocked": "Has sido bloqueado automáticamente por el software MediaWiki.",
        "apierror-templateexpansion-notwikitext": "La expansión de plantillas solo es compatible con el contenido en wikitexto. $1 usa el modelo de contenido $2.",
        "apierror-timeout": "El servidor no respondió en el plazo previsto.",
+       "apierror-toomanyvalues": "Se proporcionaron demasiados valores al parámetro <var>$1</var>. El límite es de $2.",
        "apierror-unknownaction": "La acción especificada, <kbd>$1</kbd>, no está reconocida.",
        "apierror-unknownerror-editpage": "Error de EditPage desconocido: $1.",
        "apierror-unknownerror-nocode": "Error desconocido.",
index 1cf340a..cc31e7b 100644 (file)
        "apihelp-query+recentchanges-param-limit": "Combien de modifications renvoyer au total.",
        "apihelp-query+recentchanges-param-type": "Quels types de modification afficher.",
        "apihelp-query+recentchanges-param-toponly": "Lister uniquement les modifications qui sont de la dernière révision.",
+       "apihelp-query+recentchanges-param-title": "Filtrer les entrées vers celles relatives à une page.",
        "apihelp-query+recentchanges-param-generaterevisions": "Utilisé comme générateur, générer des IDs de révision plutôt que des titres.\nLes entrées de modification récentes sans IDs de révision associé (par ex. la plupart des entrées de journaux) ne généreront rien.",
        "apihelp-query+recentchanges-example-simple": "Lister les modifications récentes",
        "apihelp-query+recentchanges-example-generator": "Obtenir l’information de page sur les modifications récentes non relues.",
index bfb0ecf..65c3cff 100644 (file)
        "apihelp-query+recentchanges-param-limit": "Quantas alterações a serem retornadas.",
        "apihelp-query+recentchanges-param-type": "Quais tipos de mudanças mostrar.",
        "apihelp-query+recentchanges-param-toponly": "Somente lista as alterações que são as últimas revisões.",
+       "apihelp-query+recentchanges-param-title": "Filtre as entradas para aquelas relacionadas a uma página.",
        "apihelp-query+recentchanges-param-generaterevisions": "Quando usado como gerador, gere IDs de revisão em vez de títulos. As entradas de alterações recentes sem IDs de revisão associadas (por exemplo, a maioria das entradas de log) não gerarão nada.",
        "apihelp-query+recentchanges-example-simple": "Listar mudanças recentes.",
        "apihelp-query+recentchanges-example-generator": "Obter informações da página sobre as mudanças recentes não patrulhadas.",
index b7e0e52..0f159fb 100644 (file)
        "apihelp-query+recentchanges-param-limit": "O número total de mudanças a serem devolvidas.",
        "apihelp-query+recentchanges-param-type": "Os tipos de mudanças a serem mostradas.",
        "apihelp-query+recentchanges-param-toponly": "Listar só as alterações que são a revisão mais recente.",
+       "apihelp-query+recentchanges-param-title": "Filtrar as entradas para produzir só as relacionadas com uma página.",
        "apihelp-query+recentchanges-param-generaterevisions": "Ao ser usado como gerador, gerar identificadores de revisões em vez de títulos. As entradas das mudanças recentes que não tenham identificadores de revisão associados (por exemplo, a maioria das entradas do registo) não geram nada.",
        "apihelp-query+recentchanges-example-simple": "Listar as mudanças recentes.",
        "apihelp-query+recentchanges-example-generator": "Obter informação de página acerca das mudanças recentes não patrulhadas.",
index e442d61..91aac43 100644 (file)
@@ -31,7 +31,8 @@
                        "Mouse21",
                        "Happy13241",
                        "Ole Yves",
-                       "AttemptToCallNil"
+                       "AttemptToCallNil",
+                       "Movses"
                ]
        },
        "apihelp-main-extended-description": "<div class=\"hlist plainlinks api-main-links\">\n* [[mw:Special:MyLanguage/API:Main_page|Документация]]\n* [[mw:Special:MyLanguage/API:FAQ|ЧаВО]]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api Почтовая рассылка]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce Новости API]\n* [https://phabricator.wikimedia.org/maniphest/query/GebfyV4uCaLd/#R Ошибки и запросы]\n</div>\n<strong>Статус:</strong> MediaWiki API — зрелый и стабильный интерфейс, активно поддерживаемый и улучшаемый. Мы стараемся избегать ломающих изменений, однако изредка они могут быть необходимы. Подпишитесь на [https://lists.wikimedia.org/pipermail/mediawiki-api-announce/ почтовую рассылку mediawiki-api-announce], чтобы быть в курсе обновлений.\n\n<strong>Ошибочные запросы:</strong> Если API получает запрос с ошибкой, вернётся заголовок HTTP с ключом «MediaWiki-API-Error», после чего значение заголовка и код ошибки будут отправлены обратно и установлены в то же значение. Более подробную информацию см. [[mw:Special:MyLanguage/API:Errors_and_warnings|API: Ошибки и предупреждения]].\n\n<p class=\"mw-apisandbox-link\"><strong>Тестирование:</strong> для удобства тестирования API-запросов, см. [[Special:ApiSandbox]].</p>",
        "apihelp-query+recentchanges-param-limit": "Сколько правок вернуть.",
        "apihelp-query+recentchanges-param-type": "Какие типы правок показать.",
        "apihelp-query+recentchanges-param-toponly": "Перечислять только последние правки страниц.",
+       "apihelp-query+recentchanges-param-title": "Вернуть записи, связанные со страницей.",
        "apihelp-query+recentchanges-param-generaterevisions": "При использовании в качестве генератора, генерировать идентификаторы версий вместо их названий. Записи последних изменений без привязанного идентификатора версии (например, большинство записей журналов) не сгенерируют ничего.",
        "apihelp-query+recentchanges-example-simple": "Список последних изменений.",
        "apihelp-query+recentchanges-example-generator": "Получить информацию о последних страницах с неотпатрулированными изменениями.",
index 2f9b693..30a685b 100644 (file)
        "api-format-title": "MediaWiki API 結果",
        "api-format-prettyprint-header": "這是$1格式的HTML呈現。HTML適合用於除錯,但不適合應用程式使用。\n\n指定<var>format</var>參數以更改輸出格式。要檢視$1格式的非HTML呈現,設定<kbd>format=$2</kbd>。\n\n參考 [[mw:Special:MyLanguage/API|完整說明文件]] 或 [[Special:ApiHelp/main|API說明]] 以取得更多資訊。",
        "api-format-prettyprint-header-only-html": "這是用來除錯的HTML呈現,不適合實際應用。\n\n參見[[mw:Special:MyLanguage/API|完整文件]]或[[Special:ApiHelp/main|API幫助]]以取得更多資訊。",
+       "api-format-prettyprint-header-hyperlinked": "這是$1格式的HTML實現。HTML對除錯很有用,但不適合應用程式使用。\n\n指定<var>format</var>參數以更改輸出格式。要查看$1格式的非HTML實現,設置[$3 <kbd>format=$2</kbd>]。\n\n參見[[mw:API|完整文件]],或[[Special:ApiHelp/main|API幫助]]以獲取更多信息。",
        "api-format-prettyprint-status": "此回應將會傳回HTTP狀態$1 $2。",
        "api-pageset-param-titles": "要使用的標題清單。",
        "api-pageset-param-pageids": "要使用的頁面 ID 清單。",
index 3125bd3..717b592 100644 (file)
@@ -138,7 +138,7 @@ class Throttler implements LoggerAwareInterface {
                                $this->logRejection( [
                                        'throttle' => $this->type,
                                        'index' => $index,
-                                       'ip' => $ipKey,
+                                       'ipKey' => $ipKey,
                                        'username' => $username,
                                        'count' => $count,
                                        'expiry' => $expiry,
@@ -193,7 +193,7 @@ class Throttler implements LoggerAwareInterface {
 
        protected function logRejection( array $context ) {
                $logMsg = 'Throttle {throttle} hit, throttled for {expiry} seconds due to {count} attempts '
-                       . 'from username {username} and IP {ip}';
+                       . 'from username {username} and IP {ipKey}';
 
                // If we are hitting a throttle for >= warningLimit attempts, it is much more likely to be
                // an attack than someone simply forgetting their password, so log it at a higher level.
index 9ac81ae..d6ab0ff 100644 (file)
@@ -333,7 +333,7 @@ class IcuCollation extends Collation {
                                static::class,
                                $this->locale,
                                $this->digitTransformLanguage->getCode(),
-                               self::getICUVersion(),
+                               INTL_ICU_VERSION,
                                self::FIRST_LETTER_VERSION
                        );
                        $this->firstLetterData = $cache->getWithSetCallback( $cacheKey, $cache::TTL_WEEK, function () {
@@ -528,18 +528,15 @@ class IcuCollation extends Collation {
         * can't be determined.
         *
         * The constant INTL_ICU_VERSION this function refers to isn't really
-        * documented. It is available since PHP 5.3.7 (see PHP 54561
-        * https://bugs.php.net/bug.php?id=54561). This function will return
-        * false on older PHPs.
-        *
-        * TODO: Remove the backwards-compatibility as MediaWiki now requires
-        * higher levels of PHP.
+        * documented, but see https://bugs.php.net/bug.php?id=54561.
         *
         * @since 1.21
-        * @return string|bool
+        * @deprecated since 1.32, use INTL_ICU_VERSION directly
+        * @return string
         */
        static function getICUVersion() {
-               return defined( 'INTL_ICU_VERSION' ) ? INTL_ICU_VERSION : false;
+               wfDeprecated( __METHOD__, '1.32' );
+               return INTL_ICU_VERSION;
        }
 
        /**
@@ -550,7 +547,7 @@ class IcuCollation extends Collation {
         * @return string|bool
         */
        static function getUnicodeVersionForICU() {
-               $icuVersion = self::getICUVersion();
+               $icuVersion = INTL_ICU_VERSION;
                if ( !$icuVersion ) {
                        return false;
                }
@@ -558,6 +555,8 @@ class IcuCollation extends Collation {
                $versionPrefix = substr( $icuVersion, 0, 3 );
                // Source: http://site.icu-project.org/download
                $map = [
+                       '61.' => '10.0',
+                       '60.' => '10.0',
                        '59.' => '9.0',
                        '58.' => '9.0',
                        '57.' => '8.0',
diff --git a/includes/compat/Timestamp.php b/includes/compat/Timestamp.php
deleted file mode 100644 (file)
index 63b87ae..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-<?php
-// This file is loaded by composer.json#autoload.files instead of autoload.php,
-// because PHP's class loader does not support autoloading an alias for a class that
-// isn't already loaded. See also AutoLoaderTest and ClassCollector.
-
-// By using an autoload file, this will trigger directly at runtime outside any class
-// loading context. This file will then register the alias and, as class_alias() does
-// by default, it will trigger a plain autoload for the destination class.
-
-// The below uses a namespaced class reference, to to avoid being seen by ClassCollector,
-// which would otherwise add it to autoload.php, after which AutoLoaderTest will
-// complain about class_alias() not being in the target class file.
-
-/**
- * @deprecated since 1.29
- * @since 1.20
- */
-class_alias( Wikimedia\Timestamp\TimestampException::class, 'TimestampException' );
index 308bef6..bce1ea6 100644 (file)
@@ -57,6 +57,7 @@ class UtfNormal {
         * @return string a clean, shiny, normalized UTF-8 string
         */
        static function cleanUp( $string ) {
+               wfDeprecated( __METHOD__, '1.25' );
                return Validator::cleanUp( $string );
        }
 
@@ -69,6 +70,7 @@ class UtfNormal {
         * @return string a UTF-8 string in normal form C
         */
        static function toNFC( $string ) {
+               wfDeprecated( __METHOD__, '1.25' );
                return Validator::toNFC( $string );
        }
 
@@ -80,6 +82,7 @@ class UtfNormal {
         * @return string a UTF-8 string in normal form D
         */
        static function toNFD( $string ) {
+               wfDeprecated( __METHOD__, '1.25' );
                return Validator::toNFD( $string );
        }
 
@@ -92,6 +95,7 @@ class UtfNormal {
         * @return string a UTF-8 string in normal form KC
         */
        static function toNFKC( $string ) {
+               wfDeprecated( __METHOD__, '1.25' );
                return Validator::toNFKC( $string );
        }
 
@@ -104,6 +108,7 @@ class UtfNormal {
         * @return string a UTF-8 string in normal form KD
         */
        static function toNFKD( $string ) {
+               wfDeprecated( __METHOD__, '1.25' );
                return Validator::toNFKD( $string );
        }
 
@@ -114,6 +119,7 @@ class UtfNormal {
         * @return bool
         */
        static function quickIsNFC( $string ) {
+               wfDeprecated( __METHOD__, '1.25' );
                return Validator::quickIsNFC( $string );
        }
 
@@ -124,6 +130,7 @@ class UtfNormal {
         * @return bool
         */
        static function quickIsNFCVerify( &$string ) {
+               wfDeprecated( __METHOD__, '1.25' );
                return Validator::quickIsNFCVerify( $string );
        }
 }
diff --git a/includes/compat/normal/UtfNormalDefines.php b/includes/compat/normal/UtfNormalDefines.php
deleted file mode 100644 (file)
index 38ce855..0000000
+++ /dev/null
@@ -1,186 +0,0 @@
-<?php
-/**
- * Backwards-compatability constants which are now provided by the
- * UtfNormal library. They are hardcoded here since they are needed
- * before the composer autoloader is initialized.
- *
- * 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 UtfNormal
- */
-
-/**
- * @deprecated since 1.25, use UtfNormal\Constants instead
- */
-define( 'UNICODE_HANGUL_FIRST', 0xac00 );
-/**
- * @deprecated since 1.25, use UtfNormal\Constants instead
- */
-define( 'UNICODE_HANGUL_LAST', 0xd7a3 );
-
-/**
- * @deprecated since 1.25, use UtfNormal\Constants instead
- */
-define( 'UNICODE_HANGUL_LBASE', 0x1100 );
-/**
- * @deprecated since 1.25, use UtfNormal\Constants instead
- */
-define( 'UNICODE_HANGUL_VBASE', 0x1161 );
-/**
- * @deprecated since 1.25, use UtfNormal\Constants instead
- */
-define( 'UNICODE_HANGUL_TBASE', 0x11a7 );
-
-/**
- * @deprecated since 1.25, use UtfNormal\Constants instead
- */
-define( 'UNICODE_HANGUL_LCOUNT', 19 );
-/**
- * @deprecated since 1.25, use UtfNormal\Constants instead
- */
-define( 'UNICODE_HANGUL_VCOUNT', 21 );
-/**
- * @deprecated since 1.25, use UtfNormal\Constants instead
- */
-define( 'UNICODE_HANGUL_TCOUNT', 28 );
-/**
- * @deprecated since 1.25, use UtfNormal\Constants instead
- */
-define( 'UNICODE_HANGUL_NCOUNT', UNICODE_HANGUL_VCOUNT * UNICODE_HANGUL_TCOUNT );
-
-/**
- * @deprecated since 1.25, use UtfNormal\Constants instead
- */
-define( 'UNICODE_HANGUL_LEND', UNICODE_HANGUL_LBASE + UNICODE_HANGUL_LCOUNT - 1 );
-/**
- * @deprecated since 1.25, use UtfNormal\Constants instead
- */
-define( 'UNICODE_HANGUL_VEND', UNICODE_HANGUL_VBASE + UNICODE_HANGUL_VCOUNT - 1 );
-/**
- * @deprecated since 1.25, use UtfNormal\Constants instead
- */
-define( 'UNICODE_HANGUL_TEND', UNICODE_HANGUL_TBASE + UNICODE_HANGUL_TCOUNT - 1 );
-
-/**
- * @deprecated since 1.25, use UtfNormal\Constants instead
- */
-define( 'UNICODE_SURROGATE_FIRST', 0xd800 );
-/**
- * @deprecated since 1.25, use UtfNormal\Constants instead
- */
-define( 'UNICODE_SURROGATE_LAST', 0xdfff );
-/**
- * @deprecated since 1.25, use UtfNormal\Constants instead
- */
-define( 'UNICODE_MAX', 0x10ffff );
-/**
- * @deprecated since 1.25, use UtfNormal\Constants instead
- */
-define( 'UNICODE_REPLACEMENT', 0xfffd );
-
-/**
- * @deprecated since 1.25, use UtfNormal\Constants instead
- */
-define( 'UTF8_HANGUL_FIRST', "\xea\xb0\x80" /*codepointToUtf8( UNICODE_HANGUL_FIRST )*/ );
-/**
- * @deprecated since 1.25, use UtfNormal\Constants instead
- */
-define( 'UTF8_HANGUL_LAST', "\xed\x9e\xa3" /*codepointToUtf8( UNICODE_HANGUL_LAST )*/ );
-
-/**
- * @deprecated since 1.25, use UtfNormal\Constants instead
- */
-define( 'UTF8_HANGUL_LBASE', "\xe1\x84\x80" /*codepointToUtf8( UNICODE_HANGUL_LBASE )*/ );
-/**
- * @deprecated since 1.25, use UtfNormal\Constants instead
- */
-define( 'UTF8_HANGUL_VBASE', "\xe1\x85\xa1" /*codepointToUtf8( UNICODE_HANGUL_VBASE )*/ );
-/**
- * @deprecated since 1.25, use UtfNormal\Constants instead
- */
-define( 'UTF8_HANGUL_TBASE', "\xe1\x86\xa7" /*codepointToUtf8( UNICODE_HANGUL_TBASE )*/ );
-
-/**
- * @deprecated since 1.25, use UtfNormal\Constants instead
- */
-define( 'UTF8_HANGUL_LEND', "\xe1\x84\x92" /*codepointToUtf8( UNICODE_HANGUL_LEND )*/ );
-/**
- * @deprecated since 1.25, use UtfNormal\Constants instead
- */
-define( 'UTF8_HANGUL_VEND', "\xe1\x85\xb5" /*codepointToUtf8( UNICODE_HANGUL_VEND )*/ );
-/**
- * @deprecated since 1.25, use UtfNormal\Constants instead
- */
-define( 'UTF8_HANGUL_TEND', "\xe1\x87\x82" /*codepointToUtf8( UNICODE_HANGUL_TEND )*/ );
-
-/**
- * @deprecated since 1.25, use UtfNormal\Constants instead
- */
-define( 'UTF8_SURROGATE_FIRST', "\xed\xa0\x80" /*codepointToUtf8( UNICODE_SURROGATE_FIRST )*/ );
-/**
- * @deprecated since 1.25, use UtfNormal\Constants instead
- */
-define( 'UTF8_SURROGATE_LAST', "\xed\xbf\xbf" /*codepointToUtf8( UNICODE_SURROGATE_LAST )*/ );
-/**
- * @deprecated since 1.25, use UtfNormal\Constants instead
- */
-define( 'UTF8_MAX', "\xf4\x8f\xbf\xbf" /*codepointToUtf8( UNICODE_MAX )*/ );
-/**
- * @deprecated since 1.25, use UtfNormal\Constants instead
- */
-define( 'UTF8_REPLACEMENT', "\xef\xbf\xbd" /*codepointToUtf8( UNICODE_REPLACEMENT )*/ );
-# define( 'UTF8_REPLACEMENT', '!' );
-
-/**
- * @deprecated since 1.25, use UtfNormal\Constants instead
- */
-define( 'UTF8_OVERLONG_A', "\xc1\xbf" );
-/**
- * @deprecated since 1.25, use UtfNormal\Constants instead
- */
-define( 'UTF8_OVERLONG_B', "\xe0\x9f\xbf" );
-/**
- * @deprecated since 1.25, use UtfNormal\Constants instead
- */
-define( 'UTF8_OVERLONG_C', "\xf0\x8f\xbf\xbf" );
-
-# These two ranges are illegal
-/**
- * @deprecated since 1.25, use UtfNormal\Constants instead
- */
-define( 'UTF8_FDD0', "\xef\xb7\x90" /*codepointToUtf8( 0xfdd0 )*/ );
-/**
- * @deprecated since 1.25, use UtfNormal\Constants instead
- */
-define( 'UTF8_FDEF', "\xef\xb7\xaf" /*codepointToUtf8( 0xfdef )*/ );
-/**
- * @deprecated since 1.25, use UtfNormal\Constants instead
- */
-define( 'UTF8_FFFE', "\xef\xbf\xbe" /*codepointToUtf8( 0xfffe )*/ );
-/**
- * @deprecated since 1.25, use UtfNormal\Constants instead
- */
-define( 'UTF8_FFFF', "\xef\xbf\xbf" /*codepointToUtf8( 0xffff )*/ );
-
-/**
- * @deprecated since 1.25, use UtfNormal\Constants instead
- */
-define( 'UTF8_HEAD', false );
-/**
- * @deprecated since 1.25, use UtfNormal\Constants instead
- */
-define( 'UTF8_TAIL', true );
diff --git a/includes/compat/normal/UtfNormalUtil.php b/includes/compat/normal/UtfNormalUtil.php
deleted file mode 100644 (file)
index 0e29dd0..0000000
+++ /dev/null
@@ -1,104 +0,0 @@
-<?php
-/**
- * Some of these functions are adapted from places in MediaWiki.
- * Should probably merge them for consistency.
- *
- * Copyright © 2004 Brion Vibber <brion@pobox.com>
- * https://www.mediawiki.org/
- *
- * 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 UtfNormal
- */
-
-use UtfNormal\Utils;
-
-/**
- * Return UTF-8 sequence for a given Unicode code point.
- *
- * @param int $codepoint
- * @return string
- * @throws InvalidArgumentException if fed out of range data.
- * @public
- * @deprecated since 1.25, use UtfNormal\Utils directly
- */
-function codepointToUtf8( $codepoint ) {
-       wfDeprecated( __FUNCTION__, '1.25' );
-       return Utils::codepointToUtf8( $codepoint );
-}
-
-/**
- * Take a series of space-separated hexadecimal numbers representing
- * Unicode code points and return a UTF-8 string composed of those
- * characters. Used by UTF-8 data generation and testing routines.
- *
- * @param string $sequence
- * @return string
- * @throws InvalidArgumentException if fed out of range data.
- * @private
- * @deprecated since 1.25, use UtfNormal\Utils directly
- */
-function hexSequenceToUtf8( $sequence ) {
-       wfDeprecated( __FUNCTION__, '1.25' );
-       return Utils::hexSequenceToUtf8( $sequence );
-}
-
-/**
- * Take a UTF-8 string and return a space-separated series of hex
- * numbers representing Unicode code points. For debugging.
- *
- * @fixme this is private but extensions + maint scripts are using it
- * @param string $str UTF-8 string.
- * @return string
- * @private
- */
-function utf8ToHexSequence( $str ) {
-       wfDeprecated( __FUNCTION__, '1.25' );
-       $buf = '';
-       foreach ( preg_split( '//u', $str, -1, PREG_SPLIT_NO_EMPTY ) as $cp ) {
-               $buf .= sprintf( '%04x ', UtfNormal\Utils::utf8ToCodepoint( $cp ) );
-       }
-
-       return rtrim( $buf );
-}
-
-/**
- * Determine the Unicode codepoint of a single-character UTF-8 sequence.
- * Does not check for invalid input data.
- *
- * @param string $char
- * @return int
- * @public
- * @deprecated since 1.25, use UtfNormal\Utils directly
- */
-function utf8ToCodepoint( $char ) {
-       wfDeprecated( __FUNCTION__, '1.25' );
-       return Utils::utf8ToCodepoint( $char );
-}
-
-/**
- * Escape a string for inclusion in a PHP single-quoted string literal.
- *
- * @param string $string string to be escaped.
- * @return string escaped string.
- * @public
- * @deprecated since 1.25, use UtfNormal\Utils directly
- */
-function escapeSingleString( $string ) {
-       wfDeprecated( __FUNCTION__, '1.25' );
-       return Utils::escapeSingleString( $string );
-}
index dfac82e..b8a2f8f 100644 (file)
        "config-env-php": "بي إتش بي $1 مثبت.",
        "config-env-hhvm": "نصبت HHVM $1.",
        "config-unicode-using-intl": "باستخدام [https://pecl.php.net/intl امتداد intl PECL] لتسوية يونيكود.",
+       "config-unicode-pure-php-warning": "<strong>تحذير:</strong> لا يتوفر [https://pecl.php.net/intl امتداد intl PECL] للتعامل مع تطبيع يونيكود; حيث يتراجع لإبطاء تنفيذ Pure-Pure;\nإذا كنت تدير موقعا عالي الزيارات، فتجب عليك القراءة قليلا في [https://www.mediawiki.org/wiki/Special:MyLanguage/Unicode_normalization_considerations تطبيع يونيكود].",
+       "config-unicode-update-warning": "<strong>تحذير:</strong> يستخدم الإصدار المثبت من برنامج تطبيع نظام يونيكود إصدارًا قديما من مكتبة [http://site.icu-project.org/ مشروع ICU];\nتجب عليك [https://www.mediawiki.org/wiki/Special:MyLanguage/Unicode_normalization_considerations الترقية] إذا كنت مهتما باستخدام يونيكود.",
+       "config-no-db": "لا يمكن العثور على مشغل قاعدة بيانات مناسب! تحتاج إلى تثبيت مشغل قاعدة بيانات PHP، \n{{PLURAL:$2|نوع قاعدة البيانات التالي مدعوم|أنواع قاعدة البيانات التالية مدعومة}} البيانات التالية مدعومة: $1.\n\nإذا قمت بتجميع PHP بنفسك، فقم بتكوينها مع تمكين عميل قاعدة البيانات، على سبيل المثال، باستخدام <code>./configure --with-mysqli</code>.\nإذا قمت بتثبيت PHP من حزمة Debian أو Ubuntu، فستحتاج أيضا إلى تثبيت، على سبيل المثال، حزمة <code>php5-mysql</code>.",
        "config-outdated-sqlite": "<strong>تحذير:</strong> لديك SQLite $1, which وهو أقل من الحد الأدنى المطلوب للنسخة $2. SQLite سوف يكون غير متوفر.",
+       "config-no-fts3": "<strong>تحذير:</strong> يتم تجميع SQLite بدون [//sqlite.org/fts3.html FTS3 module]; ستكون ميزات البحث غير متوفرة في هذه الواجهة الخلفية.",
+       "config-pcre-old": "<strong>فادح:</strong> مطلوب PCRE $1 أو أحدث،\nترتبط ثنائية PHP الخاصة بك بـPCRE $2.\n[https://www.mediawiki.org/wiki/Manual:Errors_and_symptoms/PCRE مزيد من المعلومات].",
+       "config-pcre-no-utf8": "<strong>فادح:</strong> يبدو أن وحدة PCRE في PHP يتم تجميعها بدون دعم PCRE_UTF8، \nيتطلب ميدياويكي دعم UTF-8 ليعمل بشكل صحيح.",
+       "config-memory-raised": "<code>memory_limit</code> في PHP $1 ومرتفعة إلى $2.",
+       "config-memory-bad": "<strong>تحذير:</strong> في PHP <code>memory_limit</code> $1،\nهذا على الارجح منخفض جدا;\nقد يفشل التثبيت!",
        "config-apc": "تثبيت [https://secure.php.net/apc APC]",
-       "config-apcu": "تثبيت [https://secure.php.net/apcu APCu]",
+       "config-apcu": "[https://secure.php.net/apcu APCu] مثبت",
        "config-wincache": "تثبيت [https://www.iis.net/downloads/microsoft/wincache-extension WinCache]",
+       "config-no-cache-apcu": "<strong>تحذير:</strong> تعذر العثور على [https://secure.php.net/apcu APCu] أو [https://www.iis.net/downloads/microsoft/wincache-extension WinCache];\nكائن التخزين المؤقت غير ممكّّن.",
+       "config-mod-security": "<strong>تحذير:</strong> تم تمكين خادم الويب الخاص بك [https://modsecurity.org/ mod_security]/mod_security2، العديد من التكوينات الشائعة له سوف تتسبب في مشاكل لميدياويكي والبرامج الأخرى التي تسمح للمستخدمين بنشر محتوى عشوائي; \nإذا كان ذلك ممكنا، يجب تعطيل هذا، أو يمكنك الرجوع إلى [https://modsecurity.org/documentation/ توثيق mod_security] أو الاتصال بدعم مضيفك إذا واجهتك أخطاء عشوائية.",
        "config-diff3-bad": "جنو diff3 غير موجود.",
        "config-git": "العثور على برنامج التحكم في إصدار جت <code>$1</code>.",
        "config-git-bad": "برنامج التحكم في إصدار جت غير موجود.",
        "config-no-cli-uri": "<strong>تحذير:</strong> لم يتم تحديد <code>--scriptpath</code>، باستخدام الافتراضي: <code>$1</code>.",
        "config-using-server": "باستخدام اسم الخادم \"<nowiki>$1</nowiki\".",
        "config-using-uri": "باستخدام URL الخادم \"<nowiki>$1$2</nowiki>\".",
+       "config-uploads-not-safe": "<strong>تحذير:</strong>  الدليل الافتراضي للمرفوعات <code>$1</code> عرضة لتنفيذ سكريبتات عشوائية،\nعلى الرغم من أن ميدياويكي يتحقق من كل الملفات المرفوعة للتهديدات الأمنية، فمن المستحسن بشدة [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Security#Upload_security إغلاق هذه الثغرة الأمنية] قبل تمكين المرفوعات.",
+       "config-no-cli-uploads-check": "<strong>تحذير:</strong> لم يتم تحديد الدليل الافتراضي للمرفوعات (<code>$1</code>) للقابلية للتأثر\nلتنفيذ برنامج تعسفي أثناء تثبيت CLI.",
+       "config-brokenlibxml": "يحتوي نظامك على مجموعة من إصدارات PHP وlibxml2 ويمكن أن تسبب فسادا للبيانات في ميدياويكي وتطبيقات الويب الأخرى;\nقم بالترقية إلى libxml2 2.7.3 أو أحدث ([https://bugs.php.net/bug.php؟id=45996 تم تدقيم العلة مع PHP]); \nتم إحباط التثبيت.",
+       "config-suhosin-max-value-length": "تم تثبيت Suhosin وتقييد وسيط GET <code>length</code> إلى $1 بايت،\nسيعمل مكون ResourceLoader في ميدياويكي حول هذا الحد، لكن ذلك سيؤدي إلى انخفاض مستوى الأداء، \nإذا كان ذلك ممكنا، فيجب تعيين <code>suhosin.get.max_value_length</code> على 1024 أو أعلى في <code>php.ini</code>، وتعيين <code>$wgResourceLoaderMaxQueryLength</code> لنفس القيمة في <code>LocalSettings.php</code>.",
        "config-using-32bit": "<strong>تحذير:</strong> يبدو أن نظامك يعمل مع الأعداد الصحيحة 32 بت، هذا [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:32-bit لا يُنصَح به].",
        "config-db-type": "نوع قاعدة البيانات:",
        "config-db-host": "مضيف قاعدة البيانات:",
+       "config-db-host-help": "إذا كان خادم قاعدة البيانات موجودا في خادم مختلف، فأدخل اسم المضيف أو عنوان الآيبي هنا. \n\nإذا كنت تستخدم استضافة ويب مشتركة، فيجب أن يمنحك موفر الاستضافة اسم المضيف الصحيح في وثائقه. \n\nإذا كنت تقوم بالتثبيت على خادم ويندوز واستخدام MySQL، فإن استخدام \"localhost\" قد لا يعمل لاسم الخادم، إذا لم يتم ذلك، فجرب \"127.0.0.1\" لعنوان الآيبي المحلي. \n\nإذا كنت تستخدم PostgreSQL، فاترك هذا الحقل فارغا للاتصال عبر مقبس Unix.",
        "config-db-host-oracle": "قاعدة بيانات TNS:",
+       "config-db-host-oracle-help": "أدخل [http://download.oracle.com/docs/cd/B28359_01/network.111/b28317/tnsnames.htm اسم اتصال محلي] صالحا، يجب أن يكون ملف tnsnames.ora مرئيا لهذا التثبيت.<br />إذا كنت تستخدم مكتبات العملاء 10g أو أحدث، فيمكنك أيضا استخدام طريقة التسمية [http://download.oracle.com/docs/cd/E11882_01/network.112/e10836/naming.اتصال htm السهل].",
        "config-db-wiki-settings": "حدِّد هذا الويكي",
        "config-db-name": "اسم قاعدة البيانات",
        "config-db-name-help": "اختر الاسم الذي يعرف الويكي الخاص بك. لا يجب أن يحتوي على مسافات. إذا كنت تستخدم استضافة المواقع المشتركة، مزود الاستضافة إما سيعطيك اسم قاعدة بيانات محددة لاستخدامها أو سيتيح لك إنشاء قواعد بيانات عن طريق لوحة التحكم.",
        "config-db-name-oracle": "سكيما قاعدة البيانات:",
+       "config-db-account-oracle-warn": "هناك ثلاثة سيناريوهات مدعومة لتثبيت Oracle كقاعدة بيانات خلفية: \n\nإذا كنت ترغب في إنشاء حساب قاعدة بيانات كجزء من عملية التثبيت، فيُرجَى تقديم حساب بدور SYSDBA كحساب قاعدة بيانات للتثبيت وتحديد بيانات الاعتماد المطلوبة لحساب الوصول إلى الإنترنت، وإلا يمكنك إما إنشاء حساب الوصول إلى الويب يدويا وتزويد الحساب فقط (إذا كان يتطلب صلاحيات لإنشاء كائنات المخطط) أو توفير حسابين مختلفين، أحدهما له امتيازات إنشاء وامتياز مقيد للدخول إلى الويب. \n\nيمكن العثور على البرنامج النصي لإنشاء حساب له امتيازات مطلوبة في دليل \"maintenance/oracle/\" لهذا التثبيت، ضع في اعتبارك أن استخدام حساب مقيد سيؤدي إلى تعطيل جميع إمكانات الصيانة باستخدام الحساب الافتراضي.",
        "config-db-install-account": "حساب المستخدم للتنصيب",
        "config-db-username": "اسم مستخدم قاعدة البيانات:",
        "config-db-password": "كلمة سر قاعدة البيانات:",
        "config-db-schema-help": "هذا المخطط عادة يكون على ما يرام. غيره إذا كنت تعرف أنك في حاجة إلى هذا فقط.",
        "config-pg-test-error": "لا يمكن الاتصال بقاعدة البيانات <strong>$1</strong>: $2",
        "config-sqlite-dir": "دليل بيانات SQLite:",
+       "config-sqlite-dir-help": "يخزن SQLite جميع البيانات في ملف واحد. \n\nيجب أن يكون الدليل الذي توفره قابلا للكتابة بواسطة خادم الويب أثناء التثبيت. \n\nيجب أن يكون <strong>غير</strong> متاحا عبر الويب؛ هذا هو سبب عدم وضعه في مكان ملفات PHP الخاصة بك. \n\nسيقوم المثبت بكتابة ملف <code>.htaccess</code> معه، ولكن إذا فشل ذلك، يمكن لشخص ما الوصول إلى قاعدة بياناتك الأولية، \nيتضمن ذلك بيانات المستخدم الأولية (عناوين البريد الإلكتروني وكلمات المرور المجزأة) بالإضافة إلى المراجعات المحذوفة والبيانات المحظورة الأخرى على الويكي. \n\nفكر في وضع قاعدة البيانات في مكان آخر تماما، على سبيل المثال في <code>/var/lib/mediawiki/yourwiki</code.",
        "config-oracle-def-ts": "جدولية افتراضية:",
        "config-oracle-temp-ts": "جدولية مؤقتة:",
        "config-type-mysql": "MySQL (أو متوافق)",
        "config-type-oracle": "أوراكل",
        "config-type-mssql": "خادم SQL لميكروسوفت",
        "config-support-info": "ميدياويكي يدعم نظم قواعد البيانات التالية: $1 إذا كنت لا ترى نظام قاعدة البيانات الذي تحاول استخدامه مدرجًا أدناه، اتبع الإرشادات المرتبطة فوق لتمكين الدعم.",
+       "config-dbsupport-mysql": "* [{{int:version-db-mysql-url}} MySQL] هو الهدف الأساسي لميدياويكي وأفضل دعم له، يعمل ميدياويكي أيضا مع [{{int:version-db-mariadb-url}} MariaDB] و[{{int:version-db-percona-url}} Percona Server]، وهما متوافقان مع MySQL، ([https://secure.php.net/manual/en/mysqli.installation.php كيفية تجميع PHP مع دعم MySQL])",
+       "config-dbsupport-postgres": "* [{{int:version-db-postgres-url}} PostgreSQL] هو نظام قاعدة بيانات مفتوح المصدر مشهور كبديل لـMySQL ([https://secure.php.net/manual/en/pgsql.installation.php كيفية تجميع PHP مع دعم PostgreSQL])",
+       "config-dbsupport-sqlite": "* [{{int:version-db-sqlite-url}} SQLite] هو نظام قاعدة بيانات خفيف مدعوم بشكل جيد. ([https://secure.php.net/manual/en/pdo.installation.php كيفية ترجمة PHP باستخدام دعم SQLite]، يستخدم PDO)",
+       "config-dbsupport-oracle": "* [{{int:version-db-oracle-url}} Oracle] هي قاعدة بيانات مؤسسة تجارية. ([https://secure.php.net/manual/en/oci8.installation.php كيفية تجميع PHP مع دعم OCI8])",
+       "config-dbsupport-mssql": "* [{{int:version-db-mssql-url}} Microsoft SQL Server] هي قاعدة بيانات مؤسسة تجارية لويندوز. ([https://secure.php.net/manual/en/sqlsrv.installation.php كيفية تجميع PHP مع دعم SQLSRV])",
        "config-header-mysql": "إعدادات MySQL",
        "config-header-postgres": "إعدادات PostgreSQL",
        "config-header-sqlite": "إعدادات SQLite",
        "config-missing-db-name": "يجب عليك إدخال قيمة ل\"{{int:config-db-name}}\".",
        "config-missing-db-host": "يجب إدخال قيمة لـ\"{{int:config-db-host}}\".",
        "config-missing-db-server-oracle": "يجب عليك إدخال قيمة ل\"{{int:config-db-host-oracle}}\".",
+       "config-invalid-db-server-oracle": "TNS قاعدة بيانات غير صالحة \"$1\";\nاستخدم إما \"اسم TNS\" أو سلسلة \"الاتصال السهل\" \"Easy Connect\" ([http://docs.oracle.com/cd/E11882_01/network.112/e10836/naming.htm طرقلتسمية في أوراكل]).",
+       "config-invalid-db-name": "اسم قاعدة بيانات غير صالح \"$1\". \nاستخدم فقط أحرف أسكي (az، AZ) وأرقاما (0-9) وشرطات سفلية (_).",
+       "config-invalid-db-prefix": "بادئة قاعدة بيانات غير صالحة \"$1\". \nاستخدم فقط أحرف أسكي (az، AZ) وأرقاما (0-9) وشرطات سفلية (_).",
        "config-connection-error": "$1.\nتحقق من المضيف، واسم المستخدم وكلمة المرور وحاول مرة أخرى.",
+       "config-invalid-schema": "مخطط غير صالح لميدياويكي \"$1\". \nاستخدم فقط أحرف أسكي (az، AZ) وأرقاما (0-9) وشرطات سفلية (_).",
        "config-db-sys-create-oracle": "المثبت يعتمد باستخدام حساب SYSDBA فقط لإنشاء حساب جديد.",
        "config-db-sys-user-exists-oracle": "حساب المستخدم \"$1\" موجود بالفعل; يمكن استخدام SYSDBA لإنشاء حساب جديد فقط!",
        "config-postgres-old": "PostgreSQL $1 أو لاحق مطلوب. لديك $2.",
        "config-mssql-old": "خادم Microsoft SQL $1 أو لاحق مطلوب. لديك $2.",
+       "config-sqlite-name-help": "اختر اسمًا يعرف الويكي الخاص بك، \nلا تستخدم مسافات أو شرطات، \nسيتم استخدام هذا لاسم ملف البيانات SQLite.",
+       "config-sqlite-parent-unwritable-group": "لا يمكن إنشاء دليل البيانات <code><nowiki>$1</nowiki></code>; لأن الدليل الأصلي <code><nowiki>$2</nowiki></code> غير قابل للكتابة بواسطة خادم الويب، \nحدد المثبت المستخدم الذي يعمل عليه خادم الويب الخاص بك،\nاجعل الدليل <code><nowiki>$3</nowiki></code> قابلا للكتابة بواسطته للمتابعة، \nفي نظام يونكس/لينوكس قم بـ: \n<pre>cd $2\nmkdir $3\nchgrp $4 $3\nchmod g+w $3</pre>",
+       "config-sqlite-parent-unwritable-nogroup": "لا يمكن إنشاء دليل البيانات <code><nowiki>$1</nowiki></code>; لأن الدليل الأصلي <code><nowiki>$2</nowiki></code> غير قابل للكتابة بواسطة خادم الويب، \nتعذر على المثبت تحديد المستخدم الذي يعمل عليه خادم الويب الخاص بك،\nاجعل الدليل <code><nowiki>$3</nowiki></code> قابلا للكتابة بواسطته للمتابعة، \nفي نظام يونكس/لينوكس قم بـ: \n\n<pre>cd $2\nmkdir $3\nchmod a+w $3</pre>",
        "config-sqlite-mkdir-error": "خطأ في إنشاء دليل البيانات \"$1\". تحقق من الموقع وحاول مرة أخرى.",
        "config-sqlite-dir-unwritable": "غير قادر على الكتابة إلى الدليل \"$1\";\nغيِّر أذوناته حتى يتمكن خادم الويب من الكتابة إليه، وحاول مرة أخرى.",
        "config-sqlite-connection-error": "$1.\nتحقق من اسم دليل البيانات وقواعد البيانات أدناه وحاول مرة أخرى.",
        "config-sqlite-cant-create-db": "لا يمكن إنشاء ملف قاعدة البيانات <code>$1</code>.",
        "config-sqlite-fts3-downgrade": "PHP يفتقد دعم FTS3، تخفيض الجداول.",
        "config-can-upgrade": "هناك جداول ميدياويكي في قاعدة البيانات هذه. للارتقاء بها إلى ميدياويكي $1; انقر على <strong>متابعة</strong>.",
+       "config-upgrade-done": "اكتملت الترقية; \n\nيمكنك الآن [$1 بدء استخدام الويكي الخاص بك]. \n\nإذا كنت ترغب في إعادة إنشاء ملف <code>LocalSettings.php</code>، فانقر فوق الزر أدناه،\n<strong>غير مستحسن</strong> في ما لم تكن تواجه مشاكل مع الويكي الخاص بك.",
        "config-upgrade-done-no-regenerate": "اكتملت الترقية;\n\nيمكنك الآن [$1 بدء استخدام الويكي الخاص بك].",
        "config-regenerate": "إعادة تكوين LocalSettings.php ←",
        "config-show-table-status": "<code> إظهار جدول الحالة </code> فشل الاستعلام!",
        "config-mysql-engine": "محرك التخزين",
        "config-mysql-innodb": "إنو دي بي",
        "config-mysql-myisam": "ماي إسام",
+       "config-mysql-myisam-dep": "<strong>تحذير:</strong> لقد اخترت MyISAM كمحرك تخزين لـMySQL، والذي لا يُنصَح باستخدامه مع ميدياويكي; لأنه:\n* بالكاد يدعم التزامن بسبب قفل الجدول \n* أكثر عرضة للفساد من المحركات الأخرى\n* لا يقوم الكود الأساسي لميدياويكي بمعالجة MyISAM دائما كما يجب\n\nإذا كان تثبيت MySQL يدعم InnoDB، فمن المستحسن جدا أن تختاره بدلا منه، \nإذا كان تثبيت MySQL لا يدعم InnoDB، فربما حان الوقت للترقية.",
+       "config-mysql-only-myisam-dep": "<strong>تحذير:</strong> MyISAMهو محرك التخزين الوحيد المتاح لـMySQL على هذا الجهاز، ولا يُنصَح باستخدامه مع ميدياويكي; لأنه:\n* بالكاد يدعم التزامن بسبب قفل الجدول \n* أكثر عرضة للفساد من المحركات الأخرى\n* لا يقوم الكود الأساسي لميدياويكي بمعالجة MyISAM دائما كما يجب\n\nتثبيت MySQL لا يدعم InnoDB; ربما حان الوقت للترقية.",
+       "config-mysql-engine-help": "<strong>InnoDB</strong> هو دائما الخيار الأفضل; لأنه يحتوي على دعم تزامن جيد.\n\nقد يكون <strong>MyISAM</strong> أسرع في تثبيت المستخدم الفردي أو للقراءة فقط،\nتميل قواعد بيانات MyISAM للتلف أكثر من قواعد بيانات InnoDB.",
        "config-mysql-charset": "مجموعة محارف قاعدة البيانات",
        "config-mysql-binary": "ثنائي",
        "config-mysql-utf8": "يو تي إف-8",
+       "config-mysql-charset-help": "في <strong>الوضع الثنائي</strong>، يقوم ميدياويكي بتخزين نص UTF-8 في قاعدة البيانات في الحقول الثنائية، \nهذا أكثر كفاءة من وضع UTF-8 الخاص بـMySQL، ويسمح لك باستخدام النطاق الكامل لأحرف يونيكود. \n\nفي <strong>وضع UTF-8</strong>، ستعرف MySQL ما هي مجموعة البيانات التي تقوم بها، ويمكنها تقديمها وتحويلها بشكل مناسب، ولكنها لن تسمح لك بتخزين الحروف فوق [https://en.wikipedia.org/wiki/Mapping_of_Unicode_character_planes Basic Multilingual Plane].",
        "config-mssql-auth": "نوع الاستيثاق:",
+       "config-mssql-install-auth": "حدد نوع المصادقة الذي سيتم استخدامه للاتصال بقاعدة البيانات أثناء عملية التثبيت. \nإذا حددت \"{{int:config-mssql-windowsauth}}\"، فسيتم استخدام بيانات اعتماد أي مستخدم يعمل عليه خادم الويب.",
+       "config-mssql-web-auth": "حدد نوع المصادقة الذي سيستخدمه خادم الويب للاتصال بخادم قاعدة البيانات، أثناء التشغيل العادي للويكي. \nإذا حددت \"{{int:config-mssql-windowsauth}}\"، فسيتم استخدام بيانات اعتماد أي مستخدم يعمل عليه خادم الويب.",
        "config-mssql-sqlauth": "مصادقة خادم SQL",
        "config-mssql-windowsauth": "مصادقة ويندوز",
        "config-site-name": "اسم الويكي:",
        "config-ns-site-name": "مثل اسم الويكي: $1",
        "config-ns-other": "أخرى (حدد)",
        "config-ns-other-default": "ماي ويكي",
+       "config-project-namespace-help": "مثال ويكيبيديا التالي، يبقي العديد من الويكيات صفحات سياساتها منفصلة عن صفحات محتواها، في '''نطاق المشروع'''، \nتبدأ جميع عناوين الصفحات في هذا النطاق ببادئة معينة، والتي يمكنك تحديدها هنا، \nعادة، يتم اشتقاق هذه البادئة من اسم الويكي، ولكنها لا يمكن أن تحتوي على أحرف ترقيم مثل \"#\" أو \":\".",
        "config-ns-invalid": "النطاق المحدد \"<nowiki>$1</nowiki>\" غير صالح.\nحدد نطاق مشروع مختلف.",
        "config-ns-conflict": "النطاق المحدد \"<nowiki>$1</ nowiki>\" يتعارض مع نطاق ميدياويكي الافتراضي. حدد نطاق مشروع مختلف.",
        "config-admin-box": "حساب إداري",
        "config-admin-error-password": "خطأ داخلي عند عند وضع كلمة مرور للإداري \"<nowiki>$1</nowiki>\": <pre>$2</pre>.",
        "config-admin-error-bademail": "لقد قمت بإدخال عنوان البريد الإلكتروني غير صالح.",
        "config-subscribe": "اشترك في [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce نشر إعلانات القائمة البريدية].",
+       "config-subscribe-help": "هذه قائمة بريدية ذات حجم منخفض تُستخدَم لإعلانات الإصدار، بما في ذلك إعلانات الأمان المهمة، \nيجب عليك الاشتراك فيها وتحديث تثبيت ميدياويكي الخاص بك عندما تظهر إصدارات جديدة.",
        "config-subscribe-noemail": "حاولت الاشتراك في القائمة البريدية الخاصة بإصدار إعلانات دون تقديم عنوان بريد إلكتروني. يُرجَى إدخال عنوان بريد إلكتروني إذا كنت ترغب في الاشتراك في القائمة البريدية.",
        "config-pingback": "تبادل البيانات حول هذا التثبيت مع مطوري ميدياويكي.",
+       "config-pingback-help": "إذا قمت بتحديد هذا الخيار، سيقوم ميدياويكي بشكل دوري باختبار https://www.mediawiki.org مع بيانات أساسية حول نسخة ميدياويكي، تتضمن هذه البيانات، على سبيل المثال، نوع النظام وإصدار PHP والواجهة الخلفية لقاعدة البيانات، تشارك مؤسسة ويكيميديا ​​هذه البيانات مع مطوري ميدياويكي للمساعدة في توجيه جهود التطوير المستقبلية، سيتم إرسال البيانات التالية لنظامك:\n<pre>$1</pre>",
        "config-almost-done": "لقد شارفت على الانتهاء! يمكنك الآن تخطي التكوين المتبقي وتثبيت الويكي الآن.",
        "config-optional-continue": "اسألني المزيد من الأسئلة",
        "config-optional-skip": "إنني أشعر بالملل بالفعل، فقط قم بتثبيت الويكي",
        "config-profile-no-anon": "إنشاء الحساب مطلوب",
        "config-profile-fishbowl": "المحررون المخولون فقط",
        "config-profile-private": "ويكي خاص",
+       "config-profile-help": "تعمل الويكيات بشكل أفضل عندما تسمح لأكبر عدد ممكن من الأشخاص بتحريرها قدر الإمكان، \nفي ميدياويكي، من السهل مراجعة التغييرات الأخيرة، وإعادة أي ضرر يحدث من قبل مستخدمين سذج أو ضارين، \n\nومع ذلك، وجد الكثيرون أن ميدياويكي مفيد في مجموعة متنوعة من الأدوار، وفي بعض الأحيان ليس من السهل إقناع الجميع بمزايا طريقة الويكي; \nلذلك لديك الخيار. \n\nيسمح النموذج <strong>{{int:config-profile-wiki}}</strong> لأي شخص بالتحرير، دون تسجيل الدخول. \nويكي بـ<strong>{{int:config-profile-no-anon}}</strong> يوفر مساءلة إضافية، ولكنه قد يمنع المساهمين العاديين. \n\nيسمح السيناريو <strong>{{int:config-profile-fishbowl}}</strong> للمستخدمين المعتمدين بالتحرير، ولكن يمكن للجمهور عرض الصفحات، بما في ذلك التاريخ.\nيتيح <strong>{{int:config-profile-private}}</strong> للمستخدمين المعتمدين فقط عرض الصفحات، مع السماح لنفس المجموعة بالتعديل. \n\nتتوفر تكوينات صلاحيات مستخدم أكثر تعقيدًا بعد التثبيت، راجع [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:User_rights إدخال الدليل ذي الصلة].",
        "config-license": "حقوق النسخ والترخيص:",
        "config-license-none": "لا تذييل ترخيص",
        "config-license-cc-by-sa": "المشاع الإبداعي النسبة للمؤلف المشاركة بالمثل",
        "config-license-gfdl": "رخصة جنو للوثائق الحرة 1.3 أو لاحقة",
        "config-license-pd": "ملكية عامة",
        "config-license-cc-choose": "اختر ترخيص مشاع إبداعي مخصص",
+       "config-license-help": "يضع العديد من الويكيات العامة جميع المساهمات تحت [https://freedomdefined.org/Definition خصة حرة]، \nوهذا يساعد على خلق شعور بالملكية المجتمعية ويشجع على المساهمة طويلة الأجل، \nليس من الضروري عموما استخدام ويكي خاص أو شركة. \n\nإذا كنت تريد أن تكون قادرا على استخدام النص من ويكيبيديا، وتريد أن تكون ويكيبيديا قادرة على قبول النص الذي تم نسخه من الويكي الخاص بك، فيجب عليك اختيار <strong>{{int:config-license-cc-by-sa}}</strong>. \n\nاستخدمت ويكيبيديا في السابق رخصة جنو للوثائق الحرة، \nGFDL هو ترخيص صالح، ولكن من الصعب فهمه، \nمن الصعب أيضا إعادة استخدام المحتوى المرخص بموجب GFDL.",
        "config-email-settings": "إعدادات البريد الإلكتروني",
        "config-enable-email": "تمكين البريد الإلكتروني الصادرة",
        "config-enable-email-help": "إذا كنت تريد إرسال بريد إلكتروني إلى العمل، [Config-dbsupport-oracle/manual/en/mail.configuration.php إعدات بريد PHP's] تحتاج لأن يتم تكوينها بشكل صحيح. إذا كنت لا تريد أيا من ميزات البريد الإلكتروني، يمكنك تعطيلها هنا.",
        "config-email-watchlist": "تمكين إشعارات قائمة المراقبة",
        "config-email-watchlist-help": "السماح للمستخدمين بالحصول على إشعارات حول صفحاتهم المراقبة إذا كانوا قد مكنوها في تفضيلاتهم.",
        "config-email-auth": "تمكين مصادقة البريد الإلكتروني",
+       "config-email-auth-help": "إذا تم تمكين هذا الخيار، يتعين على المستخدمين تأكيد عنوان بريدهم الإلكتروني باستخدام رابط يتم إرساله إليهم عند تعيينهم أو تغييره. \nيمكن لعناوين البريد الإلكتروني الموثوقة فقط تلقي رسائل البريد الإلكتروني من المستخدمين الآخرين أو تغيير رسائل الإشعارات الإلكترونية. \nيعد تعيين هذا الخيار <strong> موصى به</strong> لمواقع الويكي العامة بسبب احتمال إساءة استخدام ميزات البريد الإلكتروني.",
        "config-email-sender": "عنوان البريد الإلكتروني المُرسِل:",
+       "config-email-sender-help": "أدخل عنوان البريد الإلكتروني لاستخدامه كعنوان المرسل في البريد الإلكتروني الصادر، \nهذا هو المكان الذي سيتم إرساله إلى المستبعد،\nتتطلب العديد من خوادم البريد أن يكون جزء اسم النطاق صالحا على الأقل.",
        "config-upload-settings": "الصور وتحميل الملفات",
        "config-upload-enable": "تمكين تحميل الملفات",
+       "config-upload-help": "من المحتمل أن تؤدي عمليات رفع الملفات إلى تعريض الخادم لمخاطر أمنية. \nلمزيد من المعلومات; اقرأ [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Security قسم الأمن] في الدليل. \n\nلتمكين رفع الملفات; قم بتغيير الوضع في الدليل الفرعي <code>الصور</code> تحت الدليل الرئيسي لميدياويكي كي يتمكن خادم الويب من الكتابة إليه، \nثم قم بتمكين هذا الخيار.",
        "config-upload-deleted": "المجلد للملفات المحذوفة:",
        "config-upload-deleted-help": "اختر دليلا لأرشفة الملفات المحذوفة،\nمن الناحية المثالية، لا يمكن الوصول إلى هذا من الويب.",
        "config-logo": "مسار الشعار:",
+       "config-logo-help": "يحتوي المظهر الافتراضي لميدياويكي على مساحة لشعار 135x160 بكسل فوق قائمة الشريط الجانبي، \nارفع صورة بالحجم المناسب، وأدخل المسار هنا. \n\nيمكنك استخدام <code>$wgStylePath</code> أو <code>$wgScriptPath</code> إذا كان شعارك مرتبطا بتلك المسارات. \n\nإذا كنت لا تريد شعارا، فاترك هذا الصندوق فارغا.",
        "config-instantcommons": "تمكين الاستخدام الفوري لويكيميديا كومنز InstantCommons",
+       "config-instantcommons-help": "[https://www.mediawiki.org/wiki/InstantCommons كومنز الفوري] هي ميزة تسمح للويكي باستخدام الصور والأصوات والوسائط الأخرى الموجودة على موقع [https://commons.wikimedia.org/ ويكيميديا كومنز]،\nمن أجل القيام بذلك; يتطلب ميدياويكي الوصول إلى الإنترنت. \n\nلمزيد من المعلومات حول هذه الميزة، بما في ذلك تعليمات حول كيفية إعدادها لمواقع ويكي بخلاف ويكيميديا كومنز; يُرجَى الرجوع إلى [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgForeignFileRepos الدليل].",
        "config-cc-error": "لم يعطِ منتقي رخصة المشاع الإبداعي أية نتيجة; أدخل اسم الترخيص يدويا.",
        "config-cc-again": "اختر مجددًا",
        "config-cc-not-chosen": "اختر أي ترخيص تريده ثم اضغط على \"متابعة\".",
        "config-advanced-settings": "ضبط متقدم",
        "config-cache-options": "إعدادات التخزين المؤقت الكائن:",
+       "config-cache-help": "يُستخدَم التخزين المؤقت للأداة لتحسين سرعة ميدياويكي عن طريق تخزين البيانات المستخدمة بشكل متكرر، \nيتم تشجيع المواقع المتوسطة والكبيرة إلى حد كبير على تمكينه، وستشاهد المواقع الصغيرة الفوائد أيضا.",
        "config-cache-none": "لا يوجد تخزين مؤقت (هذا لا يزيل أية وظيفة، لكن قد تتأثر السرعة على مواقع الويكي الكبيرة)",
        "config-cache-accel": "كائن التخزين المؤقت PHP (APC أو APCu أو  XCache أو XCache أو WinCache)",
        "config-cache-memcached": "استخدم Memcached (يتطلب إعدادت إضافية)",
        "config-install-pg-plpgsql": "التحقق من لغة PL/pgSQL",
        "config-pg-no-plpgsql": "تحتاج إلى تثبيت لغة PL/pgSQL في قاعدة البيانات $1",
        "config-pg-no-create-privs": "الحساب الذي حددته للتنزيل ليست لديه امتيازات كافية لإنشاء حساب.",
+       "config-pg-not-in-role": "الحساب الذي حددته لمستخدم الويب موجود بالفعل، \nالحساب الذي حددته للتثبيت ليس مستخدما متميزا وليس عضوا في دور مستخدم الويب; لذلك لا يمكنه إنشاء كائنات يملكها مستخدم الويب. \n\nميدياويكي حاليا يتطلب أن تكون الجداول مملوكة من قبل مستخدم الويب; يُرجَى تحديد اسم حساب ويب آخر، أو النقر فوق \"رجوع\" وتحديد مستخدم تثبيت متميز مناسب.",
        "config-install-user": "إنشاء مستخدم قاعدة البيانات",
        "config-install-user-alreadyexists": "المستخدم \"$1\" موجود بالفعل",
        "config-install-user-create-failed": "إنشاء مستخدم \"$1\" فشل:$2",
        "config-install-mainpage-failed": "لم يتمكن من إدراج الصفحة الرئيسية: $1",
        "config-install-done": "<strong>مبروك!</strong>\nلقد قمت بتثبيت ميدياوكي.\n\nقام المثبت بتوليد ملف <code>LocalSettings.php</code>.\nيحتوي هذا الملف على كل تضبيطاتك.\n\nسيتطلب تشغيل الويكي منك تنزيل هذا الملف ووضعه في مجلد التثبيت الخاص بالويكي (نفس المجلد المحتوي على <code>index.php</code>). سيبدأ التنزيل تلقائيا.\n\nلو لم يُعرض عليك التنزيل أو قمت أنت بالغائه، يمكنك تنزيله بالضغط على الوصلة أدناه:\n\n$3\n\n<strong>تنبيه:</strong> لو لم تقم بهذا الآن، لن يكن ملف الضبط متاحا لك لاحقا إذا غادرت التثبيت بدون تنزيله.\n\nعندما تنتهي من وضع الملف بمكانه، يمكنك <strong>[$2 دخول الويكي]</strong>.",
        "config-install-done-path": "<strong>مبروك!</strong>\nلقد قمت بتثبيت ميدياوكي.\n\nقام المثبت بتوليد ملف <code>LocalSettings.php</code>.\nيحتوي هذا الملف على كل تضبيطاتك.\n\nسيتطلب تشغيل الويكي منك تنزيل هذا الملف ووضعه في <code>$4</code> (نفس المجلد المحتوي على index.php). سيبدأ التنزيل تلقائيا.\n\nلو لم يُعرض عليك التنزيل أو قمت أنت بالغائه، يمكنك تنزيله بالضغط على الوصلة أدناه:\n\n$3\n\n<strong>تنبيه:</strong> لو لم تقم بهذا الآن، لن يكن ملف الضبط متاحا لك لاحقا إذا غادرت التثبيت بدون تنزيله.\n\nعندما تنتهي من وضع الملف بمكانه، يمكنك <code>[$2 دخول الويكي]</strong>.",
+       "config-install-success": "لقد تم تثبيت ميدياويكي بنجاح; يمكنك الآن \nزيارة <$1$2> لعرض الويكي الخاص بك. \nإذا كانت لديك أسئلة، فاطلع على قائمة الأسئلة الشائعة: \n<https://www.mediawiki.org/wiki/Manual:FAQ> أو استخدم أحد \nمنتديات الدعم المرتبطة بهذه الصفحة.",
        "config-download-localsettings": "تنزيل <code>LocalSettings.php</code>",
        "config-help": "مساعدة",
        "config-help-tooltip": "اضغط للتوسيع",
index fc61940..c2ec005 100644 (file)
@@ -10,7 +10,8 @@
                        "Matěj Suchánek",
                        "LordMsz",
                        "Seb35",
-                       "Ilimanaq29"
+                       "Ilimanaq29",
+                       "Dvorapa"
                ]
        },
        "config-desc": "Instalační program pro MediaWiki",
        "config-support-info": "MediaWiki podporuje následující databázové systémy:\n\n$1\n\nPokud v nabídce níže nevidíte databázový systém, který chcete použít, musíte pro zapnutí podpory následovat instrukce odkázané výše.",
        "config-dbsupport-mysql": "* [{{int:version-db-mysql-url}} MySQL] je pro MediaWiki hlavní platformou a je podporováno nejlépe. MediaWiki pracuje také s [{{int:version-db-mariadb-url}} MariaDB] a [{{int:version-db-percona-url}} Percona Server], které jsou s MySQL kompatibilní. ([https://secure.php.net/manual/en/mysql.installation.php Jak zkompilovat PHP s podporou MySQL])",
        "config-dbsupport-postgres": "* [{{int:version-db-postgres-url}} PostgreSQL] je populární otevřený databázový systém používaný jako alternativa k MySQL. ([https://secure.php.net/manual/en/pgsql.installation.php Jak přeložit PHP s podporou PostgreSQL])",
-       "config-dbsupport-sqlite": "* [{{int:version-db-sqlite-url}} SQLite] je velmi dobře podporovaný odlehčený databázový systém. ([http://www.php.net/manual/en/pdo.installation.php Jak přeložit PHP s podporou SQLite], používá PDO)",
-       "config-dbsupport-oracle": "* [{{int:version-db-oracle-url}} Oracle] je komerční podniková databáze. ([http://www.php.net/manual/en/oci8.installation.php Jak přeložit PHP s podporou OCI8])",
-       "config-dbsupport-mssql": "* [{{int:version-db-mssql-url}} Microsoft SQL Server] je komerční podniková databáze pro Windows. ([Config-dbsupport-oracle/manual/en/sqlsrv.installation.php Jak přeložit PHP s podporou SQLSRV])",
+       "config-dbsupport-sqlite": "* [{{int:version-db-sqlite-url}} SQLite] je velmi dobře podporovaný odlehčený databázový systém. ([https://secure.php.net/manual/en/pdo.installation.php Jak přeložit PHP s podporou SQLite], používá PDO)",
+       "config-dbsupport-oracle": "* [{{int:version-db-oracle-url}} Oracle] je komerční podniková databáze. ([https://secure.php.net/manual/en/oci8.installation.php Jak přeložit PHP s podporou OCI8])",
+       "config-dbsupport-mssql": "* [{{int:version-db-mssql-url}} Microsoft SQL Server] je komerční podniková databáze pro Windows. ([https://secure.php.net/manual/en/sqlsrv.installation.php Jak přeložit PHP s podporou SQLSRV])",
        "config-header-mysql": "Nastavení MySQL",
        "config-header-postgres": "Nastavení PostgreSQL",
        "config-header-sqlite": "Nastavení SQLite",
        "config-license-help": "Mnoho veřejných wiki všechny příspěvky zveřejňuje pod některou [https://freedomdefined.org/Definition/Cs svobodnou licencí].\nTo pomáhá vytvořit duch komunitního vlastnictví a povzbuzuje dlouhodobé přispívání.\nTo obecně není potřeba u soukromé nebo firemní wiki.\n\nPokud chcete být schopni používat text z Wikipedie a chcete, aby Wikipedie byla schopna přijímat text okopírovaný z vaší wiki, měli byste zvolit <strong>{{int:config-license-cc-by-sa}}</strong>.\n\nDříve Wikipedie používala GNU Free Documentation License.\nGFDL je platná licence, ale složité jí porozumět.\nTaké je komplikované používat obsah licencovaný pod GFDL.",
        "config-email-settings": "Nastavení e-mailu",
        "config-enable-email": "Zapnout odchozí e-mail",
-       "config-enable-email-help": "Pokud chcete, aby e-mail fungoval, je potřeba správně nakonfigurovat [Config-dbsupport-oracle/manual/en/mail.configuration.php e-mailová nastavení PHP].\nPokud nechcete žádné e-mailové funkce, můžete je zde vypnout.",
+       "config-enable-email-help": "Pokud chcete, aby e-mail fungoval, je potřeba správně nakonfigurovat [https://secure.php.net/manual/en/mail.configuration.php e-mailová nastavení PHP].\nPokud nechcete žádné e-mailové funkce, můžete je zde vypnout.",
        "config-email-user": "Umožnit vzájemné e-maily mezi uživateli",
        "config-email-user-help": "Umožní všem uživatelům posílat si navzájem e-maily, pokud si to zapnout v uživatelském nastavení.",
        "config-email-usertalk": "Umožnit notifikace k uživatelským diskusím",
index 4c39ac0..add4c27 100644 (file)
        "config-nofile": "Die Datei „$1“ konnte nicht gefunden werden. Wurde sie gelöscht?",
        "config-extension-link": "Wusstest du, dass dein Wiki die Nutzung von [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Extensions Erweiterungen] unterstützt?\n\nDu kannst die [https://www.mediawiki.org/wiki/Special:MyLanguage/Category:Extensions_by_category Erweiterungen nach Kategorie] anzeigen oder die [https://www.mediawiki.org/wiki/Extension_Matrix Erweiterungs-Matrix] aufrufen, um eine vollständige Liste der Erweiterungen zu sehen.",
        "config-skins-screenshots": "$1 (Bildschirmfotos: $2)",
+       "config-skins-screenshot": "$1 ($2)",
        "config-extensions-requires": "$1 (erfordert $2)",
        "config-screenshot": "Bildschirmfoto",
        "mainpagetext": "<strong>MediaWiki wurde installiert.</strong>",
index 1eb460a..4253a89 100644 (file)
@@ -35,7 +35,8 @@
                        "Irus",
                        "Tinss",
                        "KATRINE1992",
-                       "MarcoAurelio"
+                       "MarcoAurelio",
+                       "Adjen"
                ]
        },
        "config-desc": "El instalador de MediaWiki",
        "config-type-mssql": "Microsoft SQL Server",
        "config-support-info": "MediaWiki es compatible con los siguientes sistemas de bases de datos:\n\n$1\n\nSi no encuentras en el listado el sistema de base de datos que estás intentando utilizar, sigue las instrucciones enlazadas arriba para activar la compatibilidad.",
        "config-dbsupport-mysql": "* [{{int:version-db-mysql-url}} MySQL] es la base de datos mayoritaria para MediaWiki y la que goza de mayor compatibilidad. MediaWiki también funciona con [{{int:version-db-mariadb-url}} MariaDB] y [{{int:version-db-percona-url}} Percona Server], que son compatibles con MySQL. ([https://secure.php.net/manual/es/mysql.installation.php Cómo compilar PHP con compatibilidad MySQL])",
-       "config-dbsupport-postgres": "[{{int:version-db-postgres-url}} PostgreSQL] es un sistema de base de datos popular de código abierto, alternativa a MySQL. ([https://secure.php.net/manual/es/pgsql.installation.php Cómo compilar PHP con compatibilidad PostgreSQL]).",
-       "config-dbsupport-sqlite": "* [{{int:version-db-sqlite-url}} SQLite] es un sistema de base de datos ligero con gran compatibilidad con MediaWiki. ([http://www.php.net/manual/es/pdo.installation.php Cómo compilar PHP con compatibilidad SQLite], usando PDO)",
-       "config-dbsupport-oracle": "* [{{int:version-db-oracle-url}} Oracle] es una base de datos comercial a nivel empresarial. ([http://www.php.net/manual/es/oci8.installation.php Cómo compilar PHP con compatibilidad con OCI8])",
+       "config-dbsupport-postgres": "[{{int:version-db-postgres-url}} PostgreSQL] es un sistema de base de datos popular de código abierto, alternativa a MySQL. ([https://secure.php.net/manual/es/pgsql.installation.php Cómo compilar PHP con compatibilidad PostgreSQL]).",
+       "config-dbsupport-sqlite": "* [{{int:version-db-sqlite-url}} SQLite] es un sistema de base de datos ligero con gran compatibilidad con MediaWiki. ([https://secure.php.net/manual/en/pdo.installation.php Cómo compilar PHP con compatibilidad SQLite], usando PDO)",
+       "config-dbsupport-oracle": "* [{{int:version-db-oracle-url}} Oracle] es una base de datos comercial a nivel empresarial. ([https://secure.php.net/manual/en/oci8.installation.php Cómo compilar PHP con compatibilidad con OCI8])",
        "config-dbsupport-mssql": "* [{{int:version-db-mssql-url}} Microsoft SQL Server] es un sistema comercial de base de datos empresariales para Windows. ([Config-dbsupport-oracle/manual/en/sqlsrv.installation.php Cómo compilar PHP con compatibilidad con SQLSRV])",
        "config-header-mysql": "Configuración de MySQL",
        "config-header-postgres": "Configuración de PostgreSQL",
        "config-license-help": "Muchos wikis públicos ponen todas las contribuciones bajo una [https://freedomdefined.org/Definition licencia libre].\nEsto ayuda a crear un sentido de propiedad comunitaria y alienta la contribución a largo plazo.\nEsto no es generalmente necesario para un wiki privado o corporativo.\n\nSi deseas poder utilizar texto de Wikipedia, y deseas que Wikipedia pueda aceptar el texto copiado de tu wiki, debes elegir <strong>{{int:config-license-cc-by-sa}}</strong>.\n\nWikipedia utilizaba anteriormente la licencia de documentación libre de GNU (GFDL).\nLa GFDL es una licencia válida, pero es difícil de entender.\nTambién es difícil reutilizar el contenido licenciado bajo la GFDL.",
        "config-email-settings": "Configuración de correo electrónico",
        "config-enable-email": "Activar el envío de correos electrónicos",
-       "config-enable-email-help": "Si quieres que el correo electrónico funcione, la [Config-dbsupport-oracle/manual/en/mail.configuration.php configuración PHP de correo electrónico] debe ser la correcta.\nSi no quieres la funcionalidad de correo electrónico, puedes desactivarla aquí.",
+       "config-enable-email-help": "Si quieres que el correo electrónico funcione, la [https://secure.php.net/manual/en/mail.configuration.php configuración PHP de correo electrónico] debe ser configurada correctamente.\nSi no quieres ninguna funcionalidad del correo electrónico, puedes desactivarla aquí.",
        "config-email-user": "Activar correo electrónico entre usuarios",
        "config-email-user-help": "Permitir que todos los usuarios intercambien correos electrónicos si lo han activado en sus preferencias.",
        "config-email-usertalk": "Activar notificaciones de páginas de discusión de usuarios",
index 3f8a00f..93c95ab 100644 (file)
        "config-type-mssql": "Microsoft SQL Szerver",
        "config-support-info": "A MediaWiki a következő adatbázisrendszereket támogatja:\n\n$1\n\nHa az alábbi listán nem találod azt a rendszert, melyet használni szeretnél, a fenti linken található instrukciókat követve engedélyezheted a támogatását.",
        "config-dbsupport-mysql": "* A [{{int:version-db-mysql-url}} MySQL] a MediaWiki elsődleges célpontja, így a legjobban támogatott. A MediaWiki elfut [{{int:version-db-mariadb-url}} MariaDB-n] és [{{int:version-db-percona-url}} Percona Serveren] is, mivel ezek MySQL-kompatibilisek. ([https://secure.php.net/manual/en/mysql.installation.php Hogyan fordítható a PHP MySQL-támogatással])",
-       "config-dbsupport-postgres": "* A [{{int:version-db-postgres-url}} PostgreSQL] népszerű, nyílt forráskódú adatbázisrendszer, a MySQL alternatívája. ([Config-dbsupport-oracle/manual/en/pgsql.installation.php Hogyan fordítható a PHP PostgreSQL-támogatással])",
+       "config-dbsupport-postgres": "* A [{{int:version-db-postgres-url}} PostgreSQL] népszerű, nyílt forráskódú adatbázisrendszer, a MySQL alternatívája. ([https://secure.php.net/manual/en/pgsql.installation.php Hogyan fordítható a PHP PostgreSQL-támogatással])",
        "config-dbsupport-sqlite": "* Az [{{int:version-db-sqlite-url}} SQLite] egy könnyű, nagyon jól támogatott adatbázisrendszer. ([http://www.php.net/manual/en/pdo.installation.php Hogyan fordítható a PHP SQLite-támogatással], PDO-t használ)",
        "config-dbsupport-oracle": "* Az [{{int:version-db-oracle-url}} Oracle] kereskedelmi, vállalati adatbázisrendszer. ([http://www.php.net/manual/en/oci8.installation.php Hogyan fordítható a PHP OCI8-támogatással])",
-       "config-dbsupport-mssql": "* A [{{int:version-db-mssql-url}} Microsoft SQL Server] kereskedelmi, vállalati adatbázisrendszer. ([Config-dbsupport-oracle/manual/en/sqlsrv.installation.php Hogyan fordítható a PHP SQLSRV-támogatással])",
+       "config-dbsupport-mssql": "* A [{{int:version-db-mssql-url}} Microsoft SQL Server] kereskedelmi, vállalati adatbázisrendszer. ([https://secure.php.net/manual/en/sqlsrv.installation.php Hogyan fordítható a PHP SQLSRV-támogatással])",
        "config-header-mysql": "MySQL-beállítások",
        "config-header-postgres": "PostgreSQL-beállítások",
        "config-header-sqlite": "SQLite-beállítások",
index 03bcf64..bc3abc8 100644 (file)
        "config-support-info": "O MediaWiki suporta os sistemas de banco de dados a seguir:\n\n$1\n\nSe você não vê o sistema de banco de dados que você está tentando usar listados abaixo, siga as instruções relacionadas acima, para ativar o suporte.",
        "config-dbsupport-mysql": "* [{{int:version-db-mysql-url}} MySQL] é o principal alvo para o MediaWiki e é melhor suportado. O MediaWiki também funciona com [{{int:version-db-mariadb-url}} MariaDB] e [{{int:version-db-percona-url}} Percona Server], que são compatíveis com MySQL. ([Http://www.php.net/manual/en/mysqli.installation.php Como compilar PHP com suporte a MySQL])",
        "config-dbsupport-postgres": "* [{{int:version-db-postgres-url}} PostgreSQL] é um popular sistema de banco de dados de código aberto como uma alternativa para o MySQL. ([https://secure.php.net/manual/en/pgsql.installation.php Como compilar o PHP com suporte PostgreSQL])",
-       "config-dbsupport-sqlite": "* [{{int:version-db-sqlite-url}} SQLite] é um sistema de banco de dados leve que é muito bem suportado. ([http://www.php.net/manual/en/pdo.installation.php como compilar o PHP com suporte a SQLite], usa DOP)",
-       "config-dbsupport-oracle": "* [{{int:version-db-oracle-url}} Oracle] é um banco de dados comercial de empresas. ([http://www.php.net/manual/en/oci8.installation.php Como compilar o PHP com suporte OCI8])",
-       "config-dbsupport-mssql": "* [{{int:version-db-mssql-url}} Microsoft SQL Server] é uma banco de dados comercial do Windows para empresas. ([Config-dbsupport-oracle/manual/en/sqlsrv.installation.php Como compilar o PHP com suporte SQLSRV])",
+       "config-dbsupport-sqlite": "* O [{{int:version-db-sqlite-url}} SQLite] é uma plataforma de base de dados ligeira muito bem suportada. ([https://secure.php.net/manual/en/pdo.installation.php Como compilar PHP com suporte para SQLite], usa PDO.)",
+       "config-dbsupport-oracle": "* A [{{int:version-db-oracle-url}} Oracle] é uma base de dados comercial para empresas. ([https://secure.php.net/manual/en/oci8.installation.php Como compilar PHP com suporte para OCI8].)",
+       "config-dbsupport-mssql": "* O [{{int:version-db-mssql-url}} Microsoft SQL Server] é uma base de dados comercial do Windows para empresas. ([https://secure.php.net/manual/en/sqlsrv.installation.php Como compilar PHP com suporte para SQLSRV].)",
        "config-header-mysql": "Configurações MySQL",
        "config-header-postgres": "Configurações PostgreSQL",
        "config-header-sqlite": "Configurações SQLite",
index dcf39b0..26931f8 100644 (file)
        "config-type-oracle": "Oracle",
        "config-type-mssql": "Microsoft SQL Server",
        "config-support-info": "O MediaWiki suporta as seguintes plataformas de base de dados:\n\n$1\n\nSe a plataforma que pretende usar não está listada abaixo, siga as instruções nas hiperligações acima para ativar o suporte.",
-       "config-dbsupport-mysql": "* [{{int:version-db-mysql-url}} MySQL] é a plataforma primária do MediaWiki e é a melhor suportada. O MediaWiki também trabalha com [{{int:version-db-mariadb-url}} MariaDB] e [{{int:version-db-percona-url}} Percona Server], que são compatíveis com MySQL. ([https://secure.php.net/manual/en/mysql.installation.php Como compilar PHP com suporte a MySQL])",
-       "config-dbsupport-postgres": "* O [{{int:version-db-postgres-url}} PostgreSQL] é uma plataforma popular de base de dados de código aberto, alternativa ao MySQL. ([https://secure.php.net/manual/en/pgsql.installation.php Como compilar o PHP com suporte PostgreSQL])",
-       "config-dbsupport-sqlite": "* O [{{int:version-db-sqlite-url}} SQLite] é uma plataforma de base de dados ligeira muito bem suportada. ([http://www.php.net/manual/en/pdo.installation.php Como compilar o PHP com suporte SQLite], usa PDO)",
-       "config-dbsupport-oracle": "* [{{int:version-db-oracle-url}} Oracle] é uma base de dados comercial para empresas. ([http://www.php.net/manual/en/oci8.installation.php Como compilar o PHP com suporte OCI8])",
-       "config-dbsupport-mssql": "* O [{{int:version-db-mssql-url}} Microsoft SQL Server] é uma base de dados comercial do Windows para empresas. ([Config-dbsupport-oracle/manual/en/sqlsrv.installation.php Como compilar o PHP com suporte SQLSRV])",
+       "config-dbsupport-mysql": "* O [{{int:version-db-mysql-url}} MySQL] é a base de dados preferida para o MediaWiki e a melhor suportada. O MediaWiki também trabalha com [{{int:version-db-mariadb-url}} MariaDB] e [{{int:version-db-percona-url}} Percona Server], que são compatíveis com MySQL. ([https://secure.php.net/manual/en/mysqli.installation.php Como compilar PHP com suporte para MySQL].)",
+       "config-dbsupport-postgres": "* O [{{int:version-db-postgres-url}} PostgreSQL] é uma plataforma popular de base de dados de código aberto, alternativa ao MySQL. ([https://secure.php.net/manual/en/pgsql.installation.php Como compilar PHP com suporte para PostgreSQL].)",
+       "config-dbsupport-sqlite": "* O [{{int:version-db-sqlite-url}} SQLite] é uma plataforma de base de dados ligeira muito bem suportada. ([https://secure.php.net/manual/en/pdo.installation.php Como compilar PHP com suporte para SQLite], usa PDO.)",
+       "config-dbsupport-oracle": "* A [{{int:version-db-oracle-url}} Oracle] é uma base de dados comercial para empresas. ([https://secure.php.net/manual/en/oci8.installation.php Como compilar PHP com suporte para OCI8].)",
+       "config-dbsupport-mssql": "* O [{{int:version-db-mssql-url}} Microsoft SQL Server] é uma base de dados comercial do Windows para empresas. ([https://secure.php.net/manual/en/sqlsrv.installation.php Como compilar PHP com suporte para SQLSRV].)",
        "config-header-mysql": "Definições MySQL",
        "config-header-postgres": "Definições PostgreSQL",
        "config-header-sqlite": "Definições SQLite",
        "config-license-help": "Muitas wikis de acesso público licenciam todas as colaborações com uma [https://freedomdefined.org/Definition licença livre].\nIsto ajuda a criar um sentido de propriedade da comunidade e encoraja as colaborações a longo prazo.\nTal não é geralmente necessário nas wikis privadas ou corporativas.\n\nSe pretende que seja possível usar textos da Wikipédia na sua wiki e que seja possível a Wikipédia aceitar textos copiados da sua wiki, deve escolher a licença <strong>{{int:config-license-cc-by-sa}}</strong>..\n\nA licença anterior da Wikipédia era a licença GNU Free Documentation License.\nA GFDL é uma licença válida, mas de difícil compreensão.\nTambém é difícil reutilizar conteúdos licenciados com a GFDL.",
        "config-email-settings": "Definições do correio eletrónico",
        "config-enable-email": "Ativar mensagens eletrónicas de saída",
-       "config-enable-email-help": "Se quer que o correio eletrónico funcione, as [Config-dbsupport-oracle/manual/en/mail.configuration.php definições de correio eletrónico do PHP] têm de estar configuradas corretamente.\nSe não pretende viabilizar qualquer funcionalidade de correio eletrónico, pode desativá-lo aqui.",
+       "config-enable-email-help": "Se quer que o correio eletrónico funcione, as [https://secure.php.net/manual/en/mail.configuration.php definições de correio eletrónico do PHP] têm de estar configuradas corretamente.\nSe não pretende viabilizar qualquer funcionalidade de correio eletrónico, pode desativá-lo aqui.",
        "config-email-user": "Ativar mensagens eletrónicas entre utilizadores",
        "config-email-user-help": "Permitir que todos os utilizadores troquem entre si mensagens de correio eletrónico, se tiverem ativado esta funcionalidade nas suas preferências.",
        "config-email-usertalk": "Ativar notificações de alterações à página de discussão dos utilizadores",
index 04e96d0..400b959 100644 (file)
        "config-type-mssql": "Microsoft SQL Server",
        "config-support-info": "MediaWiki stöder följande databassystem:\n\n$1\n\nOm du inte ser det databassystem som du försöker använda nedanstående, följ då instruktionerna länkade ovan för aktivera stöd för det.",
        "config-dbsupport-mysql": "* [{{int:version-db-mysql-url}} MySQL] är det primära målet för MediaWiki och det stöds bäst. MediaWiki fungerar även med [{{int:version-db-mariadb-url}} MariaDB] och [{{int:version-db-percona-url}} Percona Server], som är kompatibla med MySQL. ([https://secure.php.net/manual/en/mysqli.installation.php Hur man kompilerar PHP med stöd för MySQL])",
-       "config-dbsupport-postgres": "* [{{int:version-db-postgres-url}} PostgreSQL] är ett populärt databassystem med öppen källkod som ett alternativ till MySQL. ([Config-dbsupport-oracle/manual/en/pgsql.installation.php Hur man kompilerar PHP med PostgreSQL stöd])",
-       "config-dbsupport-sqlite": "* [{{int:version-db-sqlite-url}} SQLite] är en lättviktsdatabassystem med väldigt bra stöd. ([http://www.php.net/manual/en/pdo.installation.php Hur man kompilerar PHP med SQLite stöd], använder PDO)",
-       "config-dbsupport-oracle": "* [{{int:version-db-oracle-url}} Oracle] är en kommersiellt databas för företag. ([http://www.php.net/manual/en/oci8.installation.php Hur man kompilerar PHP med OCI8 stöd])",
-       "config-dbsupport-mssql": "* [{{int:version-db-mssql-url}} Microsoft SQL Server] är en kommersiellt databas för företag för Windows. ([Config-dbsupport-oracle/manual/en/sqlsrv.installation.php Hur man kompilerar PHP med SQLSRV stöd])",
+       "config-dbsupport-postgres": "* [{{int:version-db-postgres-url}} PostgreSQL] är ett populärt databassystem med öppen källkod som ett alternativ till MySQL. ([https://secure.php.net/manual/en/pgsql.installation.php Hur man kompilerar PHP med PostgreSQL-stöd])",
+       "config-dbsupport-sqlite": "* [{{int:version-db-sqlite-url}} SQLite] är en lättviktsdatabassystem med väldigt bra stöd. ([https://secure.php.net/manual/en/pdo.installation.php Hur man kompilerar PHP med SQLite stöd], använder PDO)",
+       "config-dbsupport-oracle": "* [{{int:version-db-oracle-url}} Oracle] är en kommersiellt databas för företag. ([https://secure.php.net/manual/en/oci8.installation.php Hur man kompilerar PHP med OCI8 stöd])",
+       "config-dbsupport-mssql": "* [{{int:version-db-mssql-url}} Microsoft SQL Server] är en kommersiellt databas för företag för Windows. ([https://secure.php.net/manual/en/sqlsrv.installation.php Hur man kompilerar PHP med SQLSRV stöd])",
        "config-header-mysql": "MySQL-inställningar",
        "config-header-postgres": "PostgreSQL-inställningar",
        "config-header-sqlite": "SQLite-inställningar",
index 9de16c4..7fed3e1 100644 (file)
@@ -33,7 +33,7 @@ class DBConnRef implements IDatabase {
                $this->lb = $lb;
                if ( $conn instanceof Database ) {
                        $this->conn = $conn; // live handle
-               } elseif ( count( $conn ) >= 4 && $conn[self::FLD_DOMAIN] !== false ) {
+               } elseif ( is_array( $conn ) && count( $conn ) >= 4 && $conn[self::FLD_DOMAIN] !== false ) {
                        $this->params = $conn;
                } else {
                        throw new InvalidArgumentException( "Missing lazy connection arguments." );
index 4e39537..2696f4d 100644 (file)
@@ -3138,11 +3138,8 @@ class Parser {
                                for ( $i = 0; $i < $argsLength; $i++ ) {
                                        $funcArgs[] = $args->item( $i );
                                }
-                               try {
-                                       $result = $this->callParserFunction( $frame, $func, $funcArgs );
-                               } catch ( Exception $ex ) {
-                                       throw $ex;
-                               }
+
+                               $result = $this->callParserFunction( $frame, $func, $funcArgs );
 
                                // Extract any forwarded flags
                                if ( isset( $result['title'] ) ) {
index d5a706a..755d108 100644 (file)
@@ -46,7 +46,6 @@ use OutputPage;
 use Parser;
 use ParserOptions;
 use PreferencesForm;
-use PreferencesFormOOUI;
 use Psr\Log\LoggerAwareTrait;
 use Psr\Log\NullLogger;
 use Skin;
@@ -1484,12 +1483,12 @@ class DefaultPreferencesFactory implements PreferencesFactory {
         * @param IContextSource $context
         * @param string $formClass
         * @param array $remove Array of items to remove
-        * @return PreferencesForm
+        * @return HTMLForm
         */
        public function getForm(
                User $user,
                IContextSource $context,
-               $formClass = PreferencesFormOOUI::class,
+               $formClass = PreferencesForm::class,
                array $remove = []
        ) {
                if ( SpecialPreferences::isOouiEnabled( $context ) ) {
@@ -1511,7 +1510,7 @@ class DefaultPreferencesFactory implements PreferencesFactory {
                }
 
                /**
-                * @var $htmlForm PreferencesForm
+                * @var $htmlForm HTMLForm
                 */
                $htmlForm = new $formClass( $formDescriptor, $context, 'prefs' );
 
@@ -1522,7 +1521,7 @@ class DefaultPreferencesFactory implements PreferencesFactory {
                # Used message keys: 'accesskey-preferences-save', 'tooltip-preferences-save'
                $htmlForm->setSubmitTooltip( 'preferences-save' );
                $htmlForm->setSubmitID( 'prefcontrol' );
-               $htmlForm->setSubmitCallback( function ( array $formData, PreferencesForm $form ) {
+               $htmlForm->setSubmitCallback( function ( array $formData, HTMLForm $form ) {
                        return $this->submitForm( $formData, $form );
                } );
 
@@ -1627,10 +1626,10 @@ class DefaultPreferencesFactory implements PreferencesFactory {
         * Handle the form submission if everything validated properly
         *
         * @param array $formData
-        * @param PreferencesForm $form
+        * @param HTMLForm $form
         * @return bool|Status|string
         */
-       protected function saveFormData( $formData, PreferencesForm $form ) {
+       protected function saveFormData( $formData, HTMLForm $form ) {
                $user = $form->getModifiedUser();
                $hiddenPrefs = $this->config->get( 'HiddenPrefs' );
                $result = true;
@@ -1707,10 +1706,10 @@ class DefaultPreferencesFactory implements PreferencesFactory {
         * @deprecated since 1.31, its inception
         *
         * @param array $formData
-        * @param PreferencesForm $form
+        * @param HTMLForm $form
         * @return bool|Status|string
         */
-       public function legacySaveFormData( $formData, PreferencesForm $form ) {
+       public function legacySaveFormData( $formData, HTMLForm $form ) {
                return $this->saveFormData( $formData, $form );
        }
 
@@ -1718,10 +1717,10 @@ class DefaultPreferencesFactory implements PreferencesFactory {
         * Save the form data and reload the page
         *
         * @param array $formData
-        * @param PreferencesForm $form
+        * @param HTMLForm $form
         * @return Status
         */
-       protected function submitForm( array $formData, PreferencesForm $form ) {
+       protected function submitForm( array $formData, HTMLForm $form ) {
                $res = $this->saveFormData( $formData, $form );
 
                if ( $res ) {
@@ -1759,10 +1758,10 @@ class DefaultPreferencesFactory implements PreferencesFactory {
         * @deprecated since 1.31, its inception
         *
         * @param array $formData
-        * @param PreferencesForm $form
+        * @param HTMLForm $form
         * @return Status
         */
-       public function legacySubmitForm( array $formData, PreferencesForm $form ) {
+       public function legacySubmitForm( array $formData, HTMLForm $form ) {
                return $this->submitForm( $formData, $form );
        }
 
index 1cbd878..1b8a4a8 100644 (file)
@@ -1504,7 +1504,7 @@ MESSAGE;
         *
         * @param string $script JavaScript code
         * @param string $nonce [optional] Content-Security-Policy nonce (from OutputPage::getCSPNonce)
-        * @return WrappedString HTML
+        * @return string|WrappedString HTML
         */
        public static function makeInlineScript( $script, $nonce = null ) {
                $js = self::makeLoaderConditionalScript( $script );
index b49a2da..b9ff732 100644 (file)
@@ -18,6 +18,7 @@
  * @file
  */
 
+use Wikimedia\WrappedString;
 use Wikimedia\WrappedStringList;
 
 /**
@@ -351,7 +352,7 @@ class ResourceLoaderClientHtml {
                        $startupQuery
                );
 
-               return WrappedStringList::join( "\n", $chunks );
+               return WrappedString::join( "\n", $chunks );
        }
 
        /**
@@ -369,7 +370,7 @@ class ResourceLoaderClientHtml {
                        );
                }
 
-               return WrappedStringList::join( "\n", $chunks );
+               return WrappedString::join( "\n", $chunks );
        }
 
        private function getContext( $group, $type ) {
index e1f2969..156df67 100644 (file)
@@ -18,6 +18,9 @@
  * @file
  */
 
+use Wikimedia\WrappedString;
+use Wikimedia\WrappedStringList;
+
 /**
  * New base template for a skin's template extended from QuickTemplate
  * this class features helper methods that provide common ways of interacting
@@ -754,14 +757,14 @@ abstract class BaseTemplate extends QuickTemplate {
         * debug stuff. This should be called right before outputting the closing
         * body and html tags.
         *
-        * @return string
+        * @return string|WrappedStringList HTML
         * @since 1.29
         */
-       function getTrail() {
-               $html = MWDebug::getDebugHTML( $this->getSkin()->getContext() );
-               $html .= $this->get( 'bottomscripts' );
-               $html .= $this->get( 'reporttime' );
-
-               return $html;
+       public function getTrail() {
+               return WrappedString::join( "\n", [
+                       MWDebug::getDebugHTML( $this->getSkin()->getContext() ),
+                       $this->get( 'bottomscripts' ),
+                       $this->get( 'reporttime' )
+               ] );
        }
 }
index 252c08d..6739c08 100644 (file)
@@ -21,6 +21,8 @@
  */
 
 use MediaWiki\MediaWikiServices;
+use Wikimedia\WrappedString;
+use Wikimedia\WrappedStringList;
 
 /**
  * @defgroup Skins Skins
@@ -402,7 +404,7 @@ abstract class Skin extends ContextSource {
        /**
         * @param array $data
         * @param string $nonce OutputPage::getCSPNonce()
-        * @return string
+        * @return string|WrappedString HTML
         */
        static function makeVariablesScript( $data, $nonce = null ) {
                if ( $data ) {
@@ -675,16 +677,22 @@ abstract class Skin extends ContextSource {
        /**
         * This gets called shortly before the "</body>" tag.
         *
-        * @return string HTML-wrapped JS code to be put before "</body>"
+        * @return string|WrappedStringList HTML containing scripts to put before `</body>`
         */
        function bottomScripts() {
                // TODO and the suckage continues. This function is really just a wrapper around
                // OutputPage::getBottomScripts() which takes a Skin param. This should be cleaned
                // up at some point
-               $bottomScriptText = $this->getOutput()->getBottomScripts();
-               Hooks::run( 'SkinAfterBottomScripts', [ $this, &$bottomScriptText ] );
-
-               return $bottomScriptText;
+               $chunks = [ $this->getOutput()->getBottomScripts() ];
+
+               // Keep the hook appendage separate to preserve WrappedString objects.
+               // This enables BaseTemplate::getTrail() to merge them where possible.
+               $extraHtml = '';
+               Hooks::run( 'SkinAfterBottomScripts', [ $this, &$extraHtml ] );
+               if ( $extraHtml !== '' ) {
+                       $chunks[] = $extraHtml;
+               }
+               return WrappedString::join( "\n", $chunks );
        }
 
        /**
index 7a4cde9..27b6a07 100644 (file)
@@ -40,6 +40,8 @@ class SpecialPreferences extends SpecialPage {
 
        /**
         * Check if OOUI mode is enabled, by config or query string
+        *
+        * @since 1.32
         * @param IContextSource $context The context.
         * @return bool
         */
index 48728a3..d4e5151 100644 (file)
@@ -233,9 +233,7 @@ class SpecialVersion extends SpecialPage {
                }
                $software[$dbr->getSoftwareLink()] = $dbr->getServerInfo();
 
-               if ( IcuCollation::getICUVersion() ) {
-                       $software['[http://site.icu-project.org/ ICU]'] = IcuCollation::getICUVersion();
-               }
+               $software['[http://site.icu-project.org/ ICU]'] = INTL_ICU_VERSION;
 
                // Allow a hook to add/remove items.
                Hooks::run( 'SoftwareInfo', [ &$software ] );
diff --git a/includes/specials/forms/PreferencesForm.php b/includes/specials/forms/PreferencesForm.php
deleted file mode 100644 (file)
index a124410..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-<?php
-/**
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- */
-
-/**
- * Temporarily define PreferencesForm as an interface, so PreferencesFormOOUI
- * and PreferencesFormLegacy can implement it.
- *
- * When PreferencesFormLegacy we can merge PreferencesFormOOUI with PreferencesForm.
- */
-interface PreferencesForm {
-}
index e6bc494..8193c5a 100644 (file)
@@ -22,8 +22,10 @@ use MediaWiki\MediaWikiServices;
 
 /**
  * Form to edit user preferences.
+ *
+ * @since 1.32
  */
-class PreferencesFormLegacy extends HTMLForm implements PreferencesForm {
+class PreferencesFormLegacy extends HTMLForm {
        // Override default value from HTMLForm
        protected $mSubSectionBeforeFields = false;
 
@@ -141,3 +143,10 @@ class PreferencesFormLegacy extends HTMLForm implements PreferencesForm {
                return array_keys( array_filter( $this->mFieldTree, 'is_array' ) );
        }
 }
+
+// Retain the old class name for backwards compatibility.
+// In the future, this alias will be changed to point to PreferencesFormOOUI.
+class PreferencesForm extends PreferencesFormLegacy {
+}
+// Phan doesn't understand class_alias()?
+// class_alias( PreferencesFormLegacy::class, 'PreferencesForm' );
index 3a5adbb..47a595f 100644 (file)
 
 /**
  * Form to edit user preferences.
+ *
+ * @since 1.32
  */
-class PreferencesFormOOUI extends OOUIHTMLForm implements PreferencesForm {
+class PreferencesFormOOUI extends OOUIHTMLForm {
        // Override default value from HTMLForm
        protected $mSubSectionBeforeFields = false;
 
index 98d2c0e..b437653 100644 (file)
@@ -389,7 +389,7 @@ class ClassCollector {
                        return;
                }
                // Note: When changing class name discovery logic,
-               // AutoLoaderTest.php may also need to be updated.
+               // AutoLoaderStructureTest.php may also need to be updated.
                switch ( $token[0] ) {
                        case T_NAMESPACE:
                        case T_CLASS:
index be0c037..1320a57 100644 (file)
@@ -2990,8 +2990,8 @@ class Language {
                global $wgAllUnicodeFixes;
                $s = UtfNormal\Validator::cleanUp( $s );
                if ( $wgAllUnicodeFixes ) {
-                       $s = $this->transformUsingPairFile( 'normalize-ar.ser', $s );
-                       $s = $this->transformUsingPairFile( 'normalize-ml.ser', $s );
+                       $s = $this->transformUsingPairFile( 'normalize-ar.php', $s );
+                       $s = $this->transformUsingPairFile( 'normalize-ml.php', $s );
                }
 
                return $s;
@@ -3011,12 +3011,10 @@ class Language {
         * @throws MWException
         * @return string
         */
-       function transformUsingPairFile( $file, $string ) {
+       protected function transformUsingPairFile( $file, $string ) {
                if ( !isset( $this->transformData[$file] ) ) {
-                       $data = wfGetPrecompiledData( $file );
-                       if ( $data === false ) {
-                               throw new MWException( __METHOD__ . ": The transformation file $file is missing" );
-                       }
+                       global $IP;
+                       $data = require "$IP/languages/data/{$file}";
                        $this->transformData[$file] = new ReplacementArray( $data );
                }
                return $this->transformData[$file]->replace( $string );
index 90e3751..efdf5a2 100644 (file)
@@ -44,7 +44,7 @@ class LanguageAr extends Language {
                global $wgFixArabicUnicode;
                $s = parent::normalize( $s );
                if ( $wgFixArabicUnicode ) {
-                       $s = $this->transformUsingPairFile( 'normalize-ar.ser', $s );
+                       $s = $this->transformUsingPairFile( 'normalize-ar.php', $s );
                }
                return $s;
        }
index df894a1..cf45762 100644 (file)
@@ -45,7 +45,7 @@ class LanguageMl extends Language {
                global $wgFixMalayalamUnicode;
                $s = parent::normalize( $s );
                if ( $wgFixMalayalamUnicode ) {
-                       $s = $this->transformUsingPairFile( 'normalize-ml.ser', $s );
+                       $s = $this->transformUsingPairFile( 'normalize-ml.php', $s );
                }
                return $s;
        }
diff --git a/languages/data/normalize-ar.php b/languages/data/normalize-ar.php
new file mode 100644 (file)
index 0000000..c1daf20
--- /dev/null
@@ -0,0 +1,735 @@
+<?php
+// File created by maintenance/generateNormalizerDataAr.php
+return [
+       'ﭐ' => 'ٱ',
+       'ﭑ' => 'ٱ',
+       'ﭒ' => 'ٻ',
+       'ﭓ' => 'ٻ',
+       'ﭔ' => 'ٻ',
+       'ﭕ' => 'ٻ',
+       'ﭖ' => 'پ',
+       'ﭗ' => 'پ',
+       'ﭘ' => 'پ',
+       'ﭙ' => 'پ',
+       'ﭚ' => 'ڀ',
+       'ﭛ' => 'ڀ',
+       'ﭜ' => 'ڀ',
+       'ﭝ' => 'ڀ',
+       'ﭞ' => 'ٺ',
+       'ﭟ' => 'ٺ',
+       'ﭠ' => 'ٺ',
+       'ﭡ' => 'ٺ',
+       'ﭢ' => 'ٿ',
+       'ﭣ' => 'ٿ',
+       'ﭤ' => 'ٿ',
+       'ﭥ' => 'ٿ',
+       'ﭦ' => 'ٹ',
+       'ﭧ' => 'ٹ',
+       'ﭨ' => 'ٹ',
+       'ﭩ' => 'ٹ',
+       'ﭪ' => 'ڤ',
+       'ﭫ' => 'ڤ',
+       'ﭬ' => 'ڤ',
+       'ﭭ' => 'ڤ',
+       'ﭮ' => 'ڦ',
+       'ﭯ' => 'ڦ',
+       'ﭰ' => 'ڦ',
+       'ﭱ' => 'ڦ',
+       'ﭲ' => 'ڄ',
+       'ﭳ' => 'ڄ',
+       'ﭴ' => 'ڄ',
+       'ﭵ' => 'ڄ',
+       'ﭶ' => 'ڃ',
+       'ﭷ' => 'ڃ',
+       'ﭸ' => 'ڃ',
+       'ﭹ' => 'ڃ',
+       'ﭺ' => 'چ',
+       'ﭻ' => 'چ',
+       'ﭼ' => 'چ',
+       'ﭽ' => 'چ',
+       'ﭾ' => 'ڇ',
+       'ﭿ' => 'ڇ',
+       'ﮀ' => 'ڇ',
+       'ﮁ' => 'ڇ',
+       'ﮂ' => 'ڍ',
+       'ﮃ' => 'ڍ',
+       'ﮄ' => 'ڌ',
+       'ﮅ' => 'ڌ',
+       'ﮆ' => 'ڎ',
+       'ﮇ' => 'ڎ',
+       'ﮈ' => 'ڈ',
+       'ﮉ' => 'ڈ',
+       'ﮊ' => 'ژ',
+       'ﮋ' => 'ژ',
+       'ﮌ' => 'ڑ',
+       'ﮍ' => 'ڑ',
+       'ﮎ' => 'ک',
+       'ﮏ' => 'ک',
+       'ﮐ' => 'ک',
+       'ﮑ' => 'ک',
+       'ﮒ' => 'گ',
+       'ﮓ' => 'گ',
+       'ﮔ' => 'گ',
+       'ﮕ' => 'گ',
+       'ﮖ' => 'ڳ',
+       'ﮗ' => 'ڳ',
+       'ﮘ' => 'ڳ',
+       'ﮙ' => 'ڳ',
+       'ﮚ' => 'ڱ',
+       'ﮛ' => 'ڱ',
+       'ﮜ' => 'ڱ',
+       'ﮝ' => 'ڱ',
+       'ﮞ' => 'ں',
+       'ﮟ' => 'ں',
+       'ﮠ' => 'ڻ',
+       'ﮡ' => 'ڻ',
+       'ﮢ' => 'ڻ',
+       'ﮣ' => 'ڻ',
+       'ﮤ' => 'ۀ',
+       'ﮥ' => 'ۀ',
+       'ﮦ' => 'ہ',
+       'ﮧ' => 'ہ',
+       'ﮨ' => 'ہ',
+       'ﮩ' => 'ہ',
+       'ﮪ' => 'ھ',
+       'ﮫ' => 'ھ',
+       'ﮬ' => 'ھ',
+       'ﮭ' => 'ھ',
+       'ﮮ' => 'ے',
+       'ﮯ' => 'ے',
+       'ﮰ' => 'ۓ',
+       'ﮱ' => 'ۓ',
+       'ﯓ' => 'ڭ',
+       'ﯔ' => 'ڭ',
+       'ﯕ' => 'ڭ',
+       'ﯖ' => 'ڭ',
+       'ﯗ' => 'ۇ',
+       'ﯘ' => 'ۇ',
+       'ﯙ' => 'ۆ',
+       'ﯚ' => 'ۆ',
+       'ﯛ' => 'ۈ',
+       'ﯜ' => 'ۈ',
+       'ﯝ' => 'ٷ',
+       'ﯞ' => 'ۋ',
+       'ﯟ' => 'ۋ',
+       'ﯠ' => 'ۅ',
+       'ﯡ' => 'ۅ',
+       'ﯢ' => 'ۉ',
+       'ﯣ' => 'ۉ',
+       'ﯤ' => 'ې',
+       'ﯥ' => 'ې',
+       'ﯦ' => 'ې',
+       'ﯧ' => 'ې',
+       'ﯨ' => 'ى',
+       'ﯩ' => 'ى',
+       'ﯪ' => 'ئا',
+       'ﯫ' => 'ئا',
+       'ﯬ' => 'ئە',
+       'ﯭ' => 'ئە',
+       'ﯮ' => 'ئو',
+       'ﯯ' => 'ئو',
+       'ﯰ' => 'ئۇ',
+       'ﯱ' => 'ئۇ',
+       'ﯲ' => 'ئۆ',
+       'ﯳ' => 'ئۆ',
+       'ﯴ' => 'ئۈ',
+       'ﯵ' => 'ئۈ',
+       'ﯶ' => 'ئې',
+       'ﯷ' => 'ئې',
+       'ﯸ' => 'ئې',
+       'ﯹ' => 'ئى',
+       'ﯺ' => 'ئى',
+       'ﯻ' => 'ئى',
+       'ﯼ' => 'ی',
+       'ﯽ' => 'ی',
+       'ﯾ' => 'ی',
+       'ﯿ' => 'ی',
+       'ﰀ' => 'ئج',
+       'ﰁ' => 'ئح',
+       'ﰂ' => 'ئم',
+       'ﰃ' => 'ئى',
+       'ﰄ' => 'ئي',
+       'ﰅ' => 'بج',
+       'ﰆ' => 'بح',
+       'ﰇ' => 'بخ',
+       'ﰈ' => 'بم',
+       'ﰉ' => 'بى',
+       'ﰊ' => 'بي',
+       'ﰋ' => 'تج',
+       'ﰌ' => 'تح',
+       'ﰍ' => 'تخ',
+       'ﰎ' => 'تم',
+       'ﰏ' => 'تى',
+       'ﰐ' => 'تي',
+       'ﰑ' => 'ثج',
+       'ﰒ' => 'ثم',
+       'ﰓ' => 'ثى',
+       'ﰔ' => 'ثي',
+       'ﰕ' => 'جح',
+       'ﰖ' => 'جم',
+       'ﰗ' => 'حج',
+       'ﰘ' => 'حم',
+       'ﰙ' => 'خج',
+       'ﰚ' => 'خح',
+       'ﰛ' => 'خم',
+       'ﰜ' => 'سج',
+       'ﰝ' => 'سح',
+       'ﰞ' => 'سخ',
+       'ﰟ' => 'سم',
+       'ﰠ' => 'صح',
+       'ﰡ' => 'صم',
+       'ﰢ' => 'ضج',
+       'ﰣ' => 'ضح',
+       'ﰤ' => 'ضخ',
+       'ﰥ' => 'ضم',
+       'ﰦ' => 'طح',
+       'ﰧ' => 'طم',
+       'ﰨ' => 'ظم',
+       'ﰩ' => 'عج',
+       'ﰪ' => 'عم',
+       'ﰫ' => 'غج',
+       'ﰬ' => 'غم',
+       'ﰭ' => 'فج',
+       'ﰮ' => 'فح',
+       'ﰯ' => 'فخ',
+       'ﰰ' => 'فم',
+       'ﰱ' => 'فى',
+       'ﰲ' => 'في',
+       'ﰳ' => 'قح',
+       'ﰴ' => 'قم',
+       'ﰵ' => 'قى',
+       'ﰶ' => 'قي',
+       'ﰷ' => 'كا',
+       'ﰸ' => 'كج',
+       'ﰹ' => 'كح',
+       'ﰺ' => 'كخ',
+       'ﰻ' => 'كل',
+       'ﰼ' => 'كم',
+       'ﰽ' => 'كى',
+       'ﰾ' => 'كي',
+       'ﰿ' => 'لج',
+       'ﱀ' => 'لح',
+       'ﱁ' => 'لخ',
+       'ﱂ' => 'لم',
+       'ﱃ' => 'لى',
+       'ﱄ' => 'لي',
+       'ﱅ' => 'مج',
+       'ﱆ' => 'مح',
+       'ﱇ' => 'مخ',
+       'ﱈ' => 'مم',
+       'ﱉ' => 'مى',
+       'ﱊ' => 'مي',
+       'ﱋ' => 'نج',
+       'ﱌ' => 'نح',
+       'ﱍ' => 'نخ',
+       'ﱎ' => 'نم',
+       'ﱏ' => 'نى',
+       'ﱐ' => 'ني',
+       'ﱑ' => 'هج',
+       'ﱒ' => 'هم',
+       'ﱓ' => 'هى',
+       'ﱔ' => 'هي',
+       'ﱕ' => 'يج',
+       'ﱖ' => 'يح',
+       'ﱗ' => 'يخ',
+       'ﱘ' => 'يم',
+       'ﱙ' => 'يى',
+       'ﱚ' => 'يي',
+       'ﱛ' => 'ذٰ',
+       'ﱜ' => 'رٰ',
+       'ﱝ' => 'ىٰ',
+       'ﱞ' => ' ٌّ',
+       'ﱟ' => ' ٍّ',
+       'ﱠ' => ' َّ',
+       'ﱡ' => ' ُّ',
+       'ﱢ' => ' ِّ',
+       'ﱣ' => ' ّٰ',
+       'ﱤ' => 'ئر',
+       'ﱥ' => 'ئز',
+       'ﱦ' => 'ئم',
+       'ﱧ' => 'ئن',
+       'ﱨ' => 'ئى',
+       'ﱩ' => 'ئي',
+       'ﱪ' => 'بر',
+       'ﱫ' => 'بز',
+       'ﱬ' => 'بم',
+       'ﱭ' => 'بن',
+       'ﱮ' => 'بى',
+       'ﱯ' => 'بي',
+       'ﱰ' => 'تر',
+       'ﱱ' => 'تز',
+       'ﱲ' => 'تم',
+       'ﱳ' => 'تن',
+       'ﱴ' => 'تى',
+       'ﱵ' => 'تي',
+       'ﱶ' => 'ثر',
+       'ﱷ' => 'ثز',
+       'ﱸ' => 'ثم',
+       'ﱹ' => 'ثن',
+       'ﱺ' => 'ثى',
+       'ﱻ' => 'ثي',
+       'ﱼ' => 'فى',
+       'ﱽ' => 'في',
+       'ﱾ' => 'قى',
+       'ﱿ' => 'قي',
+       'ﲀ' => 'كا',
+       'ﲁ' => 'كل',
+       'ﲂ' => 'كم',
+       'ﲃ' => 'كى',
+       'ﲄ' => 'كي',
+       'ﲅ' => 'لم',
+       'ﲆ' => 'لى',
+       'ﲇ' => 'لي',
+       'ﲈ' => 'ما',
+       'ﲉ' => 'مم',
+       'ﲊ' => 'نر',
+       'ﲋ' => 'نز',
+       'ﲌ' => 'نم',
+       'ﲍ' => 'نن',
+       'ﲎ' => 'نى',
+       'ﲏ' => 'ني',
+       'ﲐ' => 'ىٰ',
+       'ﲑ' => 'ير',
+       'ﲒ' => 'يز',
+       'ﲓ' => 'يم',
+       'ﲔ' => 'ين',
+       'ﲕ' => 'يى',
+       'ﲖ' => 'يي',
+       'ﲗ' => 'ئج',
+       'ﲘ' => 'ئح',
+       'ﲙ' => 'ئخ',
+       'ﲚ' => 'ئم',
+       'ﲛ' => 'ئه',
+       'ﲜ' => 'بج',
+       'ﲝ' => 'بح',
+       'ﲞ' => 'بخ',
+       'ﲟ' => 'بم',
+       'ﲠ' => 'به',
+       'ﲡ' => 'تج',
+       'ﲢ' => 'تح',
+       'ﲣ' => 'تخ',
+       'ﲤ' => 'تم',
+       'ﲥ' => 'ته',
+       'ﲦ' => 'ثم',
+       'ﲧ' => 'جح',
+       'ﲨ' => 'جم',
+       'ﲩ' => 'حج',
+       'ﲪ' => 'حم',
+       'ﲫ' => 'خج',
+       'ﲬ' => 'خم',
+       'ﲭ' => 'سج',
+       'ﲮ' => 'سح',
+       'ﲯ' => 'سخ',
+       'ﲰ' => 'سم',
+       'ﲱ' => 'صح',
+       'ﲲ' => 'صخ',
+       'ﲳ' => 'صم',
+       'ﲴ' => 'ضج',
+       'ﲵ' => 'ضح',
+       'ﲶ' => 'ضخ',
+       'ﲷ' => 'ضم',
+       'ﲸ' => 'طح',
+       'ﲹ' => 'ظم',
+       'ﲺ' => 'عج',
+       'ﲻ' => 'عم',
+       'ﲼ' => 'غج',
+       'ﲽ' => 'غم',
+       'ﲾ' => 'فج',
+       'ﲿ' => 'فح',
+       'ﳀ' => 'فخ',
+       'ﳁ' => 'فم',
+       'ﳂ' => 'قح',
+       'ﳃ' => 'قم',
+       'ﳄ' => 'كج',
+       'ﳅ' => 'كح',
+       'ﳆ' => 'كخ',
+       'ﳇ' => 'كل',
+       'ﳈ' => 'كم',
+       'ﳉ' => 'لج',
+       'ﳊ' => 'لح',
+       'ﳋ' => 'لخ',
+       'ﳌ' => 'لم',
+       'ﳍ' => 'له',
+       'ﳎ' => 'مج',
+       'ﳏ' => 'مح',
+       'ﳐ' => 'مخ',
+       'ﳑ' => 'مم',
+       'ﳒ' => 'نج',
+       'ﳓ' => 'نح',
+       'ﳔ' => 'نخ',
+       'ﳕ' => 'نم',
+       'ﳖ' => 'نه',
+       'ﳗ' => 'هج',
+       'ﳘ' => 'هم',
+       'ﳙ' => 'هٰ',
+       'ﳚ' => 'يج',
+       'ﳛ' => 'يح',
+       'ﳜ' => 'يخ',
+       'ﳝ' => 'يم',
+       'ﳞ' => 'يه',
+       'ﳟ' => 'ئم',
+       'ﳠ' => 'ئه',
+       'ﳡ' => 'بم',
+       'ﳢ' => 'به',
+       'ﳣ' => 'تم',
+       'ﳤ' => 'ته',
+       'ﳥ' => 'ثم',
+       'ﳦ' => 'ثه',
+       'ﳧ' => 'سم',
+       'ﳨ' => 'سه',
+       'ﳩ' => 'شم',
+       'ﳪ' => 'شه',
+       'ﳫ' => 'كل',
+       'ﳬ' => 'كم',
+       'ﳭ' => 'لم',
+       'ﳮ' => 'نم',
+       'ﳯ' => 'نه',
+       'ﳰ' => 'يم',
+       'ﳱ' => 'يه',
+       'ﳲ' => 'ـَّ',
+       'ﳳ' => 'ـُّ',
+       'ﳴ' => 'ـِّ',
+       'ﳵ' => 'طى',
+       'ﳶ' => 'طي',
+       'ﳷ' => 'عى',
+       'ﳸ' => 'عي',
+       'ﳹ' => 'غى',
+       'ﳺ' => 'غي',
+       'ﳻ' => 'سى',
+       'ﳼ' => 'سي',
+       'ﳽ' => 'شى',
+       'ﳾ' => 'شي',
+       'ﳿ' => 'حى',
+       'ﴀ' => 'حي',
+       'ﴁ' => 'جى',
+       'ﴂ' => 'جي',
+       'ﴃ' => 'خى',
+       'ﴄ' => 'خي',
+       'ﴅ' => 'صى',
+       'ﴆ' => 'صي',
+       'ﴇ' => 'ضى',
+       'ﴈ' => 'ضي',
+       'ﴉ' => 'شج',
+       'ﴊ' => 'شح',
+       'ﴋ' => 'شخ',
+       'ﴌ' => 'شم',
+       'ﴍ' => 'شر',
+       'ﴎ' => 'سر',
+       'ﴏ' => 'صر',
+       'ﴐ' => 'ضر',
+       'ﴑ' => 'طى',
+       'ﴒ' => 'طي',
+       'ﴓ' => 'عى',
+       'ﴔ' => 'عي',
+       'ﴕ' => 'غى',
+       'ﴖ' => 'غي',
+       'ﴗ' => 'سى',
+       'ﴘ' => 'سي',
+       'ﴙ' => 'شى',
+       'ﴚ' => 'شي',
+       'ﴛ' => 'حى',
+       'ﴜ' => 'حي',
+       'ﴝ' => 'جى',
+       'ﴞ' => 'جي',
+       'ﴟ' => 'خى',
+       'ﴠ' => 'خي',
+       'ﴡ' => 'صى',
+       'ﴢ' => 'صي',
+       'ﴣ' => 'ضى',
+       'ﴤ' => 'ضي',
+       'ﴥ' => 'شج',
+       'ﴦ' => 'شح',
+       'ﴧ' => 'شخ',
+       'ﴨ' => 'شم',
+       'ﴩ' => 'شر',
+       'ﴪ' => 'سر',
+       'ﴫ' => 'صر',
+       'ﴬ' => 'ضر',
+       'ﴭ' => 'شج',
+       'ﴮ' => 'شح',
+       'ﴯ' => 'شخ',
+       'ﴰ' => 'شم',
+       'ﴱ' => 'سه',
+       'ﴲ' => 'شه',
+       'ﴳ' => 'طم',
+       'ﴴ' => 'سج',
+       'ﴵ' => 'سح',
+       'ﴶ' => 'سخ',
+       'ﴷ' => 'شج',
+       'ﴸ' => 'شح',
+       'ﴹ' => 'شخ',
+       'ﴺ' => 'طم',
+       'ﴻ' => 'ظم',
+       'ﴼ' => 'اً',
+       'ﴽ' => 'اً',
+       'ﵐ' => 'تجم',
+       'ﵑ' => 'تحج',
+       'ﵒ' => 'تحج',
+       'ﵓ' => 'تحم',
+       'ﵔ' => 'تخم',
+       'ﵕ' => 'تمج',
+       'ﵖ' => 'تمح',
+       'ﵗ' => 'تمخ',
+       'ﵘ' => 'جمح',
+       'ﵙ' => 'جمح',
+       'ﵚ' => 'حمي',
+       'ﵛ' => 'حمى',
+       'ﵜ' => 'سحج',
+       'ﵝ' => 'سجح',
+       'ﵞ' => 'سجى',
+       'ﵟ' => 'سمح',
+       'ﵠ' => 'سمح',
+       'ﵡ' => 'سمج',
+       'ﵢ' => 'سمم',
+       'ﵣ' => 'سمم',
+       'ﵤ' => 'صحح',
+       'ﵥ' => 'صحح',
+       'ﵦ' => 'صمم',
+       'ﵧ' => 'شحم',
+       'ﵨ' => 'شحم',
+       'ﵩ' => 'شجي',
+       'ﵪ' => 'شمخ',
+       'ﵫ' => 'شمخ',
+       'ﵬ' => 'شمم',
+       'ﵭ' => 'شمم',
+       'ﵮ' => 'ضحى',
+       'ﵯ' => 'ضخم',
+       'ﵰ' => 'ضخم',
+       'ﵱ' => 'طمح',
+       'ﵲ' => 'طمح',
+       'ﵳ' => 'طمم',
+       'ﵴ' => 'طمي',
+       'ﵵ' => 'عجم',
+       'ﵶ' => 'عمم',
+       'ﵷ' => 'عمم',
+       'ﵸ' => 'عمى',
+       'ﵹ' => 'غمم',
+       'ﵺ' => 'غمي',
+       'ﵻ' => 'غمى',
+       'ﵼ' => 'فخم',
+       'ﵽ' => 'فخم',
+       'ﵾ' => 'قمح',
+       'ﵿ' => 'قمم',
+       'ﶀ' => 'لحم',
+       'ﶁ' => 'لحي',
+       'ﶂ' => 'لحى',
+       'ﶃ' => 'لجج',
+       'ﶄ' => 'لجج',
+       'ﶅ' => 'لخم',
+       'ﶆ' => 'لخم',
+       'ﶇ' => 'لمح',
+       'ﶈ' => 'لمح',
+       'ﶉ' => 'محج',
+       'ﶊ' => 'محم',
+       'ﶋ' => 'محي',
+       'ﶌ' => 'مجح',
+       'ﶍ' => 'مجم',
+       'ﶎ' => 'مخج',
+       'ﶏ' => 'مخم',
+       'ﶒ' => 'مجخ',
+       'ﶓ' => 'همج',
+       'ﶔ' => 'همم',
+       'ﶕ' => 'نحم',
+       'ﶖ' => 'نحى',
+       'ﶗ' => 'نجم',
+       'ﶘ' => 'نجم',
+       'ﶙ' => 'نجى',
+       'ﶚ' => 'نمي',
+       'ﶛ' => 'نمى',
+       'ﶜ' => 'يمم',
+       'ﶝ' => 'يمم',
+       'ﶞ' => 'بخي',
+       'ﶟ' => 'تجي',
+       'ﶠ' => 'تجى',
+       'ﶡ' => 'تخي',
+       'ﶢ' => 'تخى',
+       'ﶣ' => 'تمي',
+       'ﶤ' => 'تمى',
+       'ﶥ' => 'جمي',
+       'ﶦ' => 'جحى',
+       'ﶧ' => 'جمى',
+       'ﶨ' => 'سخى',
+       'ﶩ' => 'صحي',
+       'ﶪ' => 'شحي',
+       'ﶫ' => 'ضحي',
+       'ﶬ' => 'لجي',
+       'ﶭ' => 'لمي',
+       'ﶮ' => 'يحي',
+       'ﶯ' => 'يجي',
+       'ﶰ' => 'يمي',
+       'ﶱ' => 'ممي',
+       'ﶲ' => 'قمي',
+       'ﶳ' => 'نحي',
+       'ﶴ' => 'قمح',
+       'ﶵ' => 'لحم',
+       'ﶶ' => 'عمي',
+       'ﶷ' => 'كمي',
+       'ﶸ' => 'نجح',
+       'ﶹ' => 'مخي',
+       'ﶺ' => 'لجم',
+       'ﶻ' => 'كمم',
+       'ﶼ' => 'لجم',
+       'ﶽ' => 'نجح',
+       'ﶾ' => 'جحي',
+       'ﶿ' => 'حجي',
+       'ﷀ' => 'مجي',
+       'ﷁ' => 'فمي',
+       'ﷂ' => 'بحي',
+       'ﷃ' => 'كمم',
+       'ﷄ' => 'عجم',
+       'ﷅ' => 'صمم',
+       'ﷆ' => 'سخي',
+       'ﷇ' => 'نجي',
+       'ﷰ' => 'صلے',
+       'ﷱ' => 'قلے',
+       'ﷲ' => 'الله',
+       'ﷳ' => 'اكبر',
+       'ﷴ' => 'محمد',
+       'ﷵ' => 'صلعم',
+       'ﷶ' => 'رسول',
+       'ﷷ' => 'عليه',
+       'ﷸ' => 'وسلم',
+       'ﷹ' => 'صلى',
+       'ﷺ' => 'صلى الله عليه وسلم',
+       'ﷻ' => 'جل جلاله',
+       '﷼' => 'ریال',
+       'ﹰ' => ' ً',
+       'ﹱ' => 'ـً',
+       'ﹲ' => ' ٌ',
+       'ﹴ' => ' ٍ',
+       'ﹶ' => ' َ',
+       'ﹷ' => 'ـَ',
+       'ﹸ' => ' ُ',
+       'ﹹ' => 'ـُ',
+       'ﹺ' => ' ِ',
+       'ﹻ' => 'ـِ',
+       'ﹼ' => ' ّ',
+       'ﹽ' => 'ـّ',
+       'ﹾ' => ' ْ',
+       'ﹿ' => 'ـْ',
+       'ﺀ' => 'ء',
+       'ﺁ' => 'آ',
+       'ﺂ' => 'آ',
+       'ﺃ' => 'أ',
+       'ﺄ' => 'أ',
+       'ﺅ' => 'ؤ',
+       'ﺆ' => 'ؤ',
+       'ﺇ' => 'إ',
+       'ﺈ' => 'إ',
+       'ﺉ' => 'ئ',
+       'ﺊ' => 'ئ',
+       'ﺋ' => 'ئ',
+       'ﺌ' => 'ئ',
+       'ﺍ' => 'ا',
+       'ﺎ' => 'ا',
+       'ﺏ' => 'ب',
+       'ﺐ' => 'ب',
+       'ﺑ' => 'ب',
+       'ﺒ' => 'ب',
+       'ﺓ' => 'ة',
+       'ﺔ' => 'ة',
+       'ﺕ' => 'ت',
+       'ﺖ' => 'ت',
+       'ﺗ' => 'ت',
+       'ﺘ' => 'ت',
+       'ﺙ' => 'ث',
+       'ﺚ' => 'ث',
+       'ﺛ' => 'ث',
+       'ﺜ' => 'ث',
+       'ﺝ' => 'ج',
+       'ﺞ' => 'ج',
+       'ﺟ' => 'ج',
+       'ﺠ' => 'ج',
+       'ﺡ' => 'ح',
+       'ﺢ' => 'ح',
+       'ﺣ' => 'ح',
+       'ﺤ' => 'ح',
+       'ﺥ' => 'خ',
+       'ﺦ' => 'خ',
+       'ﺧ' => 'خ',
+       'ﺨ' => 'خ',
+       'ﺩ' => 'د',
+       'ﺪ' => 'د',
+       'ﺫ' => 'ذ',
+       'ﺬ' => 'ذ',
+       'ﺭ' => 'ر',
+       'ﺮ' => 'ر',
+       'ﺯ' => 'ز',
+       'ﺰ' => 'ز',
+       'ﺱ' => 'س',
+       'ﺲ' => 'س',
+       'ﺳ' => 'س',
+       'ﺴ' => 'س',
+       'ﺵ' => 'ش',
+       'ﺶ' => 'ش',
+       'ﺷ' => 'ش',
+       'ﺸ' => 'ش',
+       'ﺹ' => 'ص',
+       'ﺺ' => 'ص',
+       'ﺻ' => 'ص',
+       'ﺼ' => 'ص',
+       'ﺽ' => 'ض',
+       'ﺾ' => 'ض',
+       'ﺿ' => 'ض',
+       'ﻀ' => 'ض',
+       'ﻁ' => 'ط',
+       'ﻂ' => 'ط',
+       'ﻃ' => 'ط',
+       'ﻄ' => 'ط',
+       'ﻅ' => 'ظ',
+       'ﻆ' => 'ظ',
+       'ﻇ' => 'ظ',
+       'ﻈ' => 'ظ',
+       'ﻉ' => 'ع',
+       'ﻊ' => 'ع',
+       'ﻋ' => 'ع',
+       'ﻌ' => 'ع',
+       'ﻍ' => 'غ',
+       'ﻎ' => 'غ',
+       'ﻏ' => 'غ',
+       'ﻐ' => 'غ',
+       'ﻑ' => 'ف',
+       'ﻒ' => 'ف',
+       'ﻓ' => 'ف',
+       'ﻔ' => 'ف',
+       'ﻕ' => 'ق',
+       'ﻖ' => 'ق',
+       'ﻗ' => 'ق',
+       'ﻘ' => 'ق',
+       'ﻙ' => 'ك',
+       'ﻚ' => 'ك',
+       'ﻛ' => 'ك',
+       'ﻜ' => 'ك',
+       'ﻝ' => 'ل',
+       'ﻞ' => 'ل',
+       'ﻟ' => 'ل',
+       'ﻠ' => 'ل',
+       'ﻡ' => 'م',
+       'ﻢ' => 'م',
+       'ﻣ' => 'م',
+       'ﻤ' => 'م',
+       'ﻥ' => 'ن',
+       'ﻦ' => 'ن',
+       'ﻧ' => 'ن',
+       'ﻨ' => 'ن',
+       'ﻩ' => 'ه',
+       'ﻪ' => 'ه',
+       'ﻫ' => 'ه',
+       'ﻬ' => 'ه',
+       'ﻭ' => 'و',
+       'ﻮ' => 'و',
+       'ﻯ' => 'ى',
+       'ﻰ' => 'ى',
+       'ﻱ' => 'ي',
+       'ﻲ' => 'ي',
+       'ﻳ' => 'ي',
+       'ﻴ' => 'ي',
+       'ﻵ' => 'لآ',
+       'ﻶ' => 'لآ',
+       'ﻷ' => 'لأ',
+       'ﻸ' => 'لأ',
+       'ﻹ' => 'لإ',
+       'ﻺ' => 'لإ',
+       'ﻻ' => 'لا',
+       'ﻼ' => 'لا',
+];
diff --git a/languages/data/normalize-ml.php b/languages/data/normalize-ml.php
new file mode 100644 (file)
index 0000000..ca89a5a
--- /dev/null
@@ -0,0 +1,10 @@
+<?php
+// File created by maintenance/generateNormalizerDataMl.php
+return [
+       'ണ്‍' => 'ൺ',
+       'ന്‍' => 'ൻ',
+       'ര്‍' => 'ർ',
+       'ല്‍' => 'ൽ',
+       'ള്‍' => 'ൾ',
+       'ക്‍' => 'ൿ',
+];
index 52d4caf..4bbbe6f 100644 (file)
        "actionthrottled": "Buet geupeubataih",
        "actionthrottledtext": "Sibagoe saboh seunipat lawan-spam, droeneuh geupeubataih nibak neupeulaku buet nyoe le that gö lam watèë paneuk, ngön droeneuh ka leubèh nibak bataih.\nNeuci lom lam padum minèt.",
        "protectedpagetext": "Laman nyoe ka geupeulindông mangat bèk jeuet geuandam",
-       "viewsourcetext": "Droëneuh  jeuët neu’eu",
+       "viewsourcetext": "Droeneuh jeuet neueu ngön neusalén nè nibak mieng nyoe.",
        "viewyourtext": "Droëneuh meuidzin kalön ngön neucok nè andam droëneuh u laman nyoë",
        "protectedinterface": "Halaman nyoe na tèks muka keu muka keu peukakaih leumiëk ngön geupeulindông mangat bek jeuet jipeureuloh.\nKeu neuk tamah atawa ubah teujeumah keu ban dum wiki, neungui [https://translatewiki.net/ translatewiki.net], proyek lokalisasi MediaWiki.",
        "mycustomcssprotected": "Droëneuh hana hak neuandam halaman CSS nyoe.",
        "missingcommenttext": "Neupasoë beunalah di yup.",
        "summary-preview": "Eu neuringkaih neuandam:",
        "blockedtitle": "Ureueng ngui geutheun",
-       "blockedtext": "'''Nan ureuëng nguy atawa alamat IP Droëneuh  ka geutheun.'''\n\nGeutheun lé $1. Dalèh jih nakeuh ''$2''.\n\n* Geutheun yôh: $8\n* Neutheun maté tanggay bak: $6\n* Nyang geutheun: $7\n\nDroëneuh   jeuët neutanyong bak $1 atawa [[{{MediaWiki:Grouppage-sysop}}|nyang urôh nyang la’én]] keu peugah haba bhah nyoë.\n\nDroëneuh   h’an jeuët neunguy alat 'Kirém surat-e ureuëng nguy nyoë' keucuali ka neupasoë alamat surat-e nyang sah di [[Special:Preferences|Geunalak]] Droëneuh ngön Droëneuh ka geutheun keu nguy nyan.\n\nAlamat IP Droëneuh nakeuh $3, ngön ID neutheun nakeuh $5. Tulông peuseureuta salah saboh atawa ban duwa beurita nyoë bak tiëp teunanyöng nyang neupeugöt.",
+       "blockedtext": "<strong>Nan ureueng ngui atawa alamat IP Droeneuh ka geutheun.</strong>\n\nTeuneuheuen geupeugöt lé $1. \nAlasan nyang geubri nakeuh <em>$2</em>.\n\n* Phôn mula geutheun: $8\n* Maté tanggai teuneuheun: $6\n* Ureueng nyang geutheun: $7\n\nDroeneuh jeuet neutanyöng bak $1 atawa [[{{MediaWiki:Grouppage-sysop}}|ureueng urôih]] nyang la’én bhaih teuneuheun nyoe.\nDroeneuh h`an jeuet neungui alat \"{{int:emailuser}}\" keucuali meunyo alamat surat-e nyang sah na neupasoe bak [[Special:Preferences|Neuatô akun]] ngön Droeneuh hana geutheun keu neungui atra nyan.\nAlamat IP Droeneuh jinoe nakeuh $3, ngön ID teuneuheun nakeuh $5.\nNeutulông pasoe ban dum keutrangan di ateueh lam tiep teunanyöng nyang neupeugöt.",
        "autoblockedtext": "'''Nan ureuëng nguy atawa alamat IP Droëneuh  ka geutheun.'''\n\nGeutheun lé $1. Dalèh jih nakeuh ''$2''.\n\n* Geutheun yôh: $8\n* Neutheun maté tanggay bak: $6\n* Nyang geutheun: $7\n\nDroëneuh   jeuët neutanyong bak $1 atawa [[{{MediaWiki:Grouppage-sysop}}|nyang urôh nyang la’én]] keu peugah haba bhah nyoë.\n\nDroëneuh   h’an jeuët neunguy alat 'Kirém surat-e ureuëng nguy nyoë' keucuali ka neupasoë alamat surat-e nyang sah di [[Special:Preferences|Geunalak]] Droëneuh ngön Droëneuh ka geutheun keu nguy nyan.\n\nAlamat IP Droëneuh nakeuh $3, ngön ID neutheun nakeuh $5. Tulông peuseureuta salah saboh atawa ban duwa beurita nyoë bak tiëp teunanyöng nyang neupeugöt.",
        "blockednoreason": "hana dalèh nyang geubri",
        "whitelistedittext": "Droeneuh suwah $1 keu neuandam ôn.",
        "search-result-category-size": "{{PLURAL:$1|1 anggeeta|$1 anggeeta}} ({{PLURAL:$2|1 aneuk kawan|$2 aneuk kawan}}, {{PLURAL:$3|1 beureukaih|$3 beureukaih}})",
        "search-redirect": "(geupupinah nibak $1)",
        "search-section": "(bideuëng $1)",
+       "search-file-match": "(reumbang ngön asoe beureukaih)",
        "search-suggest": "Kadang meukeusud Droëneuh nakeuh: $1",
        "search-interwiki-caption": "Buët la’én",
        "search-interwiki-default": "Hasé nibak $1:",
        "recentchanges-label-plusminus": "Seunipat miëng geugantoë lé jeumeulah bita nyoë",
        "recentchanges-legend-heading": "<strong>Hareutoë:</strong>",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (eu cit [[Special:NewPages|dapeuta laman barô]])",
-       "rcnotefrom": "Di yup nyoë nakeuh neuubah yôh <strong>$2</strong> (geupeudeuh trôh ‘an <strong>$1</strong> neuubah).",
+       "rcnotefrom": "Di yup nyoe nakeuh {{PLURAL:$5|neuubah}} yôh <strong>$3, $4</strong> (trôk 'an <strong>$1</strong> geupeudeuih).",
        "rclistfrom": "Peudeuih neuubah barô yôh $3 $2 kön",
        "rcshowhideminor": "$1 andam bacut",
        "rcshowhideminor-show": "Peuleumah",
        "rcshowhidebots-show": "Peuleumah",
        "rcshowhidebots-hide": "Peusom",
        "rcshowhideliu": "$1 ureuëng ngui tamöng",
+       "rcshowhideliu-show": "Peudeuih",
        "rcshowhideliu-hide": "Peusom",
        "rcshowhideanons": "$1 ureuëng ngui hana nan",
        "rcshowhideanons-show": "Peuleumah",
        "recentchangeslinked-feed": "Neuubah meuhubông",
        "recentchangeslinked-toolbox": "Neuubah teukaw'èt",
        "recentchangeslinked-title": "Neuubah nyang meukaw'èt ngön $1",
-       "recentchangeslinked-summary": "Neupasoe saboh nan mieng keu neueu neuubah bak mieng nyang mupawôt u atawa nibak mieng nyan. (Keu neueu anggèeta nibak saboh kawan, neupasoe Kawan:Nan kawan). Neuubah bak mieng bak [[Special:Watchlist|dapeuta keunalön]] teutuléh <strong>teubai</strong>.",
+       "recentchangeslinked-summary": "Neupasoe saboh nan mieng keu neueu neuubah bak mieng nyang mupawôt u atawa nibak mieng nyan. (Keu neueu anggèeta nibak saboh kawan, neupasoe {{ns:category}}:Nan kawan). Neuubah bak mieng nyang na bak [[Special:Watchlist|dapeuta keunalön]] teutuléh <strong>teubai</strong>.",
        "recentchangeslinked-page": "Nan miëng:",
        "recentchangeslinked-to": "Peuleumah neuubah nibak laman-laman nyang mupawôt ngön laman nyang geubri",
        "upload": "Peutamöng beureukaih",
        "sp-contributions-search": "Mita soë nyang tuléh",
        "sp-contributions-username": "Alamat IP atawa nan ureuëng ngui:",
        "sp-contributions-toponly": "Peuleumah geunantoe nyang baro mantong",
+       "sp-contributions-newonly": "Peudeuih pumeugöt mieng mantöng",
        "sp-contributions-submit": "Mita",
        "whatlinkshere": "Peunawôt balék",
        "whatlinkshere-title": "Laman nyang mupawôt u $1",
        "tooltip-summary": "Pasoë éhtisa paneuk",
        "interlanguage-link-title": "$1 – $2",
        "simpleantispam-label": "Paréksa anti-spam.\n<strong>BÈK</strong> neupasoë!",
+       "pageinfo-title": "Keutrangan keu \"$1\"",
+       "pageinfo-watchers": "Jumeulah ureueng kalön mieng",
        "pageinfo-toolboxlink": "Keutrangan miëng",
        "previousdiff": "← Bida awai",
        "nextdiff": "Geunantoë lheuëh nyan →",
        "file-info-size": "$1 × $2 piksel, rayek beureukaih: $3, MIME jeunèh: $4",
+       "file-info-size-pages": "$1 × $2 piksel, seunipat beureukaih: $3, jeunèh MIME: $4, $5 {{PLURAL:$5|mieng}}",
        "file-nohires": "Hana resolusi nyang leubèh manyang.",
        "svg-long-desc": "Beureukah SVG, nominal $1 x $2 piksel, rayek beureukah: $3",
        "show-big-image": "Beureukaih aseuli",
        "confirm-unwatch-button": "Ka göt",
        "confirm-unwatch-top": "Sampôh laman nyoë nibak dapeuta keunalön droëneuh?",
        "imgmultipageprev": "← laman sigohlomjih",
+       "imgmultigo": "Jak!",
+       "imgmultigoto": "Jak u mieng $1",
        "autosumm-new": "Geupeugöt laman ngön asoë '$1'",
        "watchlisttools-view": "Peudeuh neuubah meukaw'èt",
        "watchlisttools-edit": "Peudeuh ngön andam dapeuta keunalön",
        "tag-list-wrapper": "([[Special:Tags|{{PLURAL:$1|Tag}}]]: $2)",
        "logentry-delete-delete": "$1 {{GENDER:$2|geusampôh}} miëng $3",
        "logentry-move-move": "$1 {{GENDER:$2|geupinah}} mieng $3 u $4",
+       "logentry-move-move-noredirect": "$1 {{GENDER:$2|geupinah}} mieng $3 u $4 hana geubôh peuninah",
        "logentry-newusers-create": "$1 {{GENDER:$2|geupeugöt}} akun ureuëng ngui",
        "logentry-upload-upload": "$1 {{GENDER:$2|geupasoe}} $3",
        "searchsuggest-search": "Mita {{SITENAME}}",
index 031fa94..0ba8531 100644 (file)
        "recentchanges-legend-plusminus": "(''±১২৩'')",
        "rcfilters-legend-heading": "<strong>সংক্ষিপ্ত ৰূপৰ তালিকা:</strong>",
        "rcfilters-other-review-tools": "আন পুনৰীক্ষণ সঁজুলি",
+       "rcfilters-quickfilters": "সঞ্চিত পৰিস্ৰাৱক",
+       "rcfilters-savedqueries-defaultlabel": "সঞ্চিত পৰিস্ৰাৱক",
        "rcfilters-search-placeholder": "পৰিৱৰ্তনসমূহ ছেকক (ছেকনীৰ নামৰ বাবে মেন্যু বা সন্ধান ব্যৱহাৰ কৰক)",
+       "rcfilters-highlightbutton-title": "ফলাফলসমূহ উজ্জ্বল কৰক",
+       "rcfilters-filter-editsbyself-label": "আপুনি কৰা সালসলনিসমূহ",
+       "rcfilters-filter-editsbyself-description": "আপোনাৰ নিজৰ অৱদানসমূহ।",
+       "rcfilters-filter-editsbyother-label": "আনে কৰা সালসলনিসমূহ",
+       "rcfilters-filter-editsbyother-description": "আপুনি কৰাখিনিৰ বাহিৰে আন সকলো সালসলনি।",
+       "rcfilters-filtergroup-userExpLevel": "সদস্য পঞ্জীয়ন আৰু অভিজ্ঞতা",
+       "rcfilters-filter-user-experience-level-registered-label": "পঞ্জীয়নভুক্ত",
+       "rcfilters-filter-user-experience-level-registered-description": "প্ৰৱেশ কৰা সম্পাদকসকল।",
+       "rcfilters-filter-user-experience-level-unregistered-description": "প্ৰৱেশ নকৰা সম্পাদকসকল।",
+       "rcfilters-filter-user-experience-level-newcomer-label": "নবাগতসকল",
+       "rcfilters-filter-user-experience-level-newcomer-description": "১টাতকৈ কম সম্পাদনা কৰা বা ৪ দিনতকৈ কম সময় সক্ৰিয় থকা পঞ্জীয়নভুক্ত সম্পাদকসকল।",
+       "rcfilters-filter-user-experience-level-learner-label": "ন-শিকাৰুসকল",
+       "rcfilters-filter-user-experience-level-learner-description": "পঞ্জীয়নভুক্ত সম্পাদকসকল যাৰ অভিজ্ঞতাৰ স্তৰ \"নবাগত\" আৰু \"অভিজ্ঞ সদস্য\"ৰ মাজত।",
+       "rcfilters-filter-user-experience-level-experienced-label": "অভিজ্ঞ সদস্যসকল",
+       "rcfilters-filter-user-experience-level-experienced-description": "৫০০তকৈ বেছি সম্পাদনা কৰা আৰু ৩০ দিনতকৈ বেছি সময় সক্ৰিয় থকা পঞ্জীয়নভুক্ত সম্পাদকসকল।",
        "rcfilters-filter-humans-label": "মানুহ (ব'ট নহয়)",
        "rcfilters-filter-pageedits-label": "পৃষ্ঠা সম্পাদনা",
        "rcfilters-filter-newpages-label": "পৃষ্ঠা সৃষ্টি",
index 4d3626b..0916b94 100644 (file)
        "passwordpolicies": "Палітыка пароляў",
        "passwordpolicies-summary": "Гэта сьпіс дзейных палітыкаў пароляў для групаў удзельнікаў, вызначаных у гэтай вікі.",
        "passwordpolicies-group": "Група",
-       "passwordpolicies-policies": "Палітыкі"
+       "passwordpolicies-policies": "Палітыкі",
+       "passwordpolicies-policy-minimalpasswordlength": "Пароль мусіць мець даўжыню найменей $1 {{PLURAL:$1|сымбаль|сымбалі|сымбаляў}}",
+       "passwordpolicies-policy-minimumpasswordlengthtologin": "Пароль мусіць мець даўжыню найменш $1 {{PLURAL:$1|сымбаль|сымбалі|сымбаляў}}, каб уваходзіць у сыстэму"
 }
index 5f2c954..191250f 100644 (file)
        "prefs-watchlist-edits": "নজরতালিকাতে দেখানোর জন্য সর্বাধিক পরিবর্তনের সংখ্যা:",
        "prefs-watchlist-edits-max": "সর্বোচ্চ সংখ্যা: ১০০০",
        "prefs-watchlist-token": "নজরতালিকা টোকেন:",
-       "prefs-watchlist-managetokens": "টোকেন পরিচালনা করুন",
+       "prefs-watchlist-managetokens": "টোকেনসমূহ পরিচালনা করুন",
        "prefs-misc": "বিবিধ",
        "prefs-resetpass": "পাসওয়ার্ড পরিবর্তন",
        "prefs-changeemail": "ইমেইল ঠিকানা পরিবর্তন বা বাতিল করুন",
        "prefs-dateformat": "তারিখ বিন্যাস",
        "prefs-timeoffset": "সময় অফসেট",
        "prefs-advancedediting": "সাধারণ পছন্দগুলি",
+       "prefs-developertools": "উন্নয়নকারীর সরঞ্জাম",
        "prefs-editor": "সম্পাদক",
        "prefs-preview": "প্রাকদর্শন",
        "prefs-advancedrc": "উচ্চতর পছন্দগুলি",
        "right-editcontentmodel": "পাতার তথ্যের ধরন সম্পাদনা করুন",
        "right-editinterface": "ব্যবহারকারী ইন্টারফেস সম্পাদনা",
        "right-editusercss": "অন্য ব্যবহারকারীগণের CSS ফাইল সম্পাদনা",
+       "right-edituserjson": "অন্য ব্যবহারকারীগণের JSON ফাইল সম্পাদনা",
        "right-edituserjs": "অন্য ব্যবহারকারীগণের JS ফাইল সম্পাদনা",
        "right-editmyusercss": "আপনার নিজস্ব ব্যবহারকারী সিএসএস ফাইল সম্পাদনা করুন",
+       "right-editmyuserjson": "আপনার নিজস্ব ব্যবহারকারী JSON ফাইল সম্পাদনা করা",
        "right-editmyuserjs": "আপনার নিজস্ব ব্যবহারকারী জাভাস্ক্রিপ্ট ফাইল সম্পাদনা করুন",
        "right-viewmywatchlist": "আপনার নজরতালিকা দেখুন",
        "right-editmywatchlist": "আপনার নজরতালিকা সম্পাদনা করুন। মনে রাখবেন, এই পরিবর্তনের পরও বিভিন্ন পাতা তালিকায় যুক্ত হয়ে থেতে পারে।",
        "recentchangeslinked-feed": "সম্পর্কিত পরিবর্তন",
        "recentchangeslinked-toolbox": "সম্পর্কিত পরিবর্তন",
        "recentchangeslinked-title": "\"$1\"-এর সাথে সম্পর্কিত পরিবর্তনসমূহ",
-       "recentchangeslinked-summary": "একটি পাতায় বা পাতা থেকে সংযুক্ত পাতাগুলির পরিবর্তন দেখতে একটি পাতার নাম লিখুন। (একটি বিষয়শ্রেণীর সদস্যদের দেখতে, বিষয়শ্রেণী:বিষয়শ্রেণীর নাম লিখুন)। আপনার [[Special:Watchlist|আপনার নজরতালিকায়]] রাখা পাতাগুলি <strong>গাঢ়</strong> করে দেখানো হয়েছে।",
+       "recentchangeslinked-summary": "একটি পাতায় বা পাতা থেকে সংযুক্ত পাতাগুলির পরিবর্তন দেখতে একটি পাতার নাম লিখুন। (একটি বিষয়শ্রেণীর সদস্যদের দেখতে, {{ns:category}}:বিষয়শ্রেণীর নাম লিখুন)। আপনার [[Special:Watchlist|আপনার নজরতালিকায়]] রাখা পাতাগুলি <strong>গাঢ়</strong> করে দেখানো হয়েছে।",
        "recentchangeslinked-page": "পাতার নাম:",
        "recentchangeslinked-to": "প্রদত্ত পাতায় সংযুক্ত আছে এমন পাতাগুলোর পরিবর্তন দেখাও",
        "recentchanges-page-added-to-category": "বিষয়শ্রেণীতে [[:$1]] যোগ করা হয়েছে",
        "undelete-cantcreate": "আপনি এই পাতাটি ফিরিয়ে আনতে পারবেন না কারণ এই নামে কোন পাতা বিদ্যমান নেই ও আপনার এই পাতাটি তৈরি করার অনুমতি নেই।",
        "pagedata-title": "পাতার উপাত্ত",
        "pagedata-not-acceptable": "কোন মিলে যাওয়া বিন্যাস পাওয়া যায় নি। সমর্থিত MIME ধরনগুলি হল: $1",
-       "pagedata-bad-title": "অপ্রযোজ্য শিরোনাম: \"$1\""
+       "pagedata-bad-title": "অপ্রযোজ্য শিরোনাম: \"$1\"",
+       "passwordpolicies-group": "দল",
+       "passwordpolicies-policies": "নীতিসমূহ",
+       "passwordpolicies-policy-minimalpasswordlength": "পাসওয়ার্ড অবশ্যই {{PLURAL:$1|১ অক্ষরের|$1 অক্ষরের}} হতে হবে"
 }
index fb10a20..d4b37fc 100644 (file)
        "histlegend": "Simbologia: (act) = diferència amb la versió actual,\n(prev) = diferència amb la versió anterior, m = modificació menor",
        "history-fieldset-title": "Cerca revisions",
        "history-show-deleted": "Només revisions esborrades",
-       "histfirst": "més antigues",
-       "histlast": "més noves",
+       "histfirst": "les més antigues",
+       "histlast": "les més noves",
        "historysize": "({{PLURAL:$1|1 octet|$1 octets}})",
        "historyempty": "(buit)",
        "history-feed-title": "Historial de revisió",
index 0a9db04..7603a1a 100644 (file)
        "linkstoimage-redirect": "$1 (файлан дӀасахьажорг) $2",
        "duplicatesoffile": "{{PLURAL:$1|Лахара файл ю дубликат|Лахара $1 файлаш ю дубликаташ}} хӀокху файлан ([[Special:FileDuplicateSearch/$2|мадарра]]):",
        "sharedupload": "ХӀара хӀума оцун $1 чура ю иза хила мега лелош кхечу проекташкахь.",
-       "sharedupload-desc-here": "Ð¥Ó\80аÑ\80а Ñ\84айл $1 Ñ\87Ñ\83Ñ\80а Ñ\8e Ð¸ Ð»ÐµÐ»Ð¾ Ð¹Ð¸Ñ\88 Ñ\8e Ð¼Ð°Ñ\81Ñ\81о Ð¿Ñ\80оекÑ\82аÑ\88каÑ\85Ñ\8c.\nЦÑ\83нна Ñ\85аам Ð³Ð°Ð¹Ñ\82ина Ð»Ð°Ñ\85аÑ\85Ñ\8c. [$2 Ð¤Ð°Ð¹Ð» Ð\92икигÑ\83ламехь]",
+       "sharedupload-desc-here": "Ð¥Ó\80аÑ\80а Ñ\84айл $1 Ñ\87Ñ\83Ñ\80а Ñ\8e Ð¸ Ð»ÐµÐ»Ð¾ Ð¹Ð¸Ñ\88 Ñ\8e Ð¼Ð°Ñ\81Ñ\81о Ð¿Ñ\80оекÑ\82аÑ\88каÑ\85Ñ\8c.\nЦÑ\83нна Ñ\85аам Ð³Ð°Ð¹Ñ\82ина Ð»Ð°Ñ\85аÑ\85Ñ\8c. [$2 Ð¤Ð°Ð¹Ð» Ð\92икилаÑ\80мехь]",
        "filepage-nofile": "Иштта цӀе йолуш файл яц.",
        "filepage-nofile-link": "Иштта цӀе йолуш файл яц. Хьа йиш ю и [$1 чуяккха].",
        "uploadnewversion-linktext": "Чуяккха керла верси хӀокху файлан",
index 18fd2f6..f06a2d6 100644 (file)
        "recentchanges-legend-plusminus": "(<em>±123</em>)",
        "recentchanges-submit": "Кăтарт",
        "rcfilters-legend-heading": "<strong>Кĕскетнисем:</strong>",
+       "rcfilters-filterlist-title": "Фильтрсем",
        "rcfilters-filter-user-experience-level-newcomer-label": "Çĕнĕ хутшăнакансем",
+       "rcfilters-filtergroup-automated": "Автоматлă хушнисем",
+       "rcfilters-filter-bots-label": "Бот",
+       "rcfilters-filter-humans-label": "Çын (бот мар)",
+       "rcfilters-filter-minor-label": "Кăштах тӳрлетнисем",
+       "rcfilters-filter-major-label": "Ахаль тӳрлетнисем",
+       "rcfilters-filter-categorization-label": "Категорине улăштарнисем",
+       "rcfilters-filter-lastrevision-label": "Хальхи верси",
+       "rcfilters-filter-previousrevision-label": "Юлашки верси мар",
        "rclistfrom": "$2, $3 тытăнса çĕнĕ улăшăнисене кăтартни",
        "rcshowhideminor": "пĕчĕк тӳрлетнисене $1",
        "rcshowhideminor-show": "кăтартмалла",
index 067c6fc..3112c59 100644 (file)
        "subject-preview": "Forhåndsvisning af emne/overskrift:",
        "previewerrortext": "Der opstod en fejl under forsøget på at lave en forhåndsvisning af dine ændringer.",
        "blockedtitle": "Du eller din IP-adresse er blokeret",
-       "blockedtext": "'''Dit brugernavn eller din IP-adresse er blevet blokeret.'''\n\nBlokeringen er foretaget af $1.\nDen anførte grund er ''$2''.\n\nBlokeringen starter: $8\nBlokeringen udløber: $6\nBlokeringen er rettet mod: $7\n\nDu kan kontakte $1 eller en af de andre [[{{MediaWiki:Grouppage-sysop}}|administratorer]] for at diskutere blokeringen.\nDu kan ikke bruge funktionen 'e-mail til denne bruger' medmindre der er angivet en gyldig e-mailadresse i dine\n[[Special:Preferences|kontoindstillinger]], og du ikke er blevet blokeret fra at bruge den.\n\nDin nuværende IP-adresse er $3, og blokerings-id er #$5.\nAngiv venligst alle ovenstående detaljer ved henvendelser om blokeringen.",
+       "blockedtext": "<strong>Dit brugernavn eller din IP-adresse er blevet blokeret.</strong>\n\nBlokeringen er foretaget af $1.\nDen anførte grund er <em>$2</em>.\n\nBlokeringen starter: $8\nBlokeringen udløber: $6\nBlokeringen er rettet mod: $7\n\nDu kan kontakte $1 eller en af de andre [[{{MediaWiki:Grouppage-sysop}}|administratorer]] for at diskutere blokeringen.\nDu kan ikke bruge funktionen \"{{int:emailuser}}\" medmindre der er angivet en gyldig e-mailadresse i dine [[Special:Preferences|kontoindstillinger]], og du ikke er blevet blokeret fra at bruge den.\n\nDin nuværende IP-adresse er $3, og blokerings-id er #$5.\nAngiv venligst alle ovenstående detaljer ved henvendelser om blokeringen.",
        "autoblockedtext": "Din IP-adresse er blevet blokeret automatisk fordi den blev brugt af en anden bruger som er blevet blokeret af $1.\nBegrundelsen for det er:\n\n:''$2''\n\n* Blokeringsperiodens start: $8\n* Blokeringen udløber: $6\n* Blokeringen er ment for: $7\n\nDu kan kontakte $1 eller en af de andre [[{{MediaWiki:Grouppage-sysop}}|administratorer]] for at diskutere blokeringen.\n\nBemærk at du ikke kan bruge funktionen \"e-mail til denne bruger\" medmindre du har en gyldig e-mailadresse registreret i din [[Special:Preferences|brugerindstilling]], og du ikke er blevet blokeret fra at bruge den.\n\nDin nuværende IP-adresse er $3, og blokerings-id'et er #$5.\nAngiv venligst alle de ovenstående detaljer ved eventuelle henvendelser.",
        "systemblockedtext": "Dit brugernavn eller din IP-adresse er automatisk blokeret af MediaWiki.\nBegrundelsen for det er:\n\n:<em>$2</em>\n\n* Blokeringsperiodens start: $8\n* Blokeringen udløber: $6\n* Blokeringen er ment for: $7\n\nDin nuværende IP-adresse er $3.\nAngiv venligst alle de ovenstående detaljer ved eventuelle henvendelser.",
        "blockednoreason": "ingen begrundelse givet",
        "recentchangeslinked-feed": "Relaterede ændringer",
        "recentchangeslinked-toolbox": "Relaterede ændringer",
        "recentchangeslinked-title": "Ændringer der relaterer til \"$1\"",
-       "recentchangeslinked-summary": "Indtast et sidenavn for at sændringer på sider henvist til eller fra den side. (For at se medlemmer af en kategori indtast Category:Kategorinavn). Ændringer til sider på [[Special:Watchlist|din overvågningsliste]] er vist med <strong>fed</strong> skrift.",
+       "recentchangeslinked-summary": "Indtast et sidenavn for at sændringer på sider henvist til eller fra den side. (For at se medlemmer af en kategori indtast {{ns:category}}:Kategorinavn). Ændringer til sider på [[Special:Watchlist|din overvågningsliste]] er vist med <strong>fed</strong> skrift.",
        "recentchangeslinked-page": "Sidenavn:",
        "recentchangeslinked-to": "Vis ændringer i sider der henviser til den angivne side i stedet",
        "recentchanges-page-added-to-category": "[[:$1]] tilføjet til kategori",
index ca3a000..f07453b 100644 (file)
        "italic_sample": "Italic text",
        "savearticle": "Save page",
        "anonpreviewwarning": "<em>You are not logged in. Saving will record your IP address in this page's edit history.</em>",
-       "blockedtext": "<strong>Your username or IP address has been blocked.</strong>\n\nThe block was made by $1.\nThe reason given is <em>$2</em>.\n\n* Start of block: $8\n* Expiry of block: $6\n* Intended blockee: $7\n\nYou can contact $1 or another [[{{MediaWiki:Grouppage-sysop}}|administrator]] to discuss the block.\nYou cannot use the \"email this user\" feature unless a valid email address is specified in your [[Special:Preferences|account preferences]] and you have not been blocked from using it.\nYour current IP address is $3, and the block ID is #$5.\nPlease include all above details in any queries you make.",
+       "blockedtext": "<strong>Your username or IP address has been blocked.</strong>\n\nThe block was made by $1.\nThe reason given is <em>$2</em>.\n\n* Start of block: $8\n* Expiration of block: $6\n* Intended blockee: $7\n\nYou can contact $1 or another [[{{MediaWiki:Grouppage-sysop}}|administrator]] to discuss the block.\nYou cannot use the \"{{int:emailuser}}\" feature unless a valid e-mail address is specified in your [[Special:Preferences|account preferences]] and you have not been blocked from using it.\nYour current IP address is $3, and the block ID is #$5.\nPlease include all above details in any queries you make.",
        "autoblockedtext": "Your IP address has been automatically blocked because it was used by another user, who was blocked by $1.\nThe reason given is:\n\n:<em>$2</em>\n\n* Start of block: $8\n* Expiry of block: $6\n* Intended blockee: $7\n\nYou may contact $1 or one of the other [[{{MediaWiki:Grouppage-sysop}}|administrators]] to discuss the block.\n\nNote that you may not use the \"email this user\" feature unless you have a valid email address registered in your [[Special:Preferences|user preferences]] and you have not been blocked from using it.\n\nYour current IP address is $3, and the block ID is #$5.\nPlease include all above details in any queries you make.",
        "loginreqlink": "log in",
        "noarticletext": "There is currently no text in this page.\nYou can [[Special:Search/{{PAGENAME}}|search for this page title]] in other pages,\n<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} search the related logs],\nor [{{fullurl:{{FULLPAGENAME}}|action=edit}} create this page]</span>.",
        "boteditletter": "b",
        "rc-change-size-new": "$1 {{PLURAL:$1|byte|bytes}} after change",
        "recentchangeslinked-toolbox": "Related changes",
-       "recentchangeslinked-summary": "This is a list of changes made recently to pages linked from a specified page (or to members of a specified category).\nPages on [[Special:Watchlist|your watchlist]] are <strong>bold</strong>.",
+       "recentchangeslinked-summary": "Enter a page name to see changes on the pages linked to or from that page. (To see members of a category, enter \"{{ns:category}}:Name of category\"). Changes to pages on [[Special:Watchlist|your Watchlist]] are highlighted in <strong>bold</strong>.",
        "upload": "Upload file",
        "license": "Licencing:",
        "license-header": "Licencing",
        "newpages": "New pages",
        "allpagessubmit": "Go",
        "listgrants-summary": "The following is a list of grants with their associated access to user rights. Users can authorise applications to use their account, but with limited permissions based on the grants the user gave to the application. An application acting on behalf of a user cannot actually use rights that the user does not have however.\nThere may be [[{{MediaWiki:Listgrouprights-helppage}}|additional information]] about individual rights.",
+       "emailuser": "E-mail this user",
        "wlshowhidecategorization": "page categorisation",
        "rollbacklink": "rollback",
        "sessionfailure": "There seems to be a problem with your login session;\nthis action has been cancelled as a precaution against session hijacking.\nGo back to the previous page, reload that page and then try again.",
        "tooltip-t-whatlinkshere": "A list of all wiki pages that link here",
        "tooltip-t-recentchangeslinked": "Recent changes in pages linked from this page",
        "tooltip-feed-atom": "Atom feed for this page",
+       "tooltip-t-emailuser": "Send an e-mail to {{GENDER:$1|this user}}",
        "tooltip-t-upload": "Upload files",
        "tooltip-t-specialpages": "A list of all special pages",
        "tooltip-t-print": "Printable version of this page",
index a500fa5..93af0f7 100644 (file)
        "prefs-watchlist-edits": "Número máximo de ediciones a mostrar en la lista de seguimiento:",
        "prefs-watchlist-edits-max": "Cantidad máxima: 1000",
        "prefs-watchlist-token": "Clave de lista de seguimiento:",
-       "prefs-watchlist-managetokens": "Administrar tokens",
+       "prefs-watchlist-managetokens": "Gestionar fichas",
        "prefs-misc": "Varias",
        "prefs-resetpass": "Cambiar contraseña",
        "prefs-changeemail": "Cambiar o eliminar la dirección de correo electrónico",
        "passwordpolicies-policy-passwordcannotmatchusername": "La contraseña no puede ser la misma que el nombre de usuario",
        "passwordpolicies-policy-passwordcannotmatchblacklist": "La contraseña no puede coincidir con la lista de contraseñas específicamente prohibidas",
        "passwordpolicies-policy-maximalpasswordlength": "La contraseña no puede tener más de $1 {{PLURAL:$1|caracter|caracteres}}",
-       "passwordpolicies-policy-passwordcannotbepopular": "La contraseña no puede encontrarse {{PLURAL:$1|en la lista|en las $1 listas}} de contraseñas populares"
+       "passwordpolicies-policy-passwordcannotbepopular": "La contraseña no puede {{PLURAL:$1|ser la contraseña más popular|encontrarse en la lista de $1 contraseñas populares}}"
 }
index 2a01b48..7417273 100644 (file)
        "permanentlink": "Lotura finkoa",
        "permanentlink-revid": "Berrikuspen IDa",
        "permanentlink-submit": "Berrikusketara joan",
-       "dberr-problems": "Barkatu! Webgune honek zailtasun teknikoak jasaten ari da.",
+       "dberr-problems": "Barkatu! Webgune hau zailtasun teknikoak izaten ari da.",
        "dberr-again": "Saiatu pare bat minutu itxaroten edo kargatu ezazu orrialdea berriro.",
        "dberr-info": "($1: Ezin da datu-basera konektatu)",
        "dberr-info-hidden": "(Ezin da konektatu datu-basera)",
index 80ee461..b0d2b27 100644 (file)
        "version-specialpages": "Pages spéciales",
        "version-parserhooks": "Greffons de l'analyseur syntaxique",
        "version-variables": "Variables",
-       "version-editors": "Contributeurs",
+       "version-editors": "Éditeurs",
        "version-antispam": "Prévention du pollupostage",
        "version-other": "Divers",
        "version-mediahandlers": "Manipulateurs de médias",
index 9f97204..1ad9597 100644 (file)
@@ -15,7 +15,8 @@
                        "LNDDYL",
                        "唐吉訶德的侍從",
                        "飞舞回堂前",
-                       "Macofe"
+                       "Macofe",
+                       "Ruthven"
                ]
        },
        "tog-underline": "Lièn-chiap kâ-tái sien:",
index 505e254..d5e6bbc 100644 (file)
        "viewdeletedpage": "הצגה של דפים מחוקים",
        "undeletepagetext": "{{PLURAL:$1|הדף שלהלן נמחק, אך הוא עדיין בארכיון וניתן לשחזר אותו|הדפים שלהלן נמחקו, אך הם עדיין בארכיון וניתן לשחזר אותם}}.\nייתכן שהארכיון ינוקה מעת לעת.",
        "undelete-fieldset-title": "שחזור גרסאות",
-       "undeleteextrahelp": "×\9b×\93×\99 ×\9cש×\97×\96ר ×\90ת ×\94×\99ס×\98×\95ר×\99×\99ת ×\94×\92רס×\90×\95ת ×\94×\9e×\9c×\90×\94 ×©×\9c ×\94×\93×£, ×\90×\9c {{GENDER:|תס×\9e×\9f|תס×\9e× ×\99|תס×\9e× ×\95}} ×©×\95×\9d ×ª×\99×\91ת ×¡×\99×\9e×\95×\9f; ×¤×©×\95×\98 {{GENDER:|×\9c×\97×¥|×\9c×\97צ×\99\9c×\97צ×\95}} ×¢×\9c <strong>{{int:undeletebtn}}</strong>.\n×\9b×\93×\99 ×\9cש×\97×\96ר ×\92רס×\90×\95ת ×\9eס×\95×\99×\9e×\95ת ×\91×\9c×\91×\93, {{GENDER:|ס×\9e×\9f|ס×\9e× ×\99|ס×\9e× ×\95}} ×\90ת ×\94×\92רס×\90×\95ת ×©{{GENDER:|×\91רצ×\95× ×\9a\91רצ×\95× ×\9a\91רצ×\95× ×\9b×\9d}} ×\9cש×\97×\96ר ×\95×\9c×\90×\97ר ×\9e×\9b×\9f {{GENDER:|×\9c×\97×¥|×\9c×\97צ×\99\9c×\97צ×\95}} על <strong>{{int:undeletebtn}}</strong>.",
+       "undeleteextrahelp": "×\9b×\93×\99 ×\9cש×\97×\96ר ×\90ת ×\94×\99ס×\98×\95ר×\99×\99ת ×\94×\92רס×\90×\95ת ×\94×\9e×\9c×\90×\94 ×©×\9c ×\94×\93×£, ×\99ש ×\9c×\94ש×\90×\99ר ×\90ת ×\9b×\9c ×ª×\99×\91×\95ת ×\94ס×\99×\9e×\95×\9f ×¨×\99ק×\95ת ×\95×\9c×\9c×\97×\95×¥ ×¢×\9c <strong>{{int:undeletebtn}}</strong>.\n×\9b×\93×\99 ×\9cש×\97×\96ר ×\92רס×\90×\95ת ×\9eס×\95×\99×\9e×\95ת ×\91×\9c×\91×\93, ×\99ש ×\9cס×\9e×\9f ×\90ת ×\94×\92רס×\90×\95ת ×©×ª×©×\95×\97×\96רנ×\94 ×\95×\9c×\90×\97ר ×\9e×\9b×\9f ×\9c×\9c×\97×\95×¥ על <strong>{{int:undeletebtn}}</strong>.",
        "undeleterevisions": "{{PLURAL:$1|גרסה אחת נמחקה|$1 גרסאות נמחקו}}",
-       "undeletehistory": "×\90×\9d {{GENDER:|תש×\97×\96ר|תש×\97×\96ר×\99|תש×\97×\96ר×\95}} ×\90ת ×\94×\93×£, ×\94×\92רס×\90×\95ת ×\99ש×\95×\97×\96ר×\95 ×\9c×\94×\99ס×\98×\95ר×\99×\99ת ×\94ש×\99× ×\95×\99×\99×\9d ×©×\9c×\95.\n×\90×\9d ×\94×\93×£ ×\94×\96×\94 × ×\9e×\97ק ×\91×¢×\91ר ×\95×\9c×\90×\97ר ×\9e×\9b×\9f × ×\95צר ×\9e×\97×\93ש, ×\94×\92רס×\90×\95ת ×©{{GENDER:|תש×\97×\96ר|תש×\97×\96ר×\99|תש×\97×\96ר×\95}} ×\99×\9e×\95×\96×\92×\95 ×\9c×\94×\99ס×\98×\95ר×\99×\99ת ×\94ש×\99× ×\95×\99×\99×\9d ×©×\9c ×\94×\93×£ ×\95×\99×\95פ×\99×¢×\95 ×\91ת×\95ר ×\94×\92רס×\90×\95ת ×\94×\99שנ×\95ת ×\91×\99×\95תר ×©×\9c×\95.",
+       "undeletehistory": "ש×\97×\96×\95ר ×\94×\93×£ ×\99×\92ר×\95×\9d ×\9c×\9b×\9a ×©×\94×\92רס×\90×\95ת ×©×\9c×\95 ×ª×©×\95×\97×\96רנ×\94 ×\95ת×\95פענ×\94 ×\91×\94×\99ס×\98×\95ר×\99×\99ת ×\94ש×\99× ×\95×\99×\99×\9d ×©×\9c ×\94×\93×£.\n×\90×\9d ×\94×\93×£ ×\94×\96×\94 × ×\9e×\97ק ×\91×¢×\91ר ×\95×\9c×\90×\97ר ×\9e×\9b×\9f × ×\95צר ×\9e×\97×\93ש ×\91×\90×\95ת×\95 ×\94ש×\9d, ×\94×\92רס×\90×\95ת ×\94×\9eש×\95×\97×\96ר×\95ת ×ª×\95פענ×\94 ×\91ת×\95ר ×\94×\92רס×\90×\95ת ×\94×\99שנ×\95ת ×\91×\99×\95תר.",
        "undeleterevdel": "השחזור לא יכול להתבצע אם הגרסה האחרונה של הדף מחוקה או מוסתרת.\nבמקרה כזה, יש לבטל קודם את ההסתרה של הגרסה האחרונה.",
        "undeletehistorynoadmin": "דף זה נמחק.\nהסיבה למחיקה מוצגת בתקציר שלמטה, וגם פרטים על המשתמשים שערכו את הדף לפני שהוא נמחק.\nהטקסט של הגרסאות הללו זמין למפעילי מערכת בלבד.",
        "undelete-revision": "גרסה שנמחקה מהדף $1 (מ־$5, $4) מאת $3:",
-       "undeleterevision-missing": "הגרסה שגויה או חסרה. ייתכן שמדובר בקישור שבור, או שהגרסה שוחזרה או הוסרה מהארכיון.",
+       "undeleterevision-missing": "הגרסה שגויה או חסרה.\nייתכן שמדובר בקישור שבור, או שהגרסה שוחזרה או הוסרה מהארכיון.",
        "undeleterevision-duplicate-revid": "לא ניתן היה לשחזר {{PLURAL:$1|גרסה אחת|$1 גרסאות}}, כיוון ששדה <code>rev_id</code> {{PLURAL:$1|שלה|שלהן}} כבר נמצא בשימוש.",
        "undelete-nodiff": "לא נמצאה גרסה קודמת.",
        "undeletebtn": "שחזור",
        "undeleteinvert": "הפיכת הבחירה",
        "undeletecomment": "סיבה:",
        "cannotundelete": "השחזור (או חלק ממנו) נכשל:\n$1",
-       "undeletedpage": "<strong>×\94×\93×£ $1 ×©×\95×\97×\96ר</strong>\n\nר×\90×\95 ×\90ת [[Special:Log/delete|×\99×\95×\9e×\9f ×\94×\9e×\97×\99ק×\95ת]] ×\9cרש×\99×\9e×\94 ×©×\9c ×\94×\9e×\97×\99ק×\95ת ×\95×\94ש×\97×\96×\95ר×\99×\9d ×©×\91×\95צע×\95 ×\9c×\90×\97ר×\95× ×\94.",
-       "undelete-header": "{{GENDER:|ראה|ראי|ראו}} את [[Special:Log/delete|יומן המחיקות]] לרשימה של דפים שנמחקו לאחרונה.",
+       "undeletedpage": "<strong>×\94×\93×£ $1 ×©×\95×\97×\96ר</strong>\n\nרש×\99×\9eת ×\94×\9e×\97×\99ק×\95ת ×\95×\94ש×\97×\96×\95ר×\99×\9d ×©×\91×\95צע×\95 ×\9c×\90×\97ר×\95× ×\94 ×\9e×\95פ×\99×¢×\94 ×\91[[Special:Log/delete|×\99×\95×\9e×\9f ×\94×\9e×\97×\99ק×\95ת]].",
+       "undelete-header": "רשימת הדפים שנמחקו לאחרונה מופיעה ב[[Special:Log/delete|יומן המחיקות]].",
        "undelete-search-title": "חיפוש דפים שנמחקו",
        "undelete-search-box": "חיפוש דפים שנמחקו",
        "undelete-search-prefix": "הצגת דפים החל מ:",
        "undelete-filename-mismatch": "לא ניתן לשחזר את גרסת הקובץ מ־$1: שם הקובץ לא תואם.",
        "undelete-bad-store-key": "לא ניתן לשחזר את גרסת הקובץ מ־$1: הקובץ היה חסר לפני המחיקה.",
        "undelete-cleanup-error": "שגיאת בעת מחיקת קובץ הארכיון \"$1\" שאינו בשימוש.",
-       "undelete-missing-filearchive": "שחזור קובץ הארכיון שמספרו $1 נכשל כיוון שהוא אינו בבסיס הנתונים. ייתכן שהוא כבר שוחזר.",
+       "undelete-missing-filearchive": "שחזור קובץ הארכיון שמספרו $1 נכשל כיוון שהוא אינו בבסיס הנתונים.\nייתכן שהוא כבר שוחזר.",
        "undelete-error": "שגיאה בשחזור דף",
        "undelete-error-short": "שגיאה בשחזור הקובץ: $1",
        "undelete-error-long": "שגיאות שאירעו בעת שחזור הקובץ:\n\n$1",
-       "undelete-show-file-confirm": "×\94×\90×\9d ×\90ת×\9d ×\91×\98×\95×\97×\99×\9d ×©×\91רצ×\95× ×\9b×\9d לצפות בגרסה המחוקה של הקובץ \"<nowiki>$1</nowiki>\" מ־$3, $2?",
+       "undelete-show-file-confirm": "×\94×\90×\9d ×\91רצ×\95× ×\9a לצפות בגרסה המחוקה של הקובץ \"<nowiki>$1</nowiki>\" מ־$3, $2?",
        "undelete-show-file-submit": "כן",
        "namespace": "מרחב שם:",
        "invert": "ללא מרחב זה",
        "tooltip-invert": "יש לסמן תיבה זו כדי להסתיר שינויים בדפים בתוך מרחב השם שנבחר (ובתוך מרחב השם הצמוד, אם הוא סומן)",
-       "tooltip-whatlinkshere-invert": "יש לסמן תיבה זו כדי להסתיר קישורים מדפים בתוך מרחב השם שנבחר",
+       "tooltip-whatlinkshere-invert": "יש לסמן תיבה זו כדי להסתיר קישורים מדפים בתוך מרחב השם שנבחר.",
        "namespace_association": "מרחב שם צמוד",
        "tooltip-namespace_association": "יש לסמן תיבה זו כדי לכלול גם את מרחב דפי השיחה או דפי הנושא המשויכים למרחב השם הנבחר",
        "blanknamespace": "(ראשי)",
        "sp-contributions-newonly": "הצגת עריכות שהן יצירות של דפים בלבד",
        "sp-contributions-hideminor": "הסתרת עריכות משניות",
        "sp-contributions-submit": "חיפוש",
-       "sp-contributions-outofrange": "לא ניתן להציג תוצאות. טווח ה־IP המבוקש גדול יותר ממגבלת ה־CIDR, שהיא /$1.",
+       "sp-contributions-outofrange": "לא ניתן להציג תוצאות. טווח ה־IP המבוקש גדול יותר ממגבלת ה־CIDR, שהיא <span dir=\"ltr\">/$1</span>.",
        "whatlinkshere": "דפים המקושרים לכאן",
        "whatlinkshere-title": "דפים המקשרים לדף \"$1\"",
        "whatlinkshere-page": "דף:",
index 31cf225..fb955f6 100644 (file)
        "watchlistanontext": "Jelentkezz be a figyelőlistád megtekintéséhez és szerkesztéséhez.",
        "watchnologin": "Nem vagy bejelentkezve",
        "addwatch": "Hozzáadás a figyelőlistához",
-       "addedwatchtext": "A(z) „[[:$1]]” lapot és vitalapját hozzáadtam a [[Special:Watchlist|figyelőlistádhoz]].",
-       "addedwatchtext-talk": "A(z) „[[:$1]]” lapot és a hozzá tartozó tartalmi lapot hozzáadtam a [[Special:Watchlist|figyelőlistádhoz]].",
+       "addedwatchtext": "A(z) „[[:$1]]” lap és vitalapja hozzáadva a [[Special:Watchlist|figyelőlistádhoz]].",
+       "addedwatchtext-talk": "A(z) „[[:$1]]” lap és a hozzá tartozó tartalmi lap hozzáadva a [[Special:Watchlist|figyelőlistádhoz]].",
        "addedwatchtext-short": "Az oldal: \"$1\" hozzá lett adva a figyelőlistádhoz.",
        "removewatch": "Eltávolítás a figyelőlistáról",
-       "removedwatchtext": "A(z) „[[:$1]]” lapot és vitalapját eltávolítottam a [[Special:Watchlist|figyelőlistáról]].",
-       "removedwatchtext-talk": "A(z) „[[:$1]]” lapot és a hozzá tartozó tartalmi lapot eltávolítottam a [[Special:Watchlist|figyelőlistáról]].",
+       "removedwatchtext": "A(z) „[[:$1]]” lap és vitalapja eltávolítva a [[Special:Watchlist|figyelőlistádról]].",
+       "removedwatchtext-talk": "A(z) „[[:$1]]” lap és a hozzá tartozó tartalmi lap eltávolítva a [[Special:Watchlist|figyelőlistádról]].",
        "removedwatchtext-short": "Az oldal: \"$1\" el lett távolítva a figyelőlistádról.",
        "watch": "Lap figyelése",
        "watchthispage": "Lap figyelése",
        "watchlistedit-normal-legend": "Lapok eltávolítása a figyelőlistáról",
        "watchlistedit-normal-explain": "A figyelőlistádra felvett lapok címei alább láthatóak.\nHa el szeretnél távolítani egy címet, pipáld ki a mellette található jelölőnégyzetet, majd kattints „{{int:Watchlistedit-normal-submit}}” gombra.\nLehetőséged van a [[Special:EditWatchlist/raw|figyelőlista nyers változatának]] szerkesztésére is.",
        "watchlistedit-normal-submit": "A kijelöltek eltávolítása",
-       "watchlistedit-normal-done": "{{PLURAL:$1|A következő|A következő $1}} cikket eltávolítottam a figyelőlistádról:",
+       "watchlistedit-normal-done": "{{PLURAL:$1|A következő|A következő $1}} cikket eltávolítottuk a figyelőlistádról:",
        "watchlistedit-raw-title": "A nyers figyelőlista szerkesztése",
        "watchlistedit-raw-legend": "A nyers figyelőlista szerkesztése",
        "watchlistedit-raw-explain": "A figyelőlistádra felvett lapok az alábbi listában találhatók. A lista szerkeszthető;\nminden egyes sor egy figyelt lap címe. Ha kész vagy, kattints a lista alatt található\n„{{int:Watchlistedit-raw-submit}}” feliratú gombra. Használhatod a [[Special:EditWatchlist|hagyományos listaszerkesztőt]] is.",
        "watchlistedit-raw-titles": "A figyelőlistádon található cikkek:",
        "watchlistedit-raw-submit": "Mentés",
        "watchlistedit-raw-done": "A figyelőlistád változtatásait elmentettem.",
-       "watchlistedit-raw-added": "A {{PLURAL:$1|következő|következő $1}} cikket hozzáadtam a figyelőlistádhoz:",
-       "watchlistedit-raw-removed": "A {{PLURAL:$1|következő|következő $1}} cikket eltávolítottam a figyelőlistádról:",
+       "watchlistedit-raw-added": "A {{PLURAL:$1|következő|következő $1}} cikket hozzáadtuk a figyelőlistádhoz:",
+       "watchlistedit-raw-removed": "A {{PLURAL:$1|következő|következő $1}} cikket eltávolítottuk a figyelőlistádról:",
        "watchlistedit-clear-title": "A figyelőlista kiürítése",
        "watchlistedit-clear-legend": "Figyelőlista kiürítése",
        "watchlistedit-clear-explain": "Minden cím el lesz távolítva a figyelőlistádról",
index 695f247..3ebb9f5 100644 (file)
        "expansion-depth-exceeded-category": "Paginas in que le profunditate de expansion excede le limite",
        "expansion-depth-exceeded-category-desc": "Le pagina excede le profunditate de expansion maxime.",
        "expansion-depth-exceeded-warning": "Le profunditate de expansion in iste pagina excede le limite",
-       "parser-unstrip-loop-warning": "Bucla de \"unstrip\" detegite",
-       "unstrip-depth-warning": "Limite de recursion de \"unstrip\" excedite ($1)",
+       "parser-unstrip-loop-warning": "Bucla detegite in le function \"unstrip\"",
+       "unstrip-depth-warning": "Limite de profunditate de \"unstrip\" excedite ($1)",
+       "unstrip-depth-category": "Paginas con recursion excessive de \"unstrip\"",
+       "unstrip-size-warning": "Limite de dimension de \"unstrip\" excedite ($1)",
+       "unstrip-size-category": "Paginas con dimension excessive de \"unstrip\"",
        "converter-manual-rule-error": "Error detegite in le regula manual de conversion de lingua",
        "undo-success": "Le modification pote esser disfacite.\nPer favor controla le comparation infra pro verificar que tu vole facer isto, e postea salveguarda le modificationes infra pro assi disfacer le modification.",
        "undo-failure": "Le modification non poteva esser annullate a causa de conflicto con modificationes intermedie.",
        "prefs-watchlist-edits": "Numero maxime de modificationes a monstrar in le observatorio:",
        "prefs-watchlist-edits-max": "Numero maxime: 1000",
        "prefs-watchlist-token": "Indicio pro le observatorio:",
-       "prefs-watchlist-managetokens": "Gerer indicios",
+       "prefs-watchlist-managetokens": "Gerer claves",
        "prefs-misc": "Misc",
        "prefs-resetpass": "Cambiar contrasigno",
        "prefs-changeemail": "Cambiar o remover adresse de e-mail",
        "stub-threshold-disabled": "Disactivate",
        "recentchangesdays": "Numero de dies a monstrar in modificationes recente:",
        "recentchangesdays-max": "(non plus de $1 {{PLURAL:$1|die|dies}})",
-       "recentchangescount": "Numero de modificationes a monstrar per predefinition:",
-       "prefs-help-recentchangescount": "Isto include modificationes recente, historias de paginas, e registros.",
+       "recentchangescount": "Numero predefinite de modificationes a monstrar in le lista de modificationes recente, in le historias de paginas e in le registros:",
+       "prefs-help-recentchangescount": "Numero maxime: 1000",
        "prefs-help-watchlist-token2": "Isto es le clave secrete pro le syndication web de tu observatorio.\nOmne persona qui lo cognosce pote leger tu observatorio, dunque, non divide lo.\nIn caso de necessitate, [[Special:ResetTokens|clicca hic pro reinitialisar lo]].",
        "prefs-help-tokenmanagement": "Tu pote vider e reinitialisar le clave secrete pro tu conto que pote acceder al aggregator Web de tu observatorio. Tote persona que cognosce le clave potera leger tu observatorio, dunque non divulga lo.",
        "savedprefs": "Tu preferentias ha essite confirmate.",
        "default": "predefinite",
        "prefs-files": "Files",
        "prefs-custom-css": "CSS personalisate",
+       "prefs-custom-json": "JSON personalisate",
        "prefs-custom-js": "JS personalisate",
-       "prefs-common-config": "CSS/JS commun a tote le apparentias:",
+       "prefs-common-config": "CSS/JSON/JavaScript commun a tote le apparentias:",
        "prefs-reset-intro": "Iste pagina es pro reinitialisar tu preferentias al valores predefinite del sito.\nLe operation non pote esser disfacite.",
        "prefs-emailconfirm-label": "Confirmation del e-mail:",
        "youremail": "E-mail:",
        "prefs-dateformat": "Formato de data",
        "prefs-timeoffset": "Differentia de tempore",
        "prefs-advancedediting": "Optiones general",
+       "prefs-developertools": "Instrumentos pro disveloppatores",
        "prefs-editor": "Editor",
        "prefs-preview": "Previsualisation",
        "prefs-advancedrc": "Optiones avantiate",
        "right-editcontentmodel": "Modificar le modello de contento de un pagina",
        "right-editinterface": "Modificar le interfacie de usator",
        "right-editusercss": "Modificar le files CSS de altere usatores",
+       "right-edituserjson": "Modificar le files JSON de altere usatores",
        "right-edituserjs": "Modificar le files JS de altere usatores",
        "right-editmyusercss": "Modificar le proprie files CSS de usator",
-       "right-editmyuserjs": "Modificar le proprie files JavaScript de usator",
+       "right-editmyuserjson": "Modificar le files JSON del proprie usator",
+       "right-editmyuserjs": "Modificar le files JavaScript del proprie usator",
        "right-viewmywatchlist": "Vider le proprie observatorio",
        "right-editmywatchlist": "Modificar le proprie observatorio. Remarca que alcun actiones totevia adde paginas mesmo sin iste derecto.",
        "right-viewmyprivateinfo": "Vider le proprie datos private (p.ex. adresse de e-mail, nomine real)",
        "grant-createaccount": "Crear contos",
        "grant-createeditmovepage": "Crear, modificar e renominar paginas",
        "grant-delete": "Deler paginas, versiones e entratas de registro",
-       "grant-editinterface": "Modificar le spatio de nomines MediaWiki e le CSS/JavaScript de usatores",
-       "grant-editmycssjs": "Modificar le CSS/JavaScript del proprie usator",
+       "grant-editinterface": "Modificar le spatio de nomines MediaWiki e le CSS/JSON/JavaScript de usatores",
+       "grant-editmycssjs": "Modificar le CSS/JSON/JavaScript del proprie usator",
        "grant-editmyoptions": "Modificar tu preferentias de usator",
        "grant-editmywatchlist": "Modificar tu observatorio",
        "grant-editpage": "Modificar paginas existente",
        "rcfilters-filter-humans-label": "Persona (non robot)",
        "rcfilters-filter-humans-description": "Modificationes facite per esseres human.",
        "rcfilters-filtergroup-reviewstatus": "Stato de revision",
+       "rcfilters-filter-reviewstatus-unpatrolled-description": "Modificationes non marcate como patruliate, manual- o automaticamente.",
        "rcfilters-filter-reviewstatus-unpatrolled-label": "Non patruliate",
+       "rcfilters-filter-reviewstatus-manual-description": "Modificationes manualmente marcate como patruliate.",
+       "rcfilters-filter-reviewstatus-manual-label": "Patruliate manualmente",
+       "rcfilters-filter-reviewstatus-auto-description": "Modificationes per usatores avantiate cuje travalio se marca automaticamente como patruliate.",
+       "rcfilters-filter-reviewstatus-auto-label": "Autopatruliate",
        "rcfilters-filtergroup-significance": "Importantia",
        "rcfilters-filter-minor-label": "Modificationes minor",
        "rcfilters-filter-minor-description": "Modificationes que le autor ha marcate como minor.",
        "deadendpages": "Paginas sin exito",
        "deadendpagestext": "Le sequente paginas non ha ligamines a altere paginas in {{SITENAME}}.",
        "protectedpages": "Paginas protegite",
+       "protectedpages-filters": "Filtros:",
        "protectedpages-indef": "Solmente protectiones infinite",
        "protectedpages-summary": "Iste pagina lista paginas existente que es actualmente protegite. Pro un lista de titulos protegite contra creation, vide [[{{#special:ProtectedTitles}}|{{int:protectedtitles}}]].",
        "protectedpages-cascade": "Protectiones in cascada solmente",
        "protectedtitles-submit": "Monstrar titulos",
        "listusers": "Lista de usatores",
        "listusers-editsonly": "Monstrar solmente usatores con modificationes",
+       "listusers-temporarygroupsonly": "Monstrar solmente usatores in gruppos temporari",
        "listusers-creationsort": "Ordinar per data de creation",
        "listusers-desc": "Ordinar in senso descendente",
        "usereditcount": "$1 {{PLURAL:$1|modification|modificationes}}",
        "apisandbox-dynamic-parameters-add-label": "Adder parametro:",
        "apisandbox-dynamic-parameters-add-placeholder": "Nomine del parametro",
        "apisandbox-dynamic-error-exists": "Un parametro con le nomine \"$1\" jam existe.",
+       "apisandbox-templated-parameter-reason": "Iste [[Special:ApiHelp/main#main/templatedparams|parametro de patrono]] es offerite a base del {{PLURAL:$1|valor|valores}} of $2.",
        "apisandbox-deprecated-parameters": "Parametros obsolescente",
        "apisandbox-fetch-token": "Auto-reimpler le indicio",
+       "apisandbox-add-multi": "Adder",
        "apisandbox-submit-invalid-fields-title": "Alcun campos non es valide",
        "apisandbox-submit-invalid-fields-message": "Per favor, corrige le campos marcate e reproba.",
        "apisandbox-results": "Resultatos",
        "whatlinkshere": "Paginas ligate a iste",
        "whatlinkshere-title": "Paginas con ligamines verso $1",
        "whatlinkshere-page": "Pagina:",
-       "linkshere-2": "Le sequente paginas contine ligamines a '''$1''':",
-       "nolinkshere-2": "Nulle pagina contine un ligamine verso '''$1'''.",
-       "nolinkshere-ns-2": "Nulle pagina liga a '''$1''' in le spatio de nomines seligite.",
+       "linkshere-2": "Le sequente paginas contine ligamines a <strong>$1</strong>:",
+       "nolinkshere-2": "Nulle pagina contine un ligamine verso <strong>$1</strong>.",
+       "nolinkshere-ns-2": "Nulle pagina liga a <strong>$1</strong>  in le spatio de nomines seligite.",
        "isredirect": "pagina de redirection",
        "istemplate": "transclusion",
        "isimage": "ligamine al file",
        "fix-double-redirects": "Actualisar tote le redirectiones que puncta verso le titulo original",
        "move-leave-redirect": "Lassar un redirection",
        "protectedpagemovewarning": "'''Attention:''' Iste pagina ha essite protegite de sorta que solmente usatores con privilegios de administrator pote renominar lo. Le ultime entrata del registro es fornite hic infra pro referentia:",
-       "semiprotectedpagemovewarning": "'''Nota:''' Iste pagina ha essite protegite de sorta que solmente usatores registrate pote renominar lo. Le ultime entrata del registro es fornite hic infra pro referentia:",
+       "semiprotectedpagemovewarning": "<strong>Nota:</strong> Iste pagina ha essite protegite de sorta que solmente usatores autoconfirmate pote renominar lo. Le ultime entrata del registro es fornite hic infra pro referentia:",
        "move-over-sharedrepo": "[[:$1]] jam existe in un repositorio commun. Si le file es renominate a iste titulo, illo supplantara le file commun.",
        "file-exists-sharedrepo": "Le nomine de file seligite es ja in uso in un repositorio partite.\nPer favor selige un altere nomine.",
        "export": "Exportar paginas",
        "thumbnail_dest_directory": "Impossibile crear directorio de destination",
        "thumbnail_image-type": "typo de imagine non supportate",
        "thumbnail_gd-library": "le configuration del bibliotheca GD es incomplete: manca le function $1",
+       "thumbnail_image-size-zero": "Le dimension del file de imagine pare esser zero.",
        "thumbnail_image-missing": "le file pare mancar: $1",
        "thumbnail_image-failure-limit": "Il ha habite recentemente troppo de tentativas fallite ($1 o plus) de generar iste miniatura. Per favor reproba plus tarde.",
        "import": "Importar paginas",
        "interlanguage-link-title": "$1 (in $2)",
        "common.css": "/* Le CSS placiate hic se applicara a tote le stilos */",
        "print.css": "/* Le CSS placiate hic influentiara le apparentia del paginas imprimite */",
+       "common.json": "/* Omne JSON hic essera cargate pro tote le usatores a cata cargamento de pagina. */",
        "common.js": "/* Omne JavaScript hic se executara pro tote le usatores a cata cargamento de pagina. */",
        "anonymous": "{{PLURAL:$1|Usator|Usatores}} anonyme de {{SITENAME}}",
        "siteuser": "Usator $1 de {{SITENAME}}",
        "watchlistedit-clear-titles": "Titulos:",
        "watchlistedit-clear-submit": "Rader le observatorio (isto es permanente!)",
        "watchlistedit-clear-done": "Tu observatorio ha essite radite.",
+       "watchlistedit-clear-jobqueue": "Tu observatorio es in curso de vacuation. Isto pote prender un certe tempore.",
        "watchlistedit-clear-removed": "{{PLURAL:$1|1 titulo|$1 titulos}} ha essite removite:",
        "watchlistedit-too-many": "Il ha troppo de paginas pro monstrar los hic.",
        "watchlisttools-clear": "Rader le observatorio",
        "version-specialpages": "Paginas special",
        "version-parserhooks": "Uncinos del analysator syntactic",
        "version-variables": "Variabiles",
+       "version-editors": "Editores",
        "version-antispam": "Prevention de spam",
        "version-other": "Altere",
        "version-mediahandlers": "Executores de media",
        "limitreport-templateargumentsize-value": "$1/$2 {{PLURAL:$2|byte|bytes}}",
        "limitreport-expansiondepth": "Maxime profunditate de expansion",
        "limitreport-expensivefunctioncount": "Numero de functiones analysator costose",
+       "limitreport-unstrip-depth": "Profunditate de recursion de \"unstrip\"",
+       "limitreport-unstrip-size": "Dimension de \"unstrip\" post expansion",
+       "limitreport-unstrip-size-value": "$1/$2 {{PLURAL:$2|byte|bytes}}",
        "expandtemplates": "Expander patronos",
        "expand_templates_intro": "Iste pagina special prende wikitexto e expande recursivemente tote le patronos in illo.\nIllo expande etiam le functiones del analysator syntactic como\n<code><nowiki>{{</nowiki>#language:…}}</code>, e variabiles como\n<code><nowiki>{{</nowiki>CURRENTDAY}}</code>.\nDe facto, illo expande quasi toto inter accolladas duple.",
        "expand_templates_title": "Titulo de contexto, pro {{FULLPAGENAME}} etc.:",
        "unlinkaccounts-success": "Le conto ha essite disligate.",
        "authenticationdatachange-ignored": "Le cambiamento del datos de authentication non ha succedite. Pote esser que nulle fornitor ha essite configurate?",
        "userjsispublic": "Nota ben: Subpaginas JavaScript non debe continer datos confidential perque altere usatores pote vider los.",
+       "userjsonispublic": "Nota ben: Subpaginas JSON non debe continer datos confidential perque altere usatores pote vider los.",
        "usercssispublic": "Nota ben: Subpaginas CSS non debe continer datos confidential perque altere usatores pote vider los.",
        "restrictionsfield-badip": "Adresse o intervallo IP non valide: $1",
        "restrictionsfield-label": "Intervallos IP permittite:",
        "pagedata-title": "Datos de pagina",
        "pagedata-text": "Iste pagina forni un interfacie de datos a paginas. Forni le titulo del pagina in le URL, usante le syntaxe de subpaginas.\n* Le negotiation de contento depende del capite \"Accept\" de tu cliente. Isto significa que le datos del pagina essera fornite in le formato que tu cliente prefere.",
        "pagedata-not-acceptable": "Nulle formato correspondente trovate. Typos MIME supportate: $1",
-       "pagedata-bad-title": "Titulo invalide: $1."
+       "pagedata-bad-title": "Titulo invalide: $1.",
+       "unregistered-user-config": "Pro motivos de securitate, subpaginas de usator con JavaScript, CSS e JSON non pote esser cargate pro usatores non registrate.",
+       "passwordpolicies": "Politicas de contrasigno",
+       "passwordpolicies-summary": "Isto es un lista de politicas de contrasigno in vigor pro le gruppos de usatores definite in iste wiki.",
+       "passwordpolicies-group": "Gruppo",
+       "passwordpolicies-policies": "Politicas",
+       "passwordpolicies-policy-minimalpasswordlength": "Le contrasigno debe continer al minus $1 {{PLURAL:$1|character|characteres}}",
+       "passwordpolicies-policy-minimumpasswordlengthtologin": "Le contrasigno debe continer al minus $1 {{PLURAL:$1|character|characteres}} pro poter aperir session",
+       "passwordpolicies-policy-passwordcannotmatchusername": "Le contrasigno non pote esser identic al nomine de usator",
+       "passwordpolicies-policy-passwordcannotmatchblacklist": "Le contrasigno non pote corresponder a contrasignos in le lista nigre",
+       "passwordpolicies-policy-maximalpasswordlength": "Le contrasigno debe continer minus de $1 {{PLURAL:$1|character|characteres}}",
+       "passwordpolicies-policy-passwordcannotbepopular": "Le contrasigno non pote esser {{PLURAL:$1|le contrasigno le plus popular|in le lista de $1 contrasignos popular}}"
 }
index cdd4758..65c0bcf 100644 (file)
        "print": "Зарба тоха",
        "view": "Хьажар",
        "view-foreign": "Укх $1 сайта чу хьажа",
-       "edit": "Ð\9dийÑ\81де",
+       "edit": "Тоаде",
        "edit-local": "Хувца локальни йоазонца сурт оттадар",
        "create": "Хьакхолла",
        "create-local": "ТIатоха локальни йоазонца сурт оттадар",
        "newpage": "Керда оагӀув",
        "talkpagelinktext": "дувца оттадар",
        "specialpage": "ГIулакха оагӀув",
-       "personaltools": "Ð\94оакÑ\8aаÑ\88Ñ\85оÑ\87Ñ\83н Ð³Ó\80иÑ\80Ñ\81аш",
-       "talk": "Ð\94Ñ\83вÑ\86а Ð¾Ñ\82Ñ\82адар",
+       "personaltools": "Ð\94оакÑ\8aаÑ\88Ñ\85оÑ\87Ñ\83н ÐºÐµÑ\87алаш",
+       "talk": "ЮвÑ\86ар",
        "views": "Хьажараш",
-       "toolbox": "Ð\93Ó\80иÑ\80Ñ\81аш",
+       "toolbox": "Ð\9aеÑ\87алаш",
        "imagepage": "Файла оагIон бIаргтоха",
        "mediawikipage": "Хьахьокха хоам бара оагIув",
        "templatepage": "Лера оагIон бIаргтоха",
        "viewhelppage": "Новкъостал эцар",
-       "categorypage": "Ð\9aаÑ\82егоÑ\80ен Ð¾Ð°Ð³Iон бIаргтоха",
-       "viewtalkpage": "Дувца оттадара бIаргтоха",
+       "categorypage": "Ð\9eагÓ\80аÑ\82а Ð¾Ð°Ð³Iонга бIаргтоха",
+       "viewtalkpage": "Дувцара оагIонга бIаргтоха",
        "otherlanguages": "Кхыча меттаех",
        "redirectedfrom": "($1 яха оагIув дIа-хьа хьожаяьй укхаза)",
        "redirectpagesub": "ДIа-хьа хьожавара оагIув",
        "newmessageslinkplural": "{{PLURAL:$1|керда хоам}}",
        "newmessagesdifflinkplural": "{{PLURAL:$1|тӀехьара хувцам|999=тӀехьара хувцамаш}}",
        "youhavenewmessagesmulti": "Хьога кхаьчад керда хоамаш $1 чу",
-       "editsection": "нийсде",
+       "editsection": "тоае",
        "editold": "хувца",
        "viewsourceold": "Хьажа дIадолалу ко́дага",
        "editlink": "хувца",
        "nstab-special": "ГIулакха оагӀув",
        "nstab-project": "Проектах лаьца",
        "nstab-image": "Файл",
-       "nstab-mediawiki": "Хоамбар",
+       "nstab-mediawiki": "Хоам",
        "nstab-template": "Ло",
        "nstab-help": "Новкъостал",
        "nstab-category": "ОагӀат",
        "cannotdelete-title": "ДIаяккха йиш яц «$1» яха оагIув",
        "badtitle": "Мегаш йоаца цӀи",
        "badtitletext": "Езаш йола оагӀон цӀи нийса яц, яьсса я, е харцахь йоалаяй меттий юкъера цIи е интервики цӀи. Иштта, цӀера юкъе оттаде мегаш доаца хьаракаш нийсаденна хила мегаш да.",
-       "viewsource": "Хьажар",
+       "viewsource": "Хьажа",
        "viewsource-title": "$1 яхача оагӏон чухьнахьарча текстага хьажар",
        "actionthrottled": "Сухала доазув дар",
        "protectedpagetext": "Ер оагIув лораяь я цу тIа хувцамаш дергдоацаш.",
        "viewsourcetext": "Укх оагIон чухьнахьарча текстах бIаргатоха а, цунах кеп яьккха а, йиш я хьа.",
        "virus-unknownscanner": "йовзанза антивирус:",
-       "welcomeuser": "Ð\9cаÑ\8cÑ\80Ñ\88а Ð²Ð¾Ð°Ð³Iалва, Ð´Ð¾Ð°ÐºÑ\8aаÑ\88Ñ\85о $1!",
+       "welcomeuser": "Марша воагIалва, доакъашхо $1!",
        "yourname": "Дагара йоазон цIи:",
        "userlogin-yourname": "Доакъашхочун цӀи",
        "userlogin-yourname-ph": "Iочуязъе хьай дагара йоазон цӀи",
        "createacct-yourpasswordagain": "Бакъйе пароль",
        "createacct-yourpasswordagain-ph": "Кхы цхьаькхаза Ӏочуязъе пароль",
        "userlogin-remembermypassword": "Ражача чувиса",
-       "yourdomainname": "Ð¥Ñ\8cа Ð½Ð°Ð½Ð°-Ñ\86Iа:",
+       "yourdomainname": "Ð¥Ñ\8cа Ð´Ð¾Ð¼ÐµÐ½:",
        "login": "Чувала/яла",
        "nav-login-createaccount": "Шоаш довзийтар / Дагара йоазув кхоллар",
        "logout": "Аравала/яла",
        "createacct-benefit-body3": "ТӀехьарча хана хинна {{PLURAL:$1|доакъашхо|доакъашхой}}",
        "badretype": "Оаша Iочуяьздаь къайладIоагIий цIераш цхьантара яц.",
        "loginerror": "Доакъашхо вовзара гIалат",
-       "mailmypassword": "Ð\9aÑ\8aайладIоагIа тIеракхоссар",
-       "mailerror": "Каьхат дIадохьиййташ гӀалат хилар: $1",
-       "emailconfirmlink": "Бакъде хьа электронни пошта адрес",
+       "mailmypassword": "Ð\9fаÑ\80олÑ\8c тIеракхоссар",
+       "mailerror": "Каьхат дIадохьийтача хана гӀалат хилар: $1",
+       "emailconfirmlink": "Бакъде хьай электронни пошта цIай",
        "loginlanguagelabel": "Мотт: $1",
        "pt-login": "Чувала/яла",
        "pt-login-button": "Чувала/яла",
        "botpasswords-label-create": "Хьакхолла",
        "botpasswords-label-update": "Кердадаккха",
        "botpasswords-label-cancel": "Эшац",
-       "botpasswords-label-delete": "ДIадаккха",
+       "botpasswords-label-delete": "ДIаяккха",
        "botpasswords-label-resetpassword": "Пароль тIеракхоссар",
        "resetpass-submit-loggedin": "КъайладIоагӀа дӀахувца",
        "resetpass-submit-cancel": "Эшац",
        "previousrevision": "← XьалхайоагIа",
        "nextrevision": "ТIехьайоагIа →",
        "currentrevisionlink": "ХIанзара верси",
-       "cur": "хӀанза.",
+       "cur": "карара",
        "next": "тӀехь.",
-       "last": "хьалха.",
+       "last": "хьалхара",
        "page_first": "цхьоаллагIа",
        "page_last": "тӀехьара",
        "histlegend": "Эрший хоржам: хьабелгалъе шун вIаши йиста безам бола оагIон эршаш, тIаккха тоIае '''{{int:compare-submit}}'''.<br />\nКхетавар: '''({{int:cur}})''' — карарча эршаи хержача эршаи юкъе йола башхалонаш; '''({{int:last}})''' — хьалха йоагIача эршаи хержача эршаи юкъе йола башхалонаш; '''{{int:minoreditletter}}''' — зIамига хувцамаш.",
        "diff-multi-otherusers": "(Укх {{PLURAL:$2|цхьан доакъашхочун|$2 доакъашхой}} \n{{PLURAL:$1|юккъера верси гайтаяц|юккъера версеш гайтаяц}})",
        "searchresults": "Лахар чакхдоалаш корадаьр",
        "searchresults-title": "«$1» лахар",
-       "notextmatches": "Ð\9eагIонай Ñ\82екÑ\81Ñ\82аÑ\88Ñ\82а Ñ\8eкÑ\8aе цхьатара хилар дац",
+       "notextmatches": "Ð\9eагIоний Ñ\82екÑ\81Ñ\82аÑ\88Ñ\82а Ñ\87Ñ\83 цхьатара хилар дац",
        "prevn": "{{PLURAL:$1|1=хьалхайогIар|хьалхайогIараш}} $1",
        "nextn": "{{PLURAL:$1|1=тIехьайоагIар|тIехьайоагIараш}} $1",
        "prevn-title": "{{PLURAL:$1|ХьалхадоагIа $1 дIаяздар}}",
        "powersearch-toggleall": "Деррига",
        "powersearch-togglenone": "Цхьаккха",
        "powersearch-remember": "Дагалáца хержар кхы тӀехьагӀа лохача хана накъадаргдолаш",
-       "preferences": "Ð\93IиÑ\80Ñ\81 Ñ\82оаÑ\8fÑ\80аш",
+       "preferences": "Ð\9eÑ\82Ñ\82амаш",
        "mypreferences": "Оттамаш",
        "prefs-skin": "ТIера кийчдара тема",
        "skin-preview": "Хьалххе бIаргтохар",
        "prefs-user-pages": "Доакъашхочун оагIонаш",
-       "prefs-personal": "Доакъашхочун дараш",
-       "prefs-rc": "Ð\9aеÑ\80да Ð½Ð¸Ð¹Ñ\81даÑ\80аÑ\88",
+       "prefs-personal": "Доакъашхочун хьакъехьа",
+       "prefs-rc": "Ð\94Ñ\83кÑ\85а Ñ\85а Ð¹Ð¾Ð°Ñ\86Ñ\86аÑ\88 Ñ\82оадаÑ\8cÑ\80",
        "prefs-watchlist": "Зéма хьаязъяьр",
        "prefs-watchlist-days": "Дéной дукхал:",
        "prefs-resetpass": "Хувца къайладIоагIа",
        "prefs-searchoptions": "Лахар",
        "prefs-namespaces": "ЦIерий моттигаш",
        "prefs-files": "Файлаш",
-       "youremail": "ЭлекÑ\82Ñ\80онни Ð¿Ð¾Ñ\87Ñ\82а:",
+       "youremail": "ЭлекÑ\82Ñ\80онни Ð¿Ð¾Ñ\88Ñ\82:",
        "username": "{{GENDER:$1|Доакъашхочун цӀи}}:",
        "yourrealname": "Бокъонца йола цIи:",
        "yourlanguage": "Мотт:",
        "userrights-unchangeable-col": "Хьа хувца йиш йоаца тоабаш",
        "group": "Тоаба:",
        "group-user": "Доакъашхой",
+       "group-autoconfirmed": "АвтохьатӀаийца доакъашхой",
        "group-bot": "Бóташ",
        "group-sysop": "Администратораш",
+       "group-bureaucrat": "Бюрократаш",
        "group-all": "(деррига)",
        "group-user-member": "{{GENDER:$1|доакъашхо}}",
+       "group-autoconfirmed-member": "{{GENDER:$1|автохьатӀаийца доакъашхо}}",
        "group-bot-member": "{{GENDER:$1|бот}}",
        "group-sysop-member": "{{GENDER:$1|администратор}}",
        "grouppage-user": "{{ns:project}}:Доакъашхой",
+       "grouppage-autoconfirmed": "{{ns:project}}:АвтохьатӀаийца доакъашхой",
        "grouppage-bot": "{{ns:project}}:Боташ",
        "grouppage-sysop": "{{ns:project}}:Администратораш",
+       "grouppage-bureaucrat": "{{ns:project}}:Бюрократаш",
        "right-read": "оагӀонашка хьажар",
        "right-edit": "оагӀонаш нийсъяр",
        "right-createtalk": "дувца оттадара оагӀонаш кхоллар",
        "recentchanges-label-plusminus": "байташкахь боарам хувцар",
        "recentchanges-legend-heading": "<strong>Легенда:&nbsp;</strong>",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (хьажа иштта [[Special:NewPages|керда оагIонашка]])",
+       "rcfilters-activefilters": "Хьалотаяь фильтраш",
+       "rcfilters-advancedfilters": "Шеръяь фильтраш",
+       "rcfilters-quickfilters": "Ӏалашъяь фильтраш",
+       "rcfilters-quickfilters-placeholder-title": "Ӏалашъяь фильтраш хIанзехьа яц",
+       "rcfilters-quickfilters-placeholder-description": "Фильтра оттамаш дIаяздергдолаши тIехьагIа царех юха а пайда эцаргболаши, лохегIа «Активни фильтр» яздаьча моттиге юкъеехкарг белгалъеча хьарака IотIатоIае.",
+       "rcfilters-savedqueries-defaultlabel": "Ӏалашъяь фильтраш",
+       "rcfilters-savedqueries-rename": "ЦIи хувца",
+       "rcfilters-savedqueries-setdefault": "Ше хиннача тайпара дIаоттаде",
+       "rcfilters-savedqueries-unsetdefault": "Ше хиннача тайпах яр дIаяккха",
+       "rcfilters-savedqueries-remove": "ДIаяккха",
+       "rcfilters-savedqueries-new-name-label": "ЦIи",
+       "rcfilters-filter-bots-label": "Бот",
+       "rcfilters-filter-bots-description": "Авто-кечалашца даь тоадар.",
+       "rcfilters-filter-humans-label": "Саг ва (бот яц)",
+       "rcfilters-filter-pageedits-label": "ОагӀона тоадаьраш",
+       "rcfilters-filter-newpages-label": "JагӀонаш кхоллар",
+       "rcfilters-filter-newpages-description": "Керда оагӀонаш кхолла аьнна даь тоадар.",
+       "rcfilters-liveupdates-button": "Ше-шегIа кердадахийта",
+       "rcfilters-liveupdates-button-title-on": "ДIадоаде ше-шегIа кердадахар",
+       "rcfilters-liveupdates-button-title-off": "Керда хувцам бешше хьахьокха",
        "rcnotefrom": "КIалхагIа {{PLURAL:$5|хувцам белгалбаьккхаб}} <strong>$3, $4</strong> тIера (хьахьекхабац <strong>$1</strong>-л дукхагIа).",
        "rclistfrom": "$3 $2 денза даь хувцамаш хьахьокха",
-       "rcshowhideminor": "$1 Ð·Iамига Ð½Ð¸Ð¹Ñ\81даÑ\80аÑ\88",
+       "rcshowhideminor": "$1 Ð·Iамига Ð´Ð¾Ð»Ð° Ñ\82оадаÑ\80",
        "rcshowhideminor-show": "Хьахьокха",
        "rcshowhideminor-hide": "Къайладаккха",
        "rcshowhidebots": "$1 боташ",
        "rcshowhideliu": "$1 ражача дӏаэтта доакъашхой",
        "rcshowhideliu-show": "Хьахьокха",
        "rcshowhideliu-hide": "Къайлабаха",
-       "rcshowhideanons": "$1 цIияккханза доакъашхой",
+       "rcshowhideanons": "$1 Ñ\88оай Ñ\86IиÑ\8fккÑ\85анза Ð´Ð¾Ð°ÐºÑ\8aаÑ\88Ñ\85ой",
        "rcshowhideanons-show": "Хьахьокха",
        "rcshowhideanons-hide": "Къайлабаха",
        "rcshowhidepatr": "$1 техка хувцамаш",
        "rcshowhidepatr-show": "Хьахьокха",
        "rcshowhidepatr-hide": "Къайладаккха",
-       "rcshowhidemine": "$1 хьа нийсдараш",
+       "rcshowhidemine": "$1 Iайха тоадаьраш",
        "rcshowhidemine-show": "Хьахьокха",
        "rcshowhidemine-hide": "Къайладаккха",
        "rclinks": "Хьахьокха $2 дийнахь даь хинна тIеххьара $1 хувцамаш",
        "recentchangeslinked": "ВIашагIдувзаденна нийсдараш",
        "recentchangeslinked-feed": "ВIашагIдувзаденна нийсдараш",
        "recentchangeslinked-toolbox": "ВIашагIдувзаденна хувцамаш",
-       "recentchangeslinked-title": "$1ца вIашидувзаденна хувцамаш",
+       "recentchangeslinked-title": "$1ца вIаши дувзаденна хувцамаш",
        "recentchangeslinked-summary": "Ӏочуязъе оагӀон цӀи, цунна тӀатовжаш йолча оагӀонаш чу даь дола хувцамаш бӀаргагургдолаш (ОагӀата доакъашхой бӀаргагургболаш Ӏочуязъе {{ns:category}}:ОагӀата цӀи).\n[[Special:Watchlist|Хьа зéма хьаязъяьрá]] юкъейоагӀача оагӀонаш чу даь хувцамаш <strong>сомача лапӀазаца</strong> белгалдаь да.",
        "recentchangeslinked-page": "ОагIон цIи",
        "recentchangeslinked-to": "Вешта, белгаляьккха оагIон тIахьожавеш дола оагIонашта даь хувцамаш хьахьокха.",
        "fileuploadsummary": "Лоаца сурт оттадар:",
        "license": "Лицензи ялар:",
        "license-header": "Лицензировани",
+       "listfiles-delete": "дӀаяккха",
        "imgfile": "файл",
        "listfiles": "Файлий хьаязъяьр",
        "listfiles_date": "Ди",
        "file-anchor-link": "Файл",
        "filehist": "Файла истори",
        "filehist-help": "Ди/ха долча IотIатоIае цу хана файл мишта хиннай хьажа йиш хуpгьйолаш",
+       "filehist-deleteone": "дӀаяккха",
        "filehist-revert": "юхаяьккха",
        "filehist-current": "xIанзара",
        "filehist-datetime": "Ди/Ха",
        "statistics": "ГӀулакх-хьал",
        "statistics-articles": "Статьяш",
        "statistics-pages": "ОагIонаш",
+       "statistics-users-active": "Хьинаре доакъашхой",
        "double-redirect-fixer": "ДӀа-хьа хьожавара оагIонаш тоаер",
        "brokenredirects-edit": "нийсъе",
        "brokenredirects-delete": "дӀаяккха",
        "withoutinterwiki-submit": "Хьахьокха",
        "nbytes": "$1 {{PLURAL:$1|байт}}",
        "nmembers": "$1 {{PLURAL:$1|объект}}",
-       "prefixindex": "Ð\9eагÓ\80оний Ñ\86Ó\80еÑ\80ий Ð´ÐµÑ\88Ñ\85Ñ\8cалÑ\85ех хьахокхар",
+       "prefixindex": "Ð\9eагÓ\80онаÑ\88 Ñ\88оай Ñ\86Ó\80еÑ\80ий Ñ\85Ñ\8cалÑ\85аÑ\80Ñ\87а Ð°Ð»Ð°Ð¿Ð°х хьахокхар",
        "prefixindex-namespace": "ОагӀоний цӀераш шоай дешхьалхех хьахьокхар (цIерий моттиг «{{ns:$1}}»)",
+       "prefixindex-submit": "Хьахьокха",
+       "prefixindex-strip": "ДIакъайлаяха хьелехача оагIоний дешхьалхенаш (префиксаш)",
        "shortpages": "Лоаца оагIонаш",
        "longpages": "ЙIаьха оагIонаш",
        "protectedpages-page": "ОагIув",
        "allpagesto": "Хьахьокхар соцадé укхун тӀа:",
        "allarticles": "Еррига оагIонаш",
        "allpagessubmit": "Кхоачашде",
+       "allpagesprefix": "Хьалаха оагӀонаш, дӀайолалуш йола укх алапах:",
        "allpages-hide-redirects": "ДIакъайладаха дӀа-хьа хьожавераш",
        "categories": "ОагӀаташ",
+       "categories-submit": "Хьахьокха",
        "linksearch": "Арахьара тIахьожаяргаш лахар",
        "linksearch-ns": "ЦIерий моттигаш:",
        "linksearch-ok": "Хьалаха",
        "linksearch-line": "$1 яхача оагIонна тIатовжам $2 чура",
+       "activeusers": "Хьинаре доакъашхой",
+       "activeusers-submit": "Хьахьокха хьинаре бола доакъашхой",
+       "listgrouprights": "Доакъашхой тоабай бокъонаш",
        "listgrouprights-members": "(доакъашхой хьаязъяьр)",
        "listgrouprights-namespaceprotection-namespace": "ЦIерий моттиг",
        "emailuser": "Доакъашхочоа каьхат",
        "usermessage-editor": "Системан дIакхоачадар",
-       "watchlist": "Зем бара хьаязъяьр",
-       "mywatchlist": "Зем бара хьаязъяьр",
+       "watchlist": "Зем",
+       "mywatchlist": "Зем",
        "watchlistfor2": "Цунна $1 $2",
        "addedwatchtext": "Статья «[[:$1]]» а, цун дувца оттадара оагIув а тIатехай хьа [[Special:Watchlist|зем бара хьаязъяьра]].",
        "removedwatchtext": "Статья «[[:$1]]» а, иштта цун дувца оттадара оагIув а дIаяьккхай хьа [[Special:Watchlist|зем бара хьаязъяьр]] чура.",
        "watching": "Зем бара хьаязъяьр чу тIатохар",
        "unwatching": "Зем бара хьаязъяьр чура дIадаккхар",
        "enotif_reset": "Белгалъе еррига оагӀонаш бӀаргтехача санна",
+       "enotif_impersonal_salutation": "{{grammar:genitive|{{SITENAME}}}} – доакъашхо",
        "deletepage": "ДIаяккха оагIув",
+       "delete-confirm": "$1 — дӀаяккхар",
+       "delete-legend": "ДӀаяккхар",
        "confirmdeletetext": "Оаш дIадийхад бIарчча дIадаккхар оагIон а (е сурта), цун деррига хувцара истори а. '''Дехар да''', бакъде шоай из бокъонца де безам болаш долга а, из дича хургдар кхеташ долга а, из дар укх [[{{MediaWiki:Policy-url}}|бокъонашца]] долга.",
        "actioncomplete": "Ардам кхоачашдаьд",
        "actionfailed": "Ардам кхоачашдаьдац",
        "tooltip-ca-nstab-help": "Новкъостала оагIув",
        "tooltip-ca-nstab-category": "ОагӀата оагӀув",
        "tooltip-minoredit": "Ер хувцар кIезига дар санна белгалде",
-       "tooltip-save": "Ð¥Ñ\8cа Ñ\85Ñ\83вÑ\86амаÑ\88 Ð»Ð¾Ñ\80адеÑ\88 Ð´IаÑ\8fзде",
+       "tooltip-save": "Ð\94IаÑ\8fзде Ñ\85Ñ\8cай Ñ\85Ñ\83вÑ\86амаÑ\88",
        "tooltip-preview": "ОагIонна хьалххе бIаргтохар.\nДехар да, оагӀув дIаязъелехь хьажа из мишта я!",
        "tooltip-diff": "Чухьнахьара текстаца даь хувцамаш хьахьокха",
        "tooltip-compareselectedversions": "Укх оагIон хержа шин версешта юкъе йола башхалога хьажа.",
        "tags-active-yes": "XӀау",
        "tags-active-no": "A",
        "tags-edit": "нийсде",
+       "tags-delete": "дӀаяккха",
        "tags-hitcount": "$1 {{PLURAL:$1|1=хувцам|хувцамаш}}",
        "tags-create-submit": "Хьакхолла",
        "compare-page1": "ЦхьоаллагIа оагIув",
index 1edd51b..359c6aa 100644 (file)
        "rcfilters-activefilters": "Agiva filtrili",
        "rcfilters-advancedfilters": "Rafinita filtrili",
        "rcfilters-limit-title": "Rezulti por montrar",
+       "rcfilters-limit-and-date-label": "$1 {{PLURAL:$1|modifikuro|modifikuri}}, $2",
        "rcfilters-date-popup-title": "Quanto di tempo por serchar",
        "rcfilters-days-title": "Recenta dii",
        "rcfilters-hours-title": "Recenta hori",
        "rcfilters-filter-user-experience-level-experienced-label": "Experta uzeri",
        "rcfilters-filter-user-experience-level-experienced-description": "Plu kam 30 dii di agemeso e 500 redakti.",
        "rcfilters-filter-humans-label": "Homala (ne 'bot')",
+       "rcfilters-filter-humans-description": "Redakturi kreita da homi.",
        "rcfilters-filtergroup-significance": "Senco",
        "rcfilters-filter-pageedits-label": "Redakti di pagini",
        "rcfilters-filter-pageedits-description": "Redakturi en la kontenajo dil Wiki, diskuti, deskriptado di kategorii...",
        "rcfilters-filter-newpages-label": "Kreado di pagini",
+       "rcfilters-filter-newpages-description": "Redakturi qui kreas nova pagini.",
        "rcfilters-filter-categorization-label": "Modifiki di la kategorio",
        "rcfilters-filter-logactions-label": "Agadi enrejistrata",
+       "rcfilters-filter-logactions-description": "Agadi dal administreri, kreado di konti, efaco di pagini, sendo di arkivi...",
        "rcfilters-liveupdates-button": "Quika aktualigi",
        "rcnotefrom": "Infre {{PLURAL:$5|esas la chanjo|esas la chanji}} de <strong>$3, $4</strong> (montrata til <strong>$1</strong>).",
        "rclistfrom": "Montrar nova chanji startante de $3 $2",
        "tags-delete-too-many-uses": "L'etiketo \"$1\" uzesas en plua kam $2 {{PLURAL:$2|revizo|revizi}}, do ol ne povas eskartesar.",
        "tags-delete-warnings-after-delete": "L'etiketo \"$1\" efacesis, ma la sequanta {{PLURAL:$2|avizo|avizi}} renkontresis:",
        "tags-activate-not-found": "L'etiketo \"$1\" ne existas.",
+       "dberr-problems": "Pardonez! Ica retopagino subisas teknikala problemi.",
+       "dberr-again": "Voluntez vartar kelka minuti, e riprobez acesar ol.",
+       "dberr-info": "(Ne povis acesar la datumaro: $1)",
+       "dberr-info-hidden": "(La datumaro ne esas disponebla)",
+       "dberr-outofdate": "Atencez ke l'indexi pri kontenaji povas esar antiquatra.",
        "htmlform-reset": "Desfacar chanji",
        "htmlform-selectorother-other": "Altra",
        "htmlform-cloner-create": "Adjuntar plue",
index aa1d5a5..ab3733a 100644 (file)
@@ -70,7 +70,8 @@
                        "렌즈",
                        "CYAN",
                        "Nuevo Paso",
-                       "Doyoon1995"
+                       "Doyoon1995",
+                       "Jay94ks"
                ]
        },
        "tog-underline": "링크에 밑줄 긋기:",
        "subject-preview": "주제 미리 보기:",
        "previewerrortext": "변경사항을 미리보기하는 도중 오류가 발생했습니다.",
        "blockedtitle": "사용자가 차단됨",
-       "blockedtext": "'''사용자 계정 또는 IP 주소가 차단되었습니다.'''\n\n차단한 사람은 $1입니다.\n차단한 이유는 다음과 같습니다: $2\n\n* 차단이 시작된 시간: $8\n* 차단이 끝나는 시간: $6\n* 차단된 사용자: $7\n\n$1 또는 [[{{MediaWiki:Grouppage-sysop}}|다른 관리자]]에게 차단에 대해 문의할 수 있습니다.\n[[Special:Preferences|계정 환경 설정]]에 올바른 이메일 주소가 있어야만 '이메일 보내기' 기능을 사용할 수 있습니다. 또 이메일 보내기 기능이 차단되어 있으면 이메일을 보낼 수 없습니다.\n현재 당신의 IP 주소는 $3이고, 차단 ID는 #$5입니다.\n문의할 때에 이 정보를 같이 알려주세요.",
-       "autoblockedtext": "당신의 IP 주소는 $1님이 차단한 사용자가 사용했던 IP이기 때문에 자동으로 차단되었습니다.\n차단된 이유는 다음과 같습니다:\n\n:$2\n\n* 차단이 시작된 시간: $8\n* 차단이 끝나는 시간: $6\n* 차단된 사용자: $7\n\n$1 또는 [[{{MediaWiki:Grouppage-sysop}}|다른 관리자]]에게 차단에 대해 문의할 수 있습니다.\n\n[[Special:Preferences|사용자 환경 설정]]에 올바른 이메일 주소가 있어야만 \"이메일 보내기\" 기능을 사용할 수 있습니다. 또한 이메일 보내기 기능이 차단되어 있으면 이메일을 보낼 수 없습니다.\n\n현재 IP 주소는 $3이고, 차단 ID는 #$5입니다.\n문의할 때에 이 정보를 같이 알려주세요.",
+       "blockedtext": "'''사용자 계정 또는 IP 주소가 차단되었습니다.'''\n\n차단한 사람은 $1입니다.\n차단한 이유는 다음과 같습니다: <em>$2</em>.\n\n* 차단이 시작된 시간: $8\n* 차단이 끝나는 시간: $6\n* 차단된 사용자: $7\n\n$1 또는 [[{{MediaWiki:Grouppage-sysop}}|다른 관리자]]에게 차단에 대해 문의할 수 있습니다.\n[[Special:Preferences|계정 환경 설정]]에 올바른 이메일 주소가 있어야만 '이메일 보내기' 기능을 사용할 수 있습니다. 또 이메일 보내기 기능이 차단되어 있으면 이메일을 보낼 수 없습니다.\n현재 당신의 IP 주소는 $3이고, 차단 ID는 #$5입니다.\n문의할 때에 이 정보를 같이 알려주세요.",
+       "autoblockedtext": "당신의 IP 주소는 $1님이 차단한 사용자가 사용했던 IP이기 때문에 자동으로 차단되었습니다.\n차단된 이유는 다음과 같습니다:\n\n:<em>$2</em>\n\n* 차단이 시작된 시간: $8\n* 차단이 끝나는 시간: $6\n* 차단된 사용자: $7\n\n$1 또는 [[{{MediaWiki:Grouppage-sysop}}|다른 관리자]]에게 차단에 대해 문의할 수 있습니다.\n\n[[Special:Preferences|사용자 환경 설정]]에 올바른 이메일 주소가 있어야만 \"이메일 보내기\" 기능을 사용할 수 있습니다. 또한 이메일 보내기 기능이 차단되어 있으면 이메일을 보낼 수 없습니다.\n\n현재 IP 주소는 $3이고, 차단 ID는 #$5입니다.\n문의할 때에 이 정보를 같이 알려주세요.",
        "systemblockedtext": "당신의 사용자 이름 또는 IP 주소가 자동으로 미디어위키에 의해 차단되었습니다.\n이유는 다음과 같습니다:\n\n:<em>$2</em>\n\n* 차단 시작: $8\n* 차단 만료: $6\n* 차단 대상: $7\n\n당신의 현재 IP 주소는 $3입니다.\n문의에 대해 상기의 상세 설명을 모두 포함해 주십시오.",
        "blockednoreason": "이유를 입력하지 않음",
        "whitelistedittext": "문서를 편집하기 전에 $1해야 합니다.",
        "uploadstash-bad-path-bad-format": "\"$1\" 키는 적절한 포맷이 아닙니다.",
        "uploadstash-file-not-found": "저장소에서 \"$1\" 키를 찾지 못했습니다.",
        "uploadstash-file-not-found-no-thumb": "섬네일을 가져오지 못했습니다.",
+       "uploadstash-file-not-found-no-local-path": "썸네일을 가르키는 로컬 경로가 없습니다.",
        "uploadstash-file-not-found-no-object": "섬네일을 위한 로컬 파일 객체를 만들 수 없습니다.",
        "uploadstash-file-not-found-no-remote-thumb": "섬네일 가져오기를 실패했습니다: $1\nURL = $2",
        "uploadstash-file-not-found-missing-content-type": "content-type 헤더가 없습니다.",
        "apisandbox-dynamic-parameters-add-label": "변수 추가:",
        "apisandbox-dynamic-parameters-add-placeholder": "변수 이름",
        "apisandbox-dynamic-error-exists": "\"$1\"이라는 변수 이름은 이미 존재합니다.",
+       "apisandbox-templated-parameter-reason": "이 [[Special:ApiHelp/main#main/templatedparams|템플릿 매개 변수]]는 $2의 {{PLURAL:$1|value|values}}에 따라 제공됩니다.",
        "apisandbox-deprecated-parameters": "앞으로 제거될 변수",
        "apisandbox-fetch-token": "토큰 자동 채우기",
        "apisandbox-add-multi": "추가",
index 764e56e..68d5273 100644 (file)
        "previewnote": "'''Denkt drun datt dëst nëmmen eng net gespäichert Versioun ass.'''\nÄr Ännerunge sinn nach net gespäichert!",
        "continue-editing": "Gitt weider an de Beräich fir z'änneren",
        "previewconflict": "Dir gesitt an dem ieweschten Textfeld wéi den Text ausgesi wäert, wann Dir späichert.",
-       "session_fail_preview": "Är Ännerung konnt net gespäichert gi well d'Date vun Ärer Sessioun verluergaange sinn.\nDir gouft eventuell ausgeloggt. <strong>Iwwerpréift w.e.g. ob Dir nach ageloggt sidd a probéiert nach eng Kéier</strong>.\nWann de Problem dann ëmmer nach bestoe sollt, da versicht Iech [[Special:UserLogout|auszeloggen]] an dann erëm anzeloggen an iwwerpréift datt Äre Browser Cookië vun dësem Site  akzeptéiert.",
-       "session_fail_preview_html": "Är Ännerung konnt net gespäichert gi well d'Date vun Ärer Sessioun verluergaange sinn.\n\n<em>Well op {{SITENAME}} 'raw HTML' aktivéiert ass, gouf d'Uweise vun der nach net gespäicherter Versioun ausgeblennt fir JavaScript-Attacken ze vermeiden.</em>\n\n<strong>Wann Dir eng berechtegt Ännerung maache wëllt, da versicht et w.e.g. nach eng Kéier.</strong>\n\nWann de Problem dann ëmmer nach bestoe sollt, versicht Iech [[Special:UserLogout|auszeloggen]] an dann erëm anzeloggen a vergewëssert Iech datt Äre Browser d^Späichere vu Cookieë vun dësem Site zouléisst.",
+       "session_fail_preview": "Är Ännerung konnt net gespäichert gi well d'Date vun Ärer Sessioun verluergaange sinn.\nDir gouft eventuell ausgeloggt. <strong>Iwwerpréift w.e.g. ob Dir nach ageloggt sidd a probéiert nach eng Kéier</strong>.\nWann de Problem dann ëmmer nach bestoe sollt, da versicht Iech [[Special:UserLogout|auszeloggen]] an dann erëm anzeloggen an iwwerpréift ob Äre Browser Cookië vun dësem Site  akzeptéiert.",
+       "session_fail_preview_html": "Är Ännerung konnt net gespäichert gi well d'Date vun Ärer Sessioun verluergaange sinn.\n\n<em>Well op {{SITENAME}} 'raw HTML' aktivéiert ass, gouf d'Uweise vun der nach net gespäicherter Versioun ausgeblennt fir JavaScript-Attacken ze vermeiden.</em>\n\n<strong>Wann Dir eng berechtegt Ännerung maache wëllt, da versicht et w.e.g. nach eng Kéier.</strong>\n\nWann de Problem dann ëmmer nach bestoe sollt, versicht Iech [[Special:UserLogout|auszeloggen]] an dann erëm anzeloggen a vergewëssert Iech ob Äre Browser d'Späichere vu Cookieë vun dësem Site zouléisst.",
        "token_suffix_mismatch": "'''Är Ännerung gouf refuséiert, well Äre Browser Zeechen am Ännerungs-Identifiant verännert huet.'''\nD'Ännerung gouf refuséiert, fir ze verhënneren datt den Text op der Säit onliesbar gëtt.\nDëst geschitt heiansdo wann Dir en anonyme Proxy-Service um Internet benotzt.",
        "edit_form_incomplete": "'''En Deel vum Ännerungsformulaire koum net um Server un; iwwerpréift w.e.g ob Är Ännerunge komplett sinn a probéiert nach emol.'''",
        "editing": "Ännere vu(n) $1",
index 2813f97..9edaaa8 100644 (file)
        "tooltip-pt-watchlist": "Un lista de pajes cual tu monitori per cambias",
        "tooltip-pt-mycontris": "Un lista de tua contribuis",
        "tooltip-pt-anoncontribs": "Un lista de editas fada de esta adirije IP",
-       "tooltip-pt-login": "Nos recomenda ce tu autentici, ma esta no es no obligante",
+       "tooltip-pt-login": "Nos recomenda ce tu autentici, ma esta no es obligante",
        "tooltip-pt-login-private": "Tu nesesa autentici per usa esta vici",
        "tooltip-pt-logout": "Desautentici",
        "tooltip-pt-createaccount": "Nos recomenda ce tu crea un conta e autentici, ma esta no es obligante",
index 912a2b6..ca80b0b 100644 (file)
        "bold_tip": "စာလုံးမည်း",
        "italic_sample": "စာလုံး အစောင်း",
        "italic_tip": "စာလုံး အစောင်း",
-       "link_sample": "လင့် ခေါင်းစဉ်",
-       "link_tip": "အတွင်းပိုင်း လင့်",
-       "extlink_sample": "http://www.example.com လင့် ခေါင်းစဉ်",
+       "link_sample": "လင့်ခ် ခေါင်းစဉ်",
+       "link_tip": "အတွင်းပိုင်း လင့်ခ်",
+       "extlink_sample": "http://www.example.com လင့်ခ် ခေါင်းစဉ်",
        "extlink_tip": "ပြင်ပလင့်များ (http:// ကို ရှေ့ဆုံးမှ ထည့်ရေးရန် မမေ့ပါနှင့်)",
        "headline_sample": "ခေါင်းကြီးစာသား",
        "headline_tip": "အဆင့် ၂ ခေါင်းစီး",
        "summary-preview": "တည်းဖြတ်အကျဉ်းချုပ် နမူနာ:",
        "subject-preview": "အကြောင်းအရာ နမူနာ:",
        "blockedtitle": "အသုံးပြုသူကို ပိတ်ပင်ထားသည်",
-       "blockedtext": "<strong>သင်၏ အသုံးပြုသူအမည် သို့မဟုတ် အိုင်ပီလိပ်စာသည် ပိတ်ပင်ခြင်း ခံထားရသည်။</strong>\n\nဤပိတ်ပင်မှုအား $1 က ဆောင်ရွက်ခဲ့သည်။\nအကြောင်းရင်းမှာ <em>$2</em> ဖြစ်သည်။\n\n* ပိတ်ပင်ခြင်း စတင်ချိန်: $8\n* ပိတ်ပင်ခြင်း သက်တမ်းကုန်ချိန်: $6\n* ရည်ရွယ်ရာ blockee: $7\n\nသင်သည် ပိတ်ပင်မှုအတွက် ဆွေးနွေးရန် $1 သို့မဟုတ် အခြား [[{{MediaWiki:Grouppage-sysop}}|စီမံခန့်ခွဲသူ]] အား ဆက်သွယ်နိုင်သည်။\nသင့်အနေဖြင့် [[Special:Preferences|အကောင့်၏ ရွေးချယ်စရာများ]]ထဲတွင် ရေရာသော အီးမေးလိပ်စာအား မထည့်သွင်းထားပါက \"ဤအသုံးပြုသူအား အီးမေးပို့ပါ\" လုပ်ဆောင်ချက်ကို အသုံးပြုနိုင်မည် မဟုတ်ပါ။ အလားတူ ယင်းလုပ်ဆောင်ချက်ကို ပိတ်ပင်မခံရမှ လုပ်ဆောင်နိုင်မည်ဖြစ်သည်။\nသင်၏ လက်ရှိ အိုင်ပီလိပ်စာမှာ $3 ဖြစ်ပြီး၊ ပိတ်ပင်မှုအိုင်ဒီမှာ #$5 ဖြစ်သည်။\nသင်ပြုလုပ်မည့် စုံစမ်းမေးမြန်းမှုများတွင် အထက်ပါ အချက်များ အားလုံး ပါဝင်နေပါစေ။",
+       "blockedtext": "<strong>သင်၏ အသုံးပြုသူအမည် သို့မဟုတ် အိုင်ပီလိပ်စာသည် ပိတ်ပင်ခြင်း ခံထားရသည်။</strong>\n\nဤပိတ်ပင်မှုအား $1 က ဆောင်ရွက်ခဲ့သည်။\nအကြောင်းရင်းမှာ <em>$2</em> ဖြစ်သည်။\n\n* ပိတ်ပင်ခြင်း စတင်ချိန်: $8\n* ပိတ်ပင်ခြင်း သက်တမ်းကုန်ချိန်: $6\n* ရည်ရွယ်ရာ blockee: $7\n\nသင်သည် ပိတ်ပင်မှုအတွက် ဆွေးနွေးရန် $1 သို့မဟုတ် အခြား [[{{MediaWiki:Grouppage-sysop}}|စီမံခန့်ခွဲသူ]] အား ဆက်သွယ်နိုင်သည်။\nသင့်အနေဖြင့် [[Special:Preferences|အကောင့်၏ ရွေးချယ်စရာများ]]ထဲတွင် ရေရာသော အီးမေးလိပ်စာအား မထည့်သွင်းထားပါက \"{{int:emailuser}}\" လုပ်ဆောင်ချက်ကို အသုံးပြုနိုင်မည် မဟုတ်ပါ။ အလားတူ ယင်းလုပ်ဆောင်ချက်ကို ပိတ်ပင်မခံရမှ လုပ်ဆောင်နိုင်မည်ဖြစ်သည်။\nသင်၏ လက်ရှိ အိုင်ပီလိပ်စာမှာ $3 ဖြစ်ပြီး၊ ပိတ်ပင်မှုအိုင်ဒီမှာ #$5 ဖြစ်သည်။\nသင်ပြုလုပ်မည့် စုံစမ်းမေးမြန်းမှုများတွင် အထက်ပါ အချက်များ အားလုံး ပါဝင်နေပါစေ။",
        "blockednoreason": "အကြောင်းပြချက် မပေးထားပါ",
        "whitelistedittext": "စာမျက်နှာများကို တည်းဖြတ်ရန် $1ရမည်။",
        "nosuchsectiontitle": "အပိုင်းကို ရှာမရနိုင်ပါ",
        "recentchangeslinked-feed": "ဆက်စပ်သော ​အ​ပြောင်း​အ​လဲ​များ​",
        "recentchangeslinked-toolbox": "ဆက်စပ်သော အပြောင်းအလဲများ",
        "recentchangeslinked-title": "\"$1\" နှင့် ဆက်စပ်သော အပြောင်းအလဲများ",
-       "recentchangeslinked-summary": "ဤစာမျက်နှာမှ သို့မဟုတ် ဤစာမျက်နှာသို့ ချိတ်ဆက်ထားသော စာမျက်နှာများ၏ ပြောင်းလဲမှုများကို ကြည့်ရှုနိုင်ရန် စာမျက်နှာအမည်တစ်ခုကို ထည့်သွင်းပါ။ (ကဏ္ဍတစ်ခု၏ အဖွဲ့ဝင်များကို ကြည့်ရှုရန် Category:ကဏ္ဍအမည် ကို ရိုက်ထည့်ပါ။) [[Special:Watchlist|သင့်စောင့်ကြည့်စာရင်း]]ရှိ စာမျက်နှာများ၏ ပြောင်းလဲမှုများကို <strong>စာလုံးအထူ</strong>ဖြင့် ပြထားသည်။",
+       "recentchangeslinked-summary": "ဤစာမျက်နှာမှ သို့မဟုတ် ဤစာမျက်နှာသို့ ချိတ်ဆက်ထားသော စာမျက်နှာများ၏ ပြောင်းလဲမှုများကို ကြည့်ရှုနိုင်ရန် စာမျက်နှာအမည်တစ်ခုကို ထည့်သွင်းပါ။ (ကဏ္ဍတစ်ခု၏ အဖွဲ့ဝင်များကို ကြည့်ရှုရန် {{ns:category}}:ကဏ္ဍအမည် ကို ရိုက်ထည့်ပါ။) [[Special:Watchlist|သင့်စောင့်ကြည့်စာရင်း]]ရှိ စာမျက်နှာများ၏ ပြောင်းလဲမှုများကို <strong>စာလုံးအထူ</strong>ဖြင့် ပြထားသည်။",
        "recentchangeslinked-page": "စာမျက်နှာ အမည် -",
        "recentchangeslinked-to": "ပေးထားသော စာမျက်နှာများအစား လင့်များနှင့် ဆက်စပ်နေသာ စာမျက်နှာများ၏ အပြောင်းအလဲများကို ပြရန်",
        "recentchanges-page-added-to-category": "ကဏ္ဍထဲသို့ [[:$1]] ကို ပေါင်းထည့်ခဲ့သည်",
        "whatlinkshere-title": "\"$1\" သို့ ချိတ်ဆက်ထားသော စာမျက်နှာများ",
        "whatlinkshere-page": "စာမျက်နှာ -",
        "linkshere-2": "အောက်ပါစာမျက်နှာများသည် <strong>$1</strong> သို့ ချိတ်ဆက်ထားသည် -",
-       "nolinkshere-2": "'''$1''' သို့ လင့်ထားသော စာမျက်နှာ မရှိပါ။",
+       "nolinkshere-2": "<strong>$1</strong> သို့ လင့်ခ်ထားသော စာမျက်နှာ မရှိပါ။",
        "isredirect": "ပြန်ညွှန်းသော စာမျက်နှာ",
        "istemplate": "ထည့်သွင်းကူးယူချက်",
        "isimage": "ဖိုင်လင့်",
        "whatlinkshere-prev": "{{PLURAL:$1|နောက်သို့|နောက်သို့ $1}}",
        "whatlinkshere-next": "{{PLURAL:$1|ရှေ့သို့|ရှေ့သို့ $1}}",
-       "whatlinkshere-links": "← လင့်များ",
+       "whatlinkshere-links": "â\86\90 á\80\9cá\80\84á\80·á\80ºá\80\81á\80ºá\80\99á\80»á\80¬á\80¸",
        "whatlinkshere-hideredirs": "ပြန်ညွှန်းများ $1",
        "whatlinkshere-hidetrans": "ထည့်သွင်းကူးယူချက် $1",
        "whatlinkshere-hidelinks": "လင့်ခ်များ $1 ခု",
        "blocklist-nousertalk": "မိမိ၏ဆွေးနွေးချက်စာမျက်နှာကို တည်းဖြတ်မရနိုင်ပါ",
        "ipblocklist-empty": "ပိတ်ပင်ထားမှုစာရင်းသည် ဗလာဖြစ်နေသည်။",
        "blocklink": "ပိတ်ပင်",
-       "unblocklink": "á\80\9cá\80\84á\80·á\80º á\80\95á\80¼á\80\94á\80ºá\80\96á\80¼á\80±ရန်",
+       "unblocklink": "á\80\99á\80\95á\80­á\80\90á\80ºá\80\95á\80\84á\80ºá\80\90á\80±á\80¬á\80·ရန်",
        "change-blocklink": "စာကြောင်းအမည် ပြောင်းရန်",
        "contribslink": "ပံ့ပိုး",
        "blocklogpage": "ပိတ်ပင်တားဆီးမှု မှတ်တမ်း",
        "newimages-label": "ဖိုင်အမည် (သို့ ယင်း၏အစိတ်အပိုင်း) -",
        "noimages": "ကြည့်စရာဘာမှ မရှိပါ။",
        "ilsubmit": "ရှာဖွေရန်",
-       "bydate": "á\80\9bá\80\80á\80ºá\80\85á\80½á\80²á\80\96á\80¼á\80­á\80\84á\80·á\80º",
+       "bydate": "ရက်စွဲဖြင့်",
        "sp-newimages-showfrom": "$1 နေ့ $2 အချိန်ကစသော ဖိုင်အသစ်များကို ပြရန်",
        "bad_image_list": "ဖောမတ်ပုံစံမှာ အောက်ပါအတိုင်းဖြစ်သည်။\n\nစာရင်းတွင်ထည့်သွင်းထားသော အရာများကိုသာ ထည့်သွင်းစဉ်းစားမည်။ (ခရေပွင့် * ဖြင့်စသော စာကြောင်းများ)\nစာကြောင်း၏ ပထမဆုံး လင့်သည် ဖိုင်ညံ့ ဖြစ်ရမည်။\nယင်းစာကြောင်းတွင်ပင် နောက်ထပ်လာသောလင့်များကို ချွင်းချက်အဖြစ် စဉ်းစားမည်။ ဆိုလိုသည်မှာ ၎င်းလင့်များတွင်လည်း အဆိုပါ ဖိုင်ညံ့ ပါကောင်း ပါဝင်နေမည်။",
        "metadata": "Metadata",
        "specialpages-group-maintenance": "ထိန်းသိမ်းမှု အစီရင်ခံချက်များ",
        "specialpages-group-other": "အခြားအထူးစာမျက်နှာများ",
        "specialpages-group-login": "Log in ဝင်ရန်/ အကောင့် ဖန်တီးရန်",
-       "specialpages-group-changes": "လတ်တလောအေပြောင်းအလဲနှင့် မှတ်တမ်းများ",
+       "specialpages-group-changes": "လတ်တလော အပြောင်းအလဲနှင့် မှတ်တမ်းများ",
        "specialpages-group-media": "မီဒီယာ အစီရင်ခံချက်များနှင့် Upload တင်ထားသည်များ",
        "specialpages-group-users": "အသုံးပြုသူများနှင့် အခွင့်အရေးများ",
        "specialpages-group-highuse": "အသုံးများသော စာမျက်နှာများ",
index 443bb11..7c289c7 100644 (file)
        "virus-scanfailed": "scanziona fallita (codece $1)",
        "virus-unknownscanner": "antivirus scanusciuto:",
        "logouttext": "'''Site asciùte.'''\n\nNota ca arcune paggene putessero cuntinuà ad cumparì comme se 'o logout nun fosse affettuato fin quanno nun sarrà pulezzata 'a cache d\"o proprio browser.",
-       "cannotlogoutnow-title": "Nun se pò ascì mò",
+       "cannotlogoutnow-title": "Mo nun se pò ascì",
        "cannotlogoutnow-text": "'A disconessione nun è possibbele quanno s'ausa $1.",
        "welcomeuser": "Bemmenuto, $1!",
        "welcomecreation-msg": "'O cunto vuosto è stato criato.\nMo' putite cagnà 'e [[Special:Preferences|preferenze 'e {{SITENAME}}]].",
        "userlogin-signwithsecure": "Usa na conessione sicura",
        "cannotlogin-title": "Nun se pò trasì",
        "cannotlogin-text": "Trasì nun è possibbele mò.",
-       "cannotloginnow-title": "Nun se pò trasì mò",
+       "cannotloginnow-title": "Mo nun se pò trasì",
        "cannotloginnow-text": "'A connessione nun è possibbele quanno s'ausa $1.",
        "cannotcreateaccount-title": "Nun se ponno crià cunte",
        "cannotcreateaccount-text": "'A criazione diretta 'e cunte è stutata int'a stu wiki.",
        "editconflict": "Conflitto d'edizzione: $1",
        "explainconflict": "N'at'utente ave sarvato na nova verziona d' 'a paggena pe' tramente ca stevate a fà 'e cagnamiente.\n'A cascia 'e mudifeca ncoppa cuntene 'o testo d' 'a paggena ca mò sta online, accussì comme è stato agghiurnato a l'at'utente.\n'A verziona ch' 'e cagnamiente vuoste è stata mmece riportata dint'a cascia 'e mudifeca abbascio.\nSi 'e vulite cunfermà avite 'a ripurtà 'e cagnamiente d' 'e vuoste dint'o testo ca esiste (dint'a cascia ncoppa).\nSpremmendo 'o buttón '$1', sarrà sarvato '''sulamente''' 'o testo cuntenuto dint'a cascia 'e cagnamiento ncoppa.",
        "yourtext": "'O testo vuosto",
-       "storedversion": "A verziona 'n memoria",
+       "storedversion": "A verziona int'a memoria",
        "editingold": "'''Attenziò: staje cagnanno na verziona nun agghiurnata d' 'a paggena. Si 'a sarve accussì, tutte 'e cagnamiente fatte aropp'a sta verziona sarranno sperdute.'''",
        "yourdiff": "Differenze",
        "copyrightwarning": "Pe' piacere tenite a mmente ca tutte 'e contribbute a {{SITENAME}} songo cunziderate pubbrecate dint'e térmene d'uso d' 'a licienza $2 (vedite $1 pe n'avé cchiù dettaglie).\nSi nun vulite ca 'e testi vuoste fossero cagnate e distribuite 'a uno qualunque senza lémmeto, nun 'e mannate ccà.<br />\nMannanno stu testo dichiarate pùre, sott'a responsabilità vuosta, ch'è stato scritto 'a vuje perzunalmente o pure ca è stato copiato 'a na fonte n pubblico dominio o similarmente libbera.\n'''Nun mannate materiale prutetto 'a copyright senz'avé autorizzaziona!'''",
        "tmp-write-error": "Errore a scrivere nu file temporaneo.",
        "large-file": "S'arraccumanna 'e nun appassà 'e diminsione 'e $1 p'ogne file; stu file è gruosso $2.",
        "largefileserver": "Stu file appassa 'e dimensiune permesse 'a la configurazione d' 'o server",
-       "emptyfile": "'O file carrecato mò mò pare abbacante. Può darse ch'è stato n'errore int' 'o nomme d' 'o file. Cuntrullate ca vulite overamente carrecà stu file.",
+       "emptyfile": "'O file c'avite carrecato pare avvacante. Può essere ch'è stato n'errore int' 'o nomme d' 'o file. Cuntrullate ca vulite overamente carrecà stu file.",
        "windows-nonascii-filename": "Chista wiki nun supporta nomme d' 'e file cu carattere spiciale",
        "fileexists": "Nu file cu stu nomme esiste già.\nPe' piacere cuntrullate primma <strong>[[:$1]]</strong> si nun site sicure ca 'o vulite cagnà.\n[[$1|thumb]]",
        "filepageexists": "'A paggena 'e descrizione 'e stu file è stata già criata a l'indirizzo <strong>[[:$1]]</strong>, pùre si nun esiste ancora nu file cu stu nomme. 'A descrizione 'e l'oggetto nzertàta 'n fase 'e carreca nun cumparerrà ncopp' 'a paggena 'e descrizione. Pe' ffà l'oggetto cumparì ncopp' 'a paggena 'e descrizione, l'avisseve 'a cagnà manualmente.\n[[$1|thumb]]",
        "backend-fail-read": "Nun se può lieggere 'o file \"$1\".",
        "backend-fail-create": "Nun se può scrivere 'o file \"$1\"",
        "backend-fail-maxsize": "Nun se può scrivere 'o file \"$1\" pecché chist'è cchiù gruosso 'e {{PLURAL:$2|nu byte|$2 byte}}",
-       "backend-fail-readonly": "L'archivio 'e rezza \"$1\" è mò mò 'n sola-lettura. 'O mutivo è: <em>$2</em>",
+       "backend-fail-readonly": "L'archivio 'e rezza \"$1\" sta mo c'â sola-lettura. 'O mutivo è: <em>$2</em>",
        "backend-fail-synced": "'O file \"$1\" è int' 'a nu stato ncunzistente dint'a l'archivie nterne.",
        "backend-fail-connect": "Nun se può cunnettà â memoria 'e rezza \"$1\".",
        "backend-fail-internal": "N'errore scanusciuto s'è verificato int'a l'archivie 'e rezza \"$1\".",
        "filerevert-submit": "Arrepiglia",
        "filerevert-success": "'''[[Media:$1|$1]]''' è stat'arripigliato â verziona [$4 d' 'e $3 d' 'o $2].",
        "filerevert-badversion": "Nun ce sta na virziona lucale 'e stu file cu l'orario addimannato.",
-       "filerevert-identical": "'A verziona 'e mò d' 'o file è già eguale eguale a chilla scigliuta.",
+       "filerevert-identical": "'A verziona 'e mo d' 'o file è già eguale eguale a chella scigliuta.",
        "filedelete": "Scancella $1",
        "filedelete-legend": "Scancella 'o file",
        "filedelete-intro": "State pe' scancellà 'o file '''[[Media:$1|$1]]''' cu tutta 'a cronologgia 'e chisto.",
        "protectedpages-summary": "Sta paggena elenca 'e paggene ch'esisteno e ca songo prutette mò. Pe n'avé n'elenco 'e titule prutette â criazione, vedite [[{{#special:ProtectedTitles}}|{{int:protectedtitles}}]].",
        "protectedpages-cascade": "Sulamente prutezziune ricurzive",
        "protectedpages-noredirect": "Annascunne redirect",
-       "protectedpagesempty": "Nisciuna paggena è prutetta pe mò cu sti parametre.",
+       "protectedpagesempty": "Nisciuna paggena è prutetta pe mo cu sti parametre.",
        "protectedpages-timestamp": "Data e ora",
        "protectedpages-page": "Paggena",
        "protectedpages-expiry": "Ammatura",
        "protectedpages-unknown-performer": "Utente scanusciuto",
        "protectedtitles": "Paggene prutette",
        "protectedtitles-summary": "Sta paggena elenca 'e titule ca song'attualmente prutette 'a criazione. Pe' n'avé n'elenco 'e paggene prutette ch'esisteno, vedite [[{{#special:ProtectedPages}}|{{int:protectedpages}}]].",
-       "protectedtitlesempty": "Nisciunu titolo è prutetto pe mò cu sti parametre.",
+       "protectedtitlesempty": "Nisciuno titolo è prutetto pe mo cu sti parametre.",
        "protectedtitles-submit": "Mmusta titule",
        "listusers": "Lista 'e l'utente",
        "listusers-editsonly": "Fà vedé sulamente l'utente cu cagnamiente fatte",
        "apisandbox-dynamic-parameters-add-label": "Azzecca nu parametro:",
        "apisandbox-dynamic-parameters-add-placeholder": "Nomme d' 'o parametro",
        "apisandbox-dynamic-error-exists": "Nu parametro denommenato \"$1\" esiste già.",
-       "apisandbox-deprecated-parameters": "Parametre mò obsoleti",
+       "apisandbox-deprecated-parameters": "Parametri obsoleti",
        "apisandbox-fetch-token": "Auto-ghienche 'o token",
        "apisandbox-submit-invalid-fields-title": "Cocche campo nun è buono",
        "apisandbox-submit-invalid-fields-message": "Pe' piacere curriggite 'e campe nzegnàte e tentate n'ata vota.",
        "months": "{{PLURAL:$1|$1 mese|$1 mese}}",
        "years": "{{PLURAL:$1|$1 anno|$1 anne}}",
        "ago": "$1 fà",
-       "just-now": "mò mò",
+       "just-now": "mo mmo",
        "hours-ago": "$1 {{PLURAL:$1|ora|ore}} fà",
        "minutes-ago": "$1 {{PLURAL:$1|minuto|minute}} fà",
        "seconds-ago": "$1 {{PLURAL:$1|secondo|seconde}} fà",
        "notificationemail_subject_changed": "L'indirizzo email riggistrato ncopp'a {{SITENAME}} è stato cagnato",
        "notificationemail_subject_removed": "L'indirizzo email riggistrato dint'a {{SITENAME}} è stato luvato",
        "notificationemail_body_changed": "Coccheruno, probbabilmente vuje, 'a ll'indirizzo IP $1,\nave cagnato l'indirizze e-mail d' 'o cunto \"$2\" a \"$3\" ncopp'a {{SITENAME}}.\n\nSi nun eravate vuje, pe' piacere tuzzuliate mò mò n'ammenistratore.",
-       "notificationemail_body_removed": "Coccheruno, probbabilmente vuje, 'a ll'indirizzo IP $1,\nave luvato l'indirizze e-mail d' 'o cunto \"$2\" ncopp'a {{SITENAME}}.\n\nSi nun eravate vuje, pe' piacere tuzzuliate mò mò n'ammenistratore.",
+       "notificationemail_body_removed": "Coccheruno, probbabilmente vuje, 'a ll'indirizzo IP $1,\nave luvato l'indirizze e-mail d' 'o cunto \"$2\" ncopp'a {{SITENAME}}.\n\nSi nun eravate vuje, pe piacere tuzzuliate a n'ammenistratore.",
        "scarytranscludedisabled": "['A funziona cullegamiento nfra site wiki è stata stutata]",
        "scarytranscludefailed": "[L'analisi d' 'o template s'è scassato pe' $1]",
        "scarytranscludefailed-httpstatus": "[L'analisi d' 'o template s'è scassato pe' $1: HTTP $2]",
        "specialpages-group-maintenance": "Report 'e manutenzione",
        "specialpages-group-other": "Ati paggene speciale",
        "specialpages-group-login": "Trasite o criate n'acciesso nuovo",
-       "specialpages-group-changes": "Cagnamiente 'e mò mò e riggistre",
+       "specialpages-group-changes": "Urdeme cagnamiénte e riggistre",
        "specialpages-group-media": "Riepileghe 'e media e carreche",
        "specialpages-group-users": "Utente e deritte",
        "specialpages-group-highuse": "Pàggene ausate assaje proprio",
        "dberr-info": "(Nun se può trasì 'o database: $1)",
        "dberr-info-hidden": "(Nun se può trasì 'o database)",
        "dberr-usegoogle": "Pe' tramente putite pruvà 'ascianno ncoppa Google.",
-       "dberr-outofdate": "Vedite ca l'indice lloro d' 'e cuntenute nuoste ponno nun essere agghiurnate mò mò.",
+       "dberr-outofdate": "Vedite ca ll'indice lloro d'ê cuntenute nuoste ponno essere passate.",
        "dberr-cachederror": "Chest'è na copia \"cache\" d' 'a paggena c'avite asciato, e putesse nun essere agghiurnata.",
        "htmlform-invalid-input": "Ce sta cocche probblema cu l'input c'avite miso.",
        "htmlform-select-badoption": "'O valore c'avite specificato nun è n'opziona bbuona.",
        "logentry-delete-delete": "$1 {{GENDER:$2|scancellaje}} 'a paggena $3",
        "logentry-delete-restore": "$1 {{GENDER:$2|arrepigliaje}} 'a paggena $3 ($4)",
        "logentry-delete-event": "$1 {{GENDER:$2|cagnaie}} 'a vesibbiletà 'e {{PLURAL:$5|n'azione d' 'o riggistro|$5 aziune d' 'o riggistro}} ncopp' 'a 'a $3: $4",
-       "logentry-delete-revision": "$1 {{GENDER:$2|cagnaie}} 'a vesibbiletà 'e {{PLURAL:$5|na verziona|$5 verziune}} ncopp' 'a 'a $3: $4",
-       "logentry-delete-event-legacy": "$1 {{GENDER:$2|cagnaie}} 'a vesibbiletà 'e l'aziune dint' 'o riggistro ncopp' 'a $3: $4",
-       "logentry-delete-revision-legacy": "$1 {{GENDER:$2|cagnaie}} 'a vesibbiletà d' 'e verziune ncopp' 'a $3",
+       "logentry-delete-revision": "$1 {{GENDER:$2|cagnaie}} 'a vesibbiletà 'e {{PLURAL:$5|na verziona|$5 verziune}} ncopp'a $3: $4",
+       "logentry-delete-event-legacy": "$1 {{GENDER:$2|cagnaie}} 'a vesibbiletà 'e l'aziune int' 'o riggistro ncopp'a $3: $4",
+       "logentry-delete-revision-legacy": "$1 {{GENDER:$2|cagnaie}} 'a vesibbiletà d'ê verziune ncopp'a $3",
        "logentry-suppress-delete": "$1 {{GENDER:$2|luvaje pe' sempe}} 'a paggena $3",
        "logentry-suppress-event": "$1 {{GENDER:$2|annascunnuto cagnaie|annascunnuta cagnaie}} 'a vesibbiletà 'e {{PLURAL:$5|n'azione d' 'o riggistro|$5 aziune d' 'o riggistro}} ncopp' 'a 'a $3: $4",
        "logentry-suppress-revision": "$1 {{GENDER:$2|annascunnuto cagnaie|annascunnuta cagnaie}} 'a vesibbiletà 'e {{PLURAL:$5|na verziona|$5 verziune}} ncopp' 'a 'a $3: $4",
-       "logentry-suppress-event-legacy": "$1 {{GENDER:$2|annascunnuto cagnaie|annascunnuta cagnaie}} 'a vesibbiletà 'e l'aziune 'e riggistro ncopp' 'a $3",
-       "logentry-suppress-revision-legacy": "$1 {{GENDER:$2|annascunnuto cagnaie|annascunnuta cagnaie}} 'a vesibbiletà d' 'e verziune ncopp' 'a $3",
+       "logentry-suppress-event-legacy": "$1 cagnaie {{GENDER:$2|annascunnuto|annascunnuta}} 'a vesibbiletà 'e l'aziune 'e riggistro ncopp' 'a $3",
+       "logentry-suppress-revision-legacy": "$1 cagnaie {{GENDER:$2|annascunnuto|annascunnuta}} 'a vesibbiletà d' 'e verziune ncopp'a $3",
        "revdelete-content-hid": "cuntenute annascunnute",
        "revdelete-summary-hid": "riepilego 'e cagnamiente annascunnute",
        "revdelete-uname-hid": "nomme utente annascunnuto",
        "authmanager-authplugin-setpass-denied": "'O plugin autenticazione nun premmettesse 'e cagnà 'e password.",
        "authmanager-authplugin-setpass-bad-domain": "Dominio invalido.",
        "authmanager-autocreate-noperm": "'A criazione automatica 'e ll'utenza nun fosse premmessa.",
-       "authmanager-autocreate-exception": "Criazione 'e cunte automatica mò mò è stutata pe' bbìa 'e ll'errure precedenti.",
+       "authmanager-autocreate-exception": "Criazione 'e cunte automatica stutata pe nu poc'ê tiempo pe vvìa 'e ll'errure precedenti.",
        "authmanager-userdoesnotexist": "'O cunto utente \"$1\" nun è riggistrato.",
        "authmanager-userlogin-remembermypassword-help": "Si 'a pasword adda essere arricurdata cchiù a luongo cu rispett'a tutt' 'a durata d' 'a sessione.",
        "authmanager-username-help": "Nomme utente pe' ll'autenticaziona.",
index 303f4e1..8b306c4 100644 (file)
        "authmanager-password-help": "Passord for autentisering.",
        "authmanager-domain-help": "Domene for ekstern autentisering.",
        "authmanager-retype-help": "Passord igjen for å bekrefte.",
-       "authmanager-email-label": "Epost",
+       "authmanager-email-label": "E-post",
        "authmanager-email-help": "Epostadresse",
        "authmanager-realname-label": "Virkelig navn",
        "authmanager-realname-help": "Brukerens virkelige navn",
index fbf250f..f295c76 100644 (file)
        "rcfilters-filter-reviewstatus-unpatrolled-label": "Niet gecontroleerd",
        "rcfilters-filter-reviewstatus-manual-description": "Bewerkingen die handmatig zijn gecontroleerd",
        "rcfilters-filter-reviewstatus-manual-label": "Handmatig gecontroleerd",
-       "rcfilters-filter-reviewstatus-auto-description": "Bewerkingen door geavanceerde gebruikers wiens werk automatisch gecontroleerd is.",
+       "rcfilters-filter-reviewstatus-auto-description": "Bewerkingen door geavanceerde gebruikers wier werk automatisch gecontroleerd wordt.",
        "rcfilters-filter-reviewstatus-auto-label": "Automatisch gecontroleerd",
        "rcfilters-filtergroup-significance": "Belangrijkheid",
        "rcfilters-filter-minor-label": "Kleine bewerkingen",
        "thumbnail_dest_directory": "Niet in staat doelmap aan te maken",
        "thumbnail_image-type": "Dit bestandstype wordt niet ondersteund",
        "thumbnail_gd-library": "De instellingen voor de GD-bibliotheek zijn incompleet. De functie $1 ontbreekt",
-       "thumbnail_image-size-zero": "De afbeeldingsbestandsgrootte lijkt nul te zijn.",
+       "thumbnail_image-size-zero": "De grootte van het afbeeldingsbestand lijkt nul te zijn.",
        "thumbnail_image-missing": "Het bestand lijkt niet aanwezig te zijn: $1",
        "thumbnail_image-failure-limit": "Het maken van een miniatuurafbeelding is te vaak mislukt ($1 keer of vaker). Probeer het later nog eens.",
        "import": "Pagina's importeren",
        "pagedata-text": "Deze pagina biedt een data-interface voor pagina's. Geef een paginatitel op door deze in de URL op te nemen, op de manier van een deelpagina.\n* De inhoud wordt afgestemd op de door de client meegestuurde Accept Header. Dit betekent dat de gegevens voor de pagina worden aangeboden in het voorkeursformaat van uw client.",
        "pagedata-not-acceptable": "Er is geen overeenkomende indeling gevonden. Ondersteunde MIME-typen: $1",
        "pagedata-bad-title": "Ongeldige titel: $1.",
-       "unregistered-user-config": "Vanwege veiligheidsredenen wordt worden gebruikersdeelpagina's met JavaScript, CSS en JSON niet langer geladen voor gebruikers die niet zijn geregistreerd.",
+       "unregistered-user-config": "Om veiligheidsredenen worden gebruikersdeelpagina's met JavaScript, CSS en JSON niet geladen voor gebruikers die niet zijn geregistreerd.",
        "passwordpolicies": "Wachtwoordbeleid",
        "passwordpolicies-summary": "Dit is een lijst met de wachtwoordbeleidvormen die van toepassing zijn op de gebruikersgroepen van deze wiki.",
        "passwordpolicies-group": "Groep",
index 72ebc90..c9862b6 100644 (file)
        "rcfilters-quickfilters-placeholder-description": "For å lagra filterinnstillingane dine og bruka dei på nytt seinare, klikk på bokmerkeikonet i området for aktive filter under.",
        "rcfilters-savedqueries-defaultlabel": "Lagra filter",
        "rcfilters-savedqueries-rename": "Gje nytt namn",
+       "rcfilters-savedqueries-setdefault": "Set som standard",
        "rcfilters-savedqueries-new-name-label": "Namn",
        "rcfilters-savedqueries-new-name-placeholder": "Skildra føremålet med filteret",
        "rcfilters-savedqueries-apply-label": "Lagra innstillingar",
+       "rcfilters-savedqueries-apply-and-setdefault-label": "Opprett standardfilter",
        "rcfilters-savedqueries-add-new-title": "Lagra gjeldande filterinnstillingar",
+       "rcfilters-savedqueries-already-saved": "Desse filtera er alt lagra. Endra innstillingane dine for å oppretta eit nytt lagra filter.",
        "rcfilters-clear-all-filters": "Fjern alle filter",
        "rcfilters-show-new-changes": "Sjå dei nyaste endringane",
        "rcfilters-search-placeholder": "Filtrer endringar (nytt meny eller søk etter filternamn)",
        "rcfilters-invalid-filter": "Ugyldig filter",
        "rcfilters-empty-filter": "Ingen aktive filter. Alle bidrag er viste.",
        "rcfilters-filterlist-title": "Filter",
+       "rcfilters-filterlist-whatsthis": "Korleis verkar desse?",
        "rcfilters-filterlist-feedbacklink": "Gje attendemelding på dei nye (beta)filtera",
        "rcfilters-highlightbutton-title": "Uthev resultat",
        "rcfilters-highlightmenu-title": "Vel ein farge",
index 400d86a..aa2f766 100644 (file)
        "right-siteadmin": "Verrolhar e desverrolhar la basa de donadas",
        "right-override-export-depth": "Exportar las paginas en incluent las paginas ligadas fins a una prigondor de 5 nivèls",
        "right-sendemail": "Mandar un corrièl als autres utilizaires",
+       "right-managechangetags": "Crear, activar e desactivar [[Special:Tags|tags]]",
        "right-applychangetags": "Aplicar [[Special:Tags|las balisas]] amb sas pròprias modificacions",
+       "right-changetags": "Apondre e suprimir arbitràriament [[Special:Tags|tags]] sus de revisions individualas e d'intradas de jornal",
+       "right-deletechangetags": "Suprimir [[Special:Tags|tags]] dempuèi la basa de donadas",
        "grant-generic": "ensemble de dreits « $1 »",
        "grant-group-page-interaction": "Interagir amb de paginas",
        "grant-group-file-interaction": "Interagir amb de mèdias",
        "grant-group-watchlist-interaction": "Interagir amb vòstra lista de seguiment",
        "grant-group-email": "Mandar un corrièr electronic",
+       "grant-group-high-volume": "Realizar una activitat de volum naut",
        "grant-group-customization": "Personalizacion e preferéncias",
        "grant-group-administration": "Efectuar d'accions administrativas",
        "grant-group-private-information": "Accedir a vòstras donadas privadas",
        "grant-blockusers": "Blocar e desblocar d'utilizaires",
        "grant-createaccount": "Crear de comptes",
        "grant-createeditmovepage": "Crear, modificar e desplaçar de paginas",
+       "grant-delete": "Suprimir paginas, revisions e dintradas de jornal",
        "grant-editinterface": "Modificar l'espaci de noms de MediaWiki e lo CSS/JSON/Javascript",
        "grant-editmycssjs": "Modificar vòstre CSS/JSON/JavaScript utilizator",
        "grant-editmyoptions": "Modificar vòstras preferéncias d'utilizaire",
+       "grant-editmywatchlist": "Modificar la vòstra lista de seguiment",
        "grant-editpage": "Modificar de paginas existentas",
        "grant-editprotected": "Modificar de paginas protegidas",
+       "grant-highvolume": "Modificacion de volum naut",
+       "grant-oversight": "Amagar los usatgièrs e suprimir las revisions",
        "grant-patrol": "Verificar las modificacions de paginas",
        "grant-privateinfo": "Accedir a las informacions privadas",
+       "grant-protect": "Protegir e desprotegir paginas",
+       "grant-rollback": "Anullar modificacions sus de paginas",
        "grant-sendemail": "Mandar de corriers electronics als autres utilizaires",
        "grant-uploadeditmovefile": "Telecargar, remplaçar e renomenar de fichièrs",
        "grant-uploadfile": "Importar de fichièrs novèls",
        "grant-basic": "Dreits de basa",
        "grant-viewdeleted": "Afichar los fichièrs e paginas suprimits",
        "grant-viewmywatchlist": "Afichar vòstra lista de seguiment",
+       "grant-viewrestrictedlogs": "Afichar las entradas del jornal confidencialas",
        "newuserlogpage": "Istoric de las creacions de comptes",
        "newuserlogpagetext": "Jornal de las creacions de comptes d'utilizaires.",
        "rightslog": "Istoric de las modificacions d'estatut",
        "action-createpage": "crear aquesta pagina",
        "action-createtalk": "crear aquesta pagina de discussion",
        "action-createaccount": "crear aqueste compte d'utilizaire",
+       "action-autocreateaccount": "Crear automaticament aquel compte d'usatgièr extèrne",
        "action-history": "afichar l’istoric d'aquesta pagina",
        "action-minoredit": "marcar aqueste cambiament coma menor",
        "action-move": "renomenar aquesta pagina",
        "action-deleterevision": "suprimir las revisions",
        "action-deletelogentry": "suprimir las entradas del jornal",
        "action-deletedhistory": "veire l’istoric suprimit d'una pagina",
+       "action-deletedtext": "Afichar lo tèxte de la revision suprimida",
        "action-browsearchive": "recercar de paginas suprimidas",
        "action-undelete": "restablir de paginas",
        "action-suppressrevision": "visionar e restablir de revisions suprimidas",
        "action-viewmywatchlist": "afichar vòstra pròpria lista de seguiment",
        "action-viewmyprivateinfo": "veire vòstras informacions personalas",
        "action-editmyprivateinfo": "modificar vòstras informacions personalas",
+       "action-editcontentmodel": "Editar lo modèl de contengut d'una pagina",
+       "action-managechangetags": "Crear e (des)activar d'etiquetas",
+       "action-applychangetags": "Aplicar las etiquetas amb los vòstres cambiaments",
+       "action-changetags": "Apondre e suprimir arbitràriament d'etiquetas  a las revisions individualas e a las entradas de jornal.",
+       "action-deletechangetags": "Suprimir d'etiquetas dempuèi la basa de donadas",
        "action-purge": "purgar aquesta pagina",
        "nchanges": "$1 {{PLURAL:$1|cambiament|cambiaments}}",
        "enhancedrc-since-last-visit": "$1 {{PLURAL:$1|dempuèi la darrièra visita}}",
        "recentchanges-legend": "Opcions dels darrièrs cambiaments",
        "recentchanges-summary": "Vaquí sus aquesta pagina, los darrièrs cambiaments de {{SITENAME}}.",
        "recentchanges-noresult": "Pas cap de modificacion que correspond a aqueles critèris sul periòde indicat.",
+       "recentchanges-timeout": "Aquesta cerca dura tròp de temps. Podètz ensajar de paramètres de cerca diferents",
+       "recentchanges-network": "Se pòt pas afichar pas cap de resultat en causa d'una error tecnica. Ensajatz de tornar cargar la pagina.",
+       "recentchanges-notargetpage": "Dintrar lo nom d'una pagina per veire los cambiaments relatius a aquesta pagina.",
        "recentchanges-feed-description": "Seguissètz los darrièrs cambiaments d'aqueste wiki dins un flux.",
        "recentchanges-label-newpage": "Aquesta modificacion a creat una pagina novèla",
        "recentchanges-label-minor": "Aqueste cambiament es menor",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (veire tanben la [[Special:NewPages|lista de las paginas novèlas]]).",
        "recentchanges-legend-plusminus": "(''±123'')",
        "recentchanges-submit": "Afichar",
+       "rcfilters-tag-remove": "Suprimir '$1'",
+       "rcfilters-legend-heading": "<strong>Lista de las abreviacions:</strong>",
+       "rcfilters-other-review-tools": "Autras aisinas de supervision",
+       "rcfilters-group-results-by-page": "Agropar los resultats per pagina",
        "rcfilters-activefilters": "Filtres actius",
+       "rcfilters-advancedfilters": "Filtres avançats",
+       "rcfilters-limit-title": "Resultats d'affichar",
+       "rcfilters-days-title": "Darrièrs jorns",
        "rcfilters-hours-title": "Darrièras oras",
        "rcfilters-days-show-days": "($1 {{PLURAL:$1|jorn|jorns}})",
        "rcfilters-days-show-hours": "$1 {{PLURAL:$1|ora|oras}}",
+       "rcfilters-highlighted-filters-list": "Mes en evidéncia: $1",
        "rcfilters-quickfilters": "Filtres salvats",
+       "rcfilters-quickfilters-placeholder-title": "Pas encara de filtre salvagardat",
+       "rcfilters-quickfilters-placeholder-description": "Per salvagardar los paramètres de los vòstres filtres e tornar los utilizar mai tard , clicatz sus l'icòna dels favorits dins l'airal de Filtres Actius, dejós.",
        "rcfilters-savedqueries-defaultlabel": "Filtres salvats",
        "rcfilters-savedqueries-rename": "Renomenar",
        "rcfilters-savedqueries-setdefault": "Activar per defaut",
        "rcfilters-savedqueries-apply-label": "Crear un filtre",
        "rcfilters-savedqueries-apply-and-setdefault-label": "Crear lo filtre per defaut",
        "rcfilters-savedqueries-cancel-label": "Anullar",
+       "rcfilters-savedqueries-add-new-title": "Salvagardar los paramètres del filtre actual",
+       "rcfilters-savedqueries-already-saved": "Aquestes filtres son ja salvagardats. Vos cal modificar de paramètres  per crear un novèl filtre salvagardat.",
+       "rcfilters-restore-default-filters": "Restaurar los filtres per defaut",
+       "rcfilters-clear-all-filters": "Escafar totes los filtres",
+       "rcfilters-show-new-changes": "Veire los cambiaments los mai recents",
+       "rcfilters-search-placeholder": "Filtrar los cambiaments (utilizatz lo menu o cercatz lo nom d'un filtre)",
        "rcfilters-invalid-filter": "Filtre pas valid",
+       "rcfilters-empty-filter": "I a pas cap de filtre actiu. Se mòstran totas las contribucions.",
        "rcfilters-filterlist-title": "Filtres",
+       "rcfilters-filterlist-whatsthis": "Cossí fonciona aquò ?",
+       "rcfilters-filterlist-feedbacklink": "Digatz nos que pensatz d'aquestas aisinas (novelas) per filtrar",
+       "rcfilters-highlightbutton-title": "Valorar los resultats",
        "rcfilters-highlightmenu-title": "Causir una color",
+       "rcfilters-highlightmenu-help": "Causir una color per valorar aquesta proprietat",
        "rcfilters-filterlist-noresults": "Cap de filtre pas trobat",
+       "rcfilters-noresults-conflict": "S'es pas trobat cap de resultat perque los critèris de cèrca son en conflicte",
+       "rcfilters-state-message-subset": "Aquel filtre fonciona pas perque los seus resultats son inclús dins los resultats de la cerca seguenta , {{PLURAL:$2|filtre mai larg |filtres mai larges}} (ensajatz de los destriar amb la mesa en forma): $1",
+       "rcfilters-state-message-fullcoverage": "Seleccionar totes los filtres d'aquel grop es equivalent a una seleccion voida, doncas aquel filtre a pas d'efèit. Lo grop compren: $1",
        "rcfilters-filtergroup-authorship": "Paternitat de las contribucions",
        "rcfilters-filter-editsbyself-label": "Modificacions faitas per vos",
        "rcfilters-filter-editsbyself-description": "Vòstras pròprias contribucions.",
        "rcfilters-filter-editsbyother-label": "Modificacions faitas pels autres.",
+       "rcfilters-filter-editsbyother-description": "Totes los cambiaments a l'excepcion de los vòstres.",
+       "rcfilters-filtergroup-userExpLevel": "Registrament dels usatgièrs e experiéncia",
        "rcfilters-filter-user-experience-level-registered-label": "Connectat",
        "rcfilters-filter-user-experience-level-registered-description": "Editors connectats.",
        "rcfilters-filter-user-experience-level-unregistered-label": "Pas connectat",
        "rcfilters-filter-user-experience-level-unregistered-description": "Editors que son pas connectats.",
        "rcfilters-filter-user-experience-level-newcomer-label": "Novèls arribants",
+       "rcfilters-filter-user-experience-level-newcomer-description": "Editors registrats qu'an fait mens de 10 cambiaments o que son actius dempuèi mens de 4 jorns.",
        "rcfilters-filter-user-experience-level-learner-label": "Aprenents",
+       "rcfilters-filter-user-experience-level-learner-description": "Editors registrats, que lor nivèl d'experiéncia es entre \"Utilizaire novelari\" e \"Utilizaire experimentat.\"",
        "rcfilters-filter-user-experience-level-experienced-label": "Utilizaires experimentats",
+       "rcfilters-filter-user-experience-level-experienced-description": "Editors registrats amb mai de 500 cambiaments e 30 jorns d'activitat.",
        "rcfilters-filtergroup-automated": "Contribucions automatizadas",
        "rcfilters-filter-bots-label": "Robòt",
+       "rcfilters-filter-bots-description": "Cambiaments faits per d'aisinas automaticas",
        "rcfilters-filter-humans-label": "Èsser uman (pas robòt)",
        "rcfilters-filter-humans-description": "Modificacions faitas per d'editors umans.",
+       "rcfilters-filtergroup-reviewstatus": "Estat de revision",
+       "rcfilters-filter-reviewstatus-unpatrolled-description": "Cambiaments que son pas marcats coma revisats manualament o automaticament.",
        "rcfilters-filter-reviewstatus-unpatrolled-label": "Pas patrolhat",
+       "rcfilters-filter-reviewstatus-manual-description": "Cambiaments manuals marcats coma revisats",
+       "rcfilters-filter-reviewstatus-manual-label": "Verificat manualament",
+       "rcfilters-filter-reviewstatus-auto-description": "Edicions per d'usatgièrs experimentats que lor trabalh es marcat automaticament coma verificat.",
+       "rcfilters-filter-reviewstatus-auto-label": "Verificat automaticament",
        "rcfilters-filtergroup-significance": "Significacion",
        "rcfilters-filter-minor-label": "Cambiaments menors",
        "rcfilters-filter-minor-description": "Modificacions que l'autor a marcadas coma menoras.",
        "rcfilters-filter-major-label": "Modificacions pas menoras",
        "rcfilters-filter-major-description": "Modificacions pas marcadas coma menoras.",
+       "rcfilters-filtergroup-watchlist": "Paginas de la lista de seguiment",
+       "rcfilters-filter-watchlist-watched-label": "Sus la lista de seguiment",
+       "rcfilters-filter-watchlist-watched-description": "Cambiaments faits sus las paginas de la vòstra lista de seguiment.",
+       "rcfilters-filter-watchlist-watchednew-label": "Cambiaments novèls dins la lista de seguiment",
+       "rcfilters-filter-watchlist-watchednew-description": "Cambiaments dins las paginas en seguiment qu'avètz pas vistas dempuèi que de cambiaments foguèron faits.",
+       "rcfilters-filter-watchlist-notwatched-label": "Es pas sus la lista de seguiment",
+       "rcfilters-filter-watchlist-notwatched-description": "Tot a l'excepcion de cambiaments faits sus las vòstras paginas de seguiment.",
+       "rcfilters-filtergroup-watchlistactivity": "Activitat sus la lista de seguiment",
+       "rcfilters-filter-watchlistactivity-unseen-label": "Cambiaments pas vists",
+       "rcfilters-filter-watchlistactivity-unseen-description": "Cambiaments dins las paginas en seguiment qu'avètz pas vistas dempuèi que de cambiaments foguèron faits.",
+       "rcfilters-filter-watchlistactivity-seen-label": "Cambiaments qu'avètz ja vistes",
+       "rcfilters-filter-watchlistactivity-seen-description": "Cambiaments dins las paginas  qu'avètz vistas dempuèi que de cambiaments foguèron faits.",
        "rcfilters-filtergroup-changetype": "Tipe de cambiament",
        "rcfilters-filter-pageedits-label": "Modificacions de pagina",
        "rcfilters-filter-pageedits-description": "Modificacions del contengut del wiki, de las discussions, de las descripcions de las categorias...",
        "rcfilters-filter-newpages-label": "Creacions de pagina",
        "rcfilters-filter-newpages-description": "Modificacions a l'origina de paginas novèlas.",
        "rcfilters-filter-categorization-label": "Cambiaments de categoria",
+       "rcfilters-filter-categorization-description": "Registraments de paginas apondudas o suprimidas de las categorias.",
        "rcfilters-filter-logactions-label": "Accions traçadas",
        "rcfilters-filter-logactions-description": "Accions dels administrators, creacions de comptes, supressions de paginas, telecargaments...",
        "rcnotefrom": "Çaijós {{PLURAL:$5|la modificacion efectuada|las modificacions efectuadas}} dempuèi lo <strong>$3, $4</strong> (afichadas fins a <strong>$1</strong>).",
index 8158169..70e089a 100644 (file)
        "botpasswords-restriction-failed": "Logowanie nie powiodło się z powodu ograniczeń na hasło bota.",
        "botpasswords-invalid-name": "Określona nazwa użytkownika nie zawiera separatora hasła bota (\"$1\").",
        "botpasswords-not-exist": "Użytkownik \"$1\" nie ma hasła dla bota o nazwie \"$2\".",
+       "botpasswords-needs-reset": "Hasło dla bota o nazwie „$2” {{GENDER:$1|użytkownika|użytkowniczki}} „$1” musi zostać zresetowane.",
        "resetpass_forbidden": "Hasła nie mogą zostać zmienione",
        "resetpass_forbidden-reason": "Hasła nie mogą zostać zmienione: $1",
        "resetpass-no-info": "Musisz być zalogowany, by uzyskać bezpośredni dostęp do tej strony.",
index 1ceac81..4bcde5e 100644 (file)
        "pagedata-text": "Esta página fornece uma interface de dados para páginas. Forneça o título da página no URL, usando a sintaxe de subpáginas, por favor.\n* Aplica-se a negociação de conteúdo com base no cabeçalho Accept do seu cliente. Isto significa que os dados da página serão fornecidos no formato preferido do seu cliente.",
        "pagedata-not-acceptable": "Nenhum formato correspondente encontrado. Tipos MIME suportados: $1",
        "pagedata-bad-title": "Título inválido: $1.",
-       "unregistered-user-config": "Por razões de segurança as subpáginas de utilizador com JavaScript, CSS e JSON não podem ser carregadas para usuários não registados."
+       "unregistered-user-config": "Por razões de segurança as subpáginas de utilizador com JavaScript, CSS e JSON não podem ser carregadas para usuários não registados.",
+       "passwordpolicies": "Políticas de senha",
+       "passwordpolicies-summary": "Esta é uma lista da senha efetiva para os grupos de usuários definidos neste wiki.",
+       "passwordpolicies-group": "Grupo",
+       "passwordpolicies-policies": "Políticas",
+       "passwordpolicies-policy-minimalpasswordlength": "A senha deve ter pelo menos $1 {{PLURAL:$1|caráter|caracteres}}",
+       "passwordpolicies-policy-minimumpasswordlengthtologin": "A senha deve ter pelo menos $1 {{PLURAL:$1|caráter|caracteres}} para poder entrar",
+       "passwordpolicies-policy-passwordcannotmatchusername": "Senha não pode ser o mesmo que nome de usuário",
+       "passwordpolicies-policy-passwordcannotmatchblacklist": "A senha não pode corresponder senhas especificamente na lista negra",
+       "passwordpolicies-policy-maximalpasswordlength": "A senha deve ser menor que $1 {{PLURAL:$1|caráter|caracteres}}",
+       "passwordpolicies-policy-passwordcannotbepopular": "A senha não pode {{PLURAL:$1|ser a mais popular|estar na lista das $1 palavras-passe mais populares}}"
 }
index 700d01a..011b3cf 100644 (file)
        "protectedtitles-submit": "Mostrar títulos",
        "listusers": "Utilizadores",
        "listusers-editsonly": "Mostrar apenas utilizadores com edições",
+       "listusers-temporarygroupsonly": "Mostrar apenas os utilizadores em grupos de utilizadores temporários",
        "listusers-creationsort": "Ordenar por data de criação",
        "listusers-desc": "Ordenar de forma decrescente",
        "usereditcount": "$1 {{PLURAL:$1|edição|edições}}",
        "pagedata-bad-title": "Título inválido: $1.",
        "unregistered-user-config": "Por razões de segurança as subpáginas de utilizador com JavaScript, CSS e JSON não podem ser carregadas para utilizadores não registados.",
        "passwordpolicies": "Regras para palavras-passe",
+       "passwordpolicies-summary": "Esta lista contém as normas efetivas para palavras-passe dos grupos de utilizadores definidos nesta wiki.",
        "passwordpolicies-group": "Grupo",
-       "passwordpolicies-policies": "Normas e recomendações"
+       "passwordpolicies-policies": "Normas e recomendações",
+       "passwordpolicies-policy-minimalpasswordlength": "A palavra-passe tem de ter pelo menos $1 {{PLURAL:$1|carácter|caracteres}}",
+       "passwordpolicies-policy-minimumpasswordlengthtologin": "A palavra-passe tem de ter pelo menos $1 {{PLURAL:$1|carácter|caracteres}} para poder iniciar sessão",
+       "passwordpolicies-policy-passwordcannotmatchusername": "A palavra-passe não pode ser igual ao nome de utilizador",
+       "passwordpolicies-policy-passwordcannotmatchblacklist": "A palavra-passe não pode corresponder às especificamente bloqueadas pela lista negra",
+       "passwordpolicies-policy-maximalpasswordlength": "A palavra-passe tem de ter menos de $1 {{PLURAL:$1|carácter|caracteres}}",
+       "passwordpolicies-policy-passwordcannotbepopular": "A palavra-passe não pode {{PLURAL:$1|ser a mais popular|estar na lista das $1 palavras-passe mais populares}}"
 }
index 2551051..417e0f7 100644 (file)
        "expansion-depth-exceeded-category": "This message is used as a category name for a [[mw:Help:Tracking categories|tracking category]] where pages are placed automatically if the [[meta:Help:Expansion_depth|expansion depth]] of the preprocessor exceeds the limit.",
        "expansion-depth-exceeded-category-desc": "Expansion depth exceeded category description. Shown on [[Special:TrackingCategories]].\n\nSee also:\n* {{msg-mw|Expansion-depth-exceeded-category}}",
        "expansion-depth-exceeded-warning": "Error message shown when a page exceeded the [[meta:Help:Expansion_depth|expansion depth limit]] of the preprocessor.\n\nParameters:\n* $1 - (Unused) the value of the depth limit\n* $2 - (Unused) the value of the max depth limit\nSee also:\n* {{msg-mw|Expansion-depth-exceeded-category}}",
-       "parser-unstrip-loop-warning": "{{Doc-important|Do not translate function name <code>unstrip</code>.}}\nThis error is shown when a parser extension tag such as <code><nowiki><pre></nowiki></code> includes a reference to itself in its own output.\n\nThe reference must be to the exact same invocation of the tag at the same location in the source, merely writing <code><nowiki><pre><pre></pre></pre></nowiki></code> will not do it.\n\nThis is usually impossible and unlikely to happen by accident, so translation is not essential.\n\n\"Unstrip\" refers to the internal function of the parser, called \"unstrip\", which recursively puts the output of parser functions in the place of the parser function call and which would enter an infinite loop in the situation above.\n\nSee also:\n*{{msg-mw|Parser-unstrip-recursion-limit}}",
-       "unstrip-depth-warning": "{{doc-important|Do not translate function name <code>unstrip</code>.}}\nThis message is shown when the recursion limit for nested parser extension tags is exceeded.\n\nThis warning may be encountered due to input text like <code><nowiki><ref><ref><ref>...</ref></ref></ref></nowiki></code>.\n\nParameters:\n* $1 - the depth limit\n\n\"Unstrip\" refers to the internal function of the parser, called 'unstrip', which recursively puts the output of parser functions in the place of the parser function call.\n\nSee also:\n* {{msg-mw|Parser-unstrip-loop-warning}}",
-       "unstrip-depth-category": "This message is used as the category name of a [[mw:Help:Tracking categories|tracking category]] in which pages are placed automatically if the unstrip recursion depth limit is exceeded.",
-       "unstrip-size-warning": "{{doc-important|Do not translate function name <code>unstrip</code>.}}\nThis message is shown when the maximum expansion size for nested parser extension tags is exceeded.\n\nParameters:\n* $1 - the size limit\n\n\"Unstrip\" refers to the internal function of the parser, called 'unstrip', which recursively puts the output of parser functions in the place of the parser function call.\n\nSee also:\n* {{msg-mw|Parser-unstrip-loop-warning}}",
-       "unstrip-size-category": "This message is used as the category name of a [[mw:Help:Tracking categories|tracking category]] in which pages are placed automatically if the unstrip expansion size limit is exceeded.",
+       "parser-unstrip-loop-warning": "{{Doc-important|Do not translate function name <code>unstrip</code>.}}\nThis error is shown when a parser extension tag such as <code><nowiki><pre></nowiki></code> includes a reference to itself in its own output.\n\nThe reference must be to the exact same invocation of the tag at the same location in the source, merely writing <code><nowiki><pre><pre></pre></pre></nowiki></code> will not do it.\n\nThis is usually impossible and unlikely to happen by accident, so translation is not essential.\n\n\"Unstrip\" refers to the internal function of the parser, called \"unstrip\", which recursively puts the output of parser functions in the place of the parser function call and which would enter an infinite loop in the situation above.\n\nSee also:\n*{{msg-mw|Limitreport-unstrip-depth}}\n*{{msg-mw|Limitreport-unstrip-size}}\n*{{msg-mw|Unstrip-depth-category}}\n*{{msg-mw|Unstrip-depth-warning}}\n*{{msg-mw|Unstrip-size-category}}\n*{{msg-mw|Unstrip-size-warning}}",
+       "unstrip-depth-warning": "{{doc-important|Do not translate function name <code>unstrip</code>.}}\nThis message is shown when the recursion limit for nested parser extension tags is exceeded.\n\nThis warning may be encountered due to input text like <code><nowiki><ref><ref><ref>...</ref></ref></ref></nowiki></code>.\n\nParameters:\n* $1 - the depth limit\n\n\"Unstrip\" refers to the internal function of the parser, called 'unstrip', which recursively puts the output of parser functions in the place of the parser function call.\n\nSee also:\n*{{msg-mw|Limitreport-unstrip-depth}}\n*{{msg-mw|Limitreport-unstrip-size}}\n*{{msg-mw|Parser-unstrip-loop-warning}}\n*{{msg-mw|Unstrip-depth-category}}\n*{{msg-mw|Unstrip-size-category}}\n*{{msg-mw|Unstrip-size-warning}}",
+       "unstrip-depth-category": "{{Doc-important|Do not translate function name <code>unstrip</code>.}}\nThis message is used as the category name of a [[mw:Help:Tracking categories|tracking category]] in which pages are placed automatically if the unstrip recursion depth limit is exceeded.\n\n\"Unstrip\" refers to the internal function of the parser, called \"unstrip\", which recursively puts the output of parser functions in the place of the parser function call.\n\nSee also:\n*{{msg-mw|Limitreport-unstrip-depth}}\n*{{msg-mw|Limitreport-unstrip-size}}\n*{{msg-mw|Parser-unstrip-loop-warning}}\n*{{msg-mw|Unstrip-depth-warning}}\n*{{msg-mw|Unstrip-size-category}}\n*{{msg-mw|Unstrip-size-warning}}",
+       "unstrip-size-warning": "{{doc-important|Do not translate function name <code>unstrip</code>.}}\nThis message is shown when the maximum expansion size for nested parser extension tags is exceeded.\n\nParameters:\n* $1 - the size limit\n\n\"Unstrip\" refers to the internal function of the parser, called 'unstrip', which recursively puts the output of parser functions in the place of the parser function call.\n\nSee also:\n*{{msg-mw|Limitreport-unstrip-depth}}\n*{{msg-mw|Limitreport-unstrip-size}}\n*{{msg-mw|Parser-unstrip-loop-warning}}\n*{{msg-mw|Unstrip-depth-category}}\n*{{msg-mw|Unstrip-depth-warning}}\n*{{msg-mw|Unstrip-size-category}}",
+       "unstrip-size-category": "{{Doc-important|Do not translate function name <code>unstrip</code>.}}\nThis message is used as the category name of a [[mw:Help:Tracking categories|tracking category]] in which pages are placed automatically if the unstrip expansion size limit is exceeded.\n\n\"Unstrip\" refers to the internal function of the parser, called \"unstrip\", which recursively puts the output of parser functions in the place of the parser function call.\n\nSee also:\n*{{msg-mw|Limitreport-unstrip-depth}}\n*{{msg-mw|Limitreport-unstrip-size}}\n*{{msg-mw|Parser-unstrip-loop-warning}}\n*{{msg-mw|Unstrip-depth-category}}\n*{{msg-mw|Unstrip-depth-warning}}\n*{{msg-mw|Unstrip-size-warning}}",
        "converter-manual-rule-error": "Used as error message when a manual conversion rule for the [[mw:Language_converter|language converter]] has errors. For example it's not using the correct syntax, or not supplying text in all variants.",
        "undo-success": "Text on special page to confirm edit revert. You arrive on this page by clicking on the \"undo\" link on a revision history special page.\n\n{{Identical|Undo}}",
        "undo-failure": "Message appears if an attempt to revert an edit by clicking the \"undo\" link on the page history fails.\n\nSee also:\n* {{msg-mw|Undo-norev}}\n* {{msg-mw|Undo-nochange}}\n{{Identical|Undo}}",
        "limitreport-expansiondepth-value": "{{optional}}\nFormat for the \"Highest expansion depth\" row in the limit report table.\n\nParameters:\n* $1 - the depth\n* $2 - the maximum",
        "limitreport-expensivefunctioncount": "Label for the \"Expensive parser function count\" row in the limit report table",
        "limitreport-expensivefunctioncount-value": "{{optional}}\nFormat for the \"Expensive parser function count\" row in the limit report table.\n\nParameters:\n* $1 - the usage\n* $2 - the maximum",
-       "limitreport-unstrip-depth": "Label for the \"unstrip depth\" row in the limit report table. \"Unstrip\" is a MediaWiki function name and as such does not need to be translated.",
+       "limitreport-unstrip-depth": "{{Doc-important|Do not translate function name <code>unstrip</code>.}}\nLabel for the \"unstrip depth\" row in the limit report table.\n\n\"Unstrip\" refers to the internal function of the parser, called \"unstrip\", which recursively puts the output of parser functions in the place of the parser function call.\n\nSee also:\n*{{msg-mw|Limitreport-unstrip-size}}\n*{{msg-mw|Parser-unstrip-loop-warning}}\n*{{msg-mw|Unstrip-depth-category}}\n*{{msg-mw|Unstrip-depth-warning}}\n*{{msg-mw|Unstrip-size-category}}\n*{{msg-mw|Unstrip-size-warning}}",
        "limitreport-unstrip-depth-value": "{{optional}}\nFormat for the \"unstrip depth\" row in the limit report table.\n\nParameters:\n* $1 - the usage\n* $2 - the maximum",
-       "limitreport-unstrip-size": "Label for the \"unstrip size\" row in the limit report table. \"Unstrip\" is a MediaWiki function name and as such does not need to be translated.",
+       "limitreport-unstrip-size": "{{Doc-important|Do not translate function name <code>unstrip</code>.}}\nLabel for the \"unstrip size\" row in the limit report table.\n\n\"Unstrip\" refers to the internal function of the parser, called \"unstrip\", which recursively puts the output of parser functions in the place of the parser function call.\n\nSee also:\n*{{msg-mw|Limitreport-unstrip-depth}}\n*{{msg-mw|Parser-unstrip-loop-warning}}\n*{{msg-mw|Unstrip-depth-category}}\n*{{msg-mw|Unstrip-depth-warning}}\n*{{msg-mw|Unstrip-size-category}}\n*{{msg-mw|Unstrip-size-warning}}",
        "limitreport-unstrip-size-value": "Format for the \"unstrip size\" row in the limit report table.\n\nParameters:\n* $1 - the usage\n* $2 - the maximum\n{{Identical|Byte}}",
        "expandtemplates": "{{doc-special|ExpandTemplates}}\nThe name of the [[mw:Extension:ExpandTemplates|Expand Templates extension]].",
        "expand_templates_intro": "This is the explanation given in the heading of the [[Special:ExpandTemplates]] page; it describes its functionality to the users.\nFor more information, see [[mw:Extension:ExpandTemplates]]",
index e153ec3..cb006f0 100644 (file)
@@ -9,7 +9,8 @@
                        "C.R.",
                        "Macofe",
                        "Purodha",
-                       "Fitoschido"
+                       "Fitoschido",
+                       "Ruthven"
                ]
        },
        "tog-underline": "Collegaminde sottolinèate:",
        "subject-preview": "Andeprime de l'oggette:",
        "previewerrortext": "'N'errore ha assute quanne ste facive l'andeprime de le cangiaminde.",
        "blockedtitle": "L'utende è blocchete",
-       "blockedtext": "''''U nome de l'utende o l'indirizze IP ha state bloccate.'''\n\n'U blocche ha state fatte da $1.\n'U mutive date jè ''$2''.\n\n* 'U Blocche accumenze: $8\n* 'U Blocche spicce: $6\n* Tipe de blocche: $7\n\nTu puè condatta $1 o n'otre [[{{MediaWiki:Grouppage-sysop}}|amministratore]] pe 'ngazzarte sus a 'u blocche.\nTu non ge puè ausà 'u strumende 'manne 'na mail a stu utende' senza ca mitte n'indirizze e-mail valide jndr'à le\n[[Special:Preferences|preferenze tue]] e ce è state blocchete sus 'a l'use sue.\nL'IP ca tine mò jè $3 e 'u codece d'u blocche jè #$5.\nPe piacere mitte ste doje 'mbormaziune ce manne 'na richieste de sblocche.",
+       "blockedtext": "<strong>'U nome de l'utende o l'indirizze IP ha state bloccate.</strong>\n\n'U blocche ha state fatte da $1.\n'U mutive date jè <em>$2</em>.\n\n* 'U Blocche accumenze: $8\n* 'U Blocche spicce: $6\n* Tipe de blocche: $7\n\nTu puè condatta $1 o n'otre [[{{MediaWiki:Grouppage-sysop}}|amministratore]] pe 'ngazzarte sus a 'u blocche.\nTu non ge puè ausà 'u strumende \"{{int:emailuser}}\" senza ca mitte n'indirizze email valide jndr'à le\n[[Special:Preferences|preferenze tune]] e ce è state bloccate sus a l'use sue.\nL'IP ca tine mò jè $3 e 'u codece d'u blocche jè #$5.\nPe piacere mitte ste doje 'mbormaziune ce manne 'na richieste de sblocche.",
        "autoblockedtext": "L'indirizze IP tue ha state automaticamende blocchete purcè ha state ausete da n'otre utende, ca avère state blocchete da $1.\n'U mutive date jè 'u seguende:\n\n:''$2''\n\n* Inizie d'u blocche: $8\n* Scadenze d'u blocche: $6\n* Blocche 'ndise: $7\n\nTu puè cundattà $1 o une de l'otre [[{{MediaWiki:Grouppage-sysop}}|amministrature]] pe parà de stu probbleme.\n\nVide Bbuene ca tu non ge puè ausà 'a funziona \"manne n'e-mail a stu utende\" senze ca tu tìne 'n'indirizze e-mail valide e reggistrete jndr'à seziona [[Special:Preferences|me piace accussì]] e tu non ge sinde blocchete da ausarle.\n\nL'indirizze IP corrende jè $3, e 'u codece d'u blocche jè #$5.\nPe piacere mitte tutte le dettaglie ca ponne essere utile pe le richieste tue.",
        "blockednoreason": "nisciune mutive",
        "whitelistedittext": "Tu ha $1 pàggene da cangià.",
        "recentchangeslinked-feed": "Cangiaminde culleghete",
        "recentchangeslinked-toolbox": "Cangiaminde culleghete",
        "recentchangeslinked-title": "Cangiaminde culleghete a \"$1\"",
-       "recentchangeslinked-summary": "Mitte 'u nome de 'na pàgene pe 'ndrucà le cangiaminde a le pàggene ca sò collegate o ca appondane a sta pàgene. (Pe 'ndrucà le membre de 'na categorije, mitte Categoria:Nome d'a categorije). Le cangiaminde a le pàggene ca stonne jndr'à l'elenghe de [[Special:Watchlist|le Pàggene condrollate]] stonne in <strong>grascette</strong>.",
+       "recentchangeslinked-summary": "Mitte 'u nome de 'na pàgene pe 'ndrucà le cangiaminde a le pàggene ca sò collegate o ca appondane a sta pàgene. (Pe 'ndrucà le membre de 'na categorije, mitte {{ns:category}}:Nome d'a categorije). Le cangiaminde a le pàggene ca stonne jndr'à l'elenghe de [[Special:Watchlist|le Pàggene condrollate]] stonne in <strong>grascette</strong>.",
        "recentchangeslinked-page": "Nome d'a vôsce:",
        "recentchangeslinked-to": "Fa vedè le cangiaminde de le pàggene colleghete a 'na certa pàgene",
        "recentchanges-page-added-to-category": "[[:$1]] aggiunde a categorije",
index 6f9c3f7..b5331b2 100644 (file)
        "rcfilters-restore-default-filters": "Восстановить фильтры по умолчанию",
        "rcfilters-clear-all-filters": "Очистить все фильтры",
        "rcfilters-show-new-changes": "Последние изменения",
-       "rcfilters-search-placeholder": "Ð\98зменениÑ\8f Ñ\84илÑ\8cÑ\82Ñ\80ов (используйте меню или ищите по названию фильтра)",
+       "rcfilters-search-placeholder": "ФилÑ\8cÑ\82Ñ\80оваÑ\82Ñ\8c Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ\8f (используйте меню или ищите по названию фильтра)",
        "rcfilters-invalid-filter": "Недопустимый фильтр",
        "rcfilters-empty-filter": "Нет активных фильтров. Показываются все правки.",
        "rcfilters-filterlist-title": "Фильтры",
        "movenosubpage": "У этой страницы нет подстраниц.",
        "movereason": "Причина:",
        "revertmove": "возврат",
-       "delete_and_move_text": "Страница с именем «[[:$1]]» уже существует. \nХотите удалить её, чтобы сделать возможным переименование?",
+       "delete_and_move_text": "ЦелеваÑ\8f Ñ\81траница с именем «[[:$1]]» уже существует. \nХотите удалить её, чтобы сделать возможным переименование?",
        "delete_and_move_confirm": "Да, удалить эту страницу",
        "delete_and_move_reason": "Удалено для возможности переименования «[[$1]]»",
        "selfmove": "Невозможно переименовать страницу: исходное и новое имя страницы совпадают.",
index e7a03f1..d802e94 100644 (file)
        "permissionserrorstext-withaction": "Немате дозволу за $2 из {{PLURAL:$1|следећег|следећих}} разлога:",
        "contentmodelediterror": "Не можете уредити ову измену јер је њен модел садржаја <code>$1</code>, што се разликује од тренутног модела садржаја странице <code>$2</code>.",
        "recreate-moveddeleted-warn": "<strong>Упозорење: поново правите страницу која је претходно обрисана.</strong>\n\nРазмотрите да ли је прикладно да наставите с уређивањем ове странице.\nОвде је наведена историја брисања и премештања с образложењем:",
-       "moveddeleted-notice": "Ð\9eва Ñ\81Ñ\82Ñ\80аниÑ\86а Ñ\98е Ð¾Ð±Ñ\80иÑ\81ана.\nÐ\98Ñ\81Ñ\82оÑ\80иÑ\98а Ñ\9aеног Ð±Ñ\80иÑ\81аÑ\9aа, Ð·Ð°Ñ\88Ñ\82иÑ\82е Ð¸ Ð¿Ñ\80емеÑ\88Ñ\82аÑ\9aа Ð½Ð°Ð»Ð°Ð·Ð¸ Ñ\81е Ð¸Ñ\81под:",
+       "moveddeleted-notice": "Ð\9eва Ñ\81Ñ\82Ñ\80аниÑ\86а Ñ\98е Ð¾Ð±Ñ\80иÑ\81ана.\nÐ\94невник Ð±Ñ\80иÑ\81аÑ\9aа, Ð·Ð°Ñ\88Ñ\82иÑ\82е Ð¸ Ð¿Ñ\80емеÑ\88Ñ\82аÑ\9aа Ñ\81Ñ\82Ñ\80аниÑ\86е Ð½Ð°Ð»Ð°Ð·Ð¸ Ñ\81е Ð¸Ñ\81под.",
        "moveddeleted-notice-recent": "Жао нам је, ова страница је недавно обрисана (у последњих 24 сата).\nИсторија њеног брисања, заштите и премештања налази се испод:",
        "log-fulllog": "Погледај целу историју",
        "edit-hook-aborted": "Измену је прекинула кука.\nНије дато никакво образложење.",
index d947d2a..ddd4b1e 100644 (file)
        "noindex-category": "Neindeksirane stranice",
        "broken-file-category": "Stranice s neispravnim vezama do datoteka",
        "about": "O nama",
-       "article": "Stranica sa sadržajem",
+       "article": "Članak",
        "newwindow": "(otvara se u novom prozoru)",
        "cancel": "Otkaži",
        "moredotdotdot": "Više…",
        "permissionserrorstext": "Nemate ovlašćenje za ovu radnju iz {{PLURAL:$1|1=sledećeg|sledećih}} razloga:",
        "permissionserrorstext-withaction": "Nemate dozvolu za $2 iz {{PLURAL:$1|sledećeg|sledećih}} razloga:",
        "recreate-moveddeleted-warn": "<strong>Upozorenje: ponovo pravite stranicu koja je prethodno obrisana.</strong>\n\nRazmotrite da li je prikladno da nastavite s uređivanjem ove stranice.\nOvde je navedena istorija brisanja i premeštanja s obrazloženjem:",
-       "moveddeleted-notice": "Ova stranica je obrisana.\nIstorija njenog brisanja i premeštanja nalazi se ispod:",
+       "moveddeleted-notice": "Ova stranica je obrisana.\nDnevnik brisanja, zaštite i premeštanja stranice nalazi se ispod.",
        "moveddeleted-notice-recent": "Žao nam je, ova stranica je nedavno obrisana (u poslednjih 24 sata).\nOvde je navedena istorija brisanja i premeštanja s obrazloženjem.",
        "log-fulllog": "Pogledaj celu istoriju",
        "edit-hook-aborted": "Izmenu je prekinula kuka.\nNije dato nikakvo obrazloženje.",
index 1a68426..1b9561b 100644 (file)
        "recentchangeslinked-feed": "Бәйләнешле үзгәртүләр",
        "recentchangeslinked-toolbox": "Бәйләнешле үзгәртүләр",
        "recentchangeslinked-title": "\"$1\" битенә бәйләнешле үзгәртүләр",
-       "recentchangeslinked-summary": "Ð\91Ñ\83 ÐºÒ¯Ñ\80Ñ\81Ó\99Ñ\82елгÓ\99н Ð±Ð¸Ñ\82 Ð±ÐµÐ»Ó\99н Ñ\81Ñ\8bлÑ\82алган (йÓ\99 ÐºÒ¯Ñ\80Ñ\81Ó\99Ñ\82елгÓ\99н Ñ\82Ó©Ñ\80кемгÓ\99 ÐºÐµÑ\80Ñ\82кÓ\99н) Ð±Ð¸Ñ\82лÓ\99Ñ\80нең Ò¯Ð·Ð³Ó\99Ñ\80Ñ\82елмÓ\99лÓ\99Ñ\80е Ð¸Ñ\81емлеге. [[Special:Watchlist|Күзәтү исемлегегезгә]] керә торган битләр '''калын''' итеп күрсәтелгән.",
+       "recentchangeslinked-summary": "Ð\91Ñ\83 Ð±Ð¸Ñ\82Ñ\82Ñ\82Ó\99н Ñ\8fиÑ\81Ó\99 Ð±Ñ\83 Ð±Ð¸Ñ\82кÓ\99 Ñ\81Ñ\8bлÑ\82аган Ð±Ð¸Ñ\82лÓ\99Ñ\80дÓ\99ге Ò¯Ð·Ð³Ó\99Ñ\80Ñ\82мÓ\99ле ÐºÐ°Ñ\80аÑ\83 Ó©Ñ\87ен Ð±Ð¸Ñ\82нең Ð¸Ñ\81емен ÐºÐµÑ\80Ñ\82егез. (Ð\91илгеле Ð±ÐµÑ\80 Ñ\82Ó©Ñ\80кемгÓ\99 ÐºÐ°Ñ\80аган Ð±Ð¸Ñ\82лÓ\99Ñ\80не ÐºÐ°Ñ\80аÑ\83 Ó©Ñ\87ен {{ns:category}}:ТөÑ\80кем Ð¸Ñ\81емен Ñ\8fзÑ\8bгÑ\8bз).[[Special:Watchlist|Күзәтү исемлегегезгә]] керә торган битләр '''калын''' итеп күрсәтелгән.",
        "recentchangeslinked-page": "Битнең исеме:",
        "recentchangeslinked-to": "Моның урынына бу биткә бәйле булган битләрдәге үзгәртүләрне күрсәтү",
        "upload": "Файл йөкләү",
index 35422ec..29fa085 100644 (file)
@@ -33,7 +33,9 @@
                        "Asdfugil",
                        "Deryck Chan",
                        "Hello903hello",
-                       "Fitoschido"
+                       "Fitoschido",
+                       "Kanashimi",
+                       "Roy17"
                ]
        },
        "tog-underline": "連結加底線:",
        "cascadeprotected": "呢一版已經保護咗唔能夠編輯,因為佢係響以下嘅{{PLURAL:$1|一|幾}}頁度包含咗,當中啟用咗\"連串\"保護選項來保護嗰一版: $2",
        "namespaceprotected": "你無權編輯響'''$1'''空間名裏面嘅呢一版。",
        "customcssprotected": "你無權改呢版CSS,因為佢包含其他用戶嘅個人設定。",
+       "customjsonprotected": "你無權改呢版JSON,因為佢包含其他用戶嘅個人設定。",
        "customjsprotected": "你無權改呢版JavaScript,因為佢包含其他用戶嘅個人設定。",
        "mycustomcssprotected": "你無權改呢版CSS。",
+       "mycustomjsonprotected": "你無權改呢版JSON。",
        "mycustomjsprotected": "你無權改呢版JavaScript。",
        "myprivateinfoprotected": "你無權改呢版你嘅私人資料。",
        "mypreferencesprotected": "你無權改呢版你嘅個人設定。",
        "botpasswords-deleted-body": "{{GENDER:$2|用戶}}「$2」嘅機械人「$1」嘅密碼已經剷走咗。",
        "botpasswords-restriction-failed": "機械人密碼限制令到呢次簽到失敗。",
        "botpasswords-invalid-name": "呢個用戶名無機械人密碼分隔字(「$1」)",
+       "botpasswords-not-exist": "用戶「$1」無叫做「$2」嘅機械人密碼。",
+       "botpasswords-needs-reset": "{{GENDER:$1|用戶}}「$1」嘅機械人「$2」嘅密碼一定要重新改。",
        "resetpass_forbidden": "唔可以更改密碼",
        "resetpass_forbidden-reason": "改唔到密碼:$1",
        "resetpass-no-info": "你一定要登入咗去直接入來呢一版。",
        "subject-preview": "主題預覽:",
        "previewerrortext": "預覽你嘅修改嗰陣出錯。",
        "blockedtitle": "用戶已經封鎖",
-       "blockedtext": "你嘅用戶名或者 IP 位址已經被 $1 封咗。\n\n呢次封鎖係由$1所封嘅。當中嘅原因係''$2''。\n\n* 呢次封鎖嘅開始時間係:$8\n* 呢次封鎖嘅到期時間係:$6\n* 對於被封鎖者:$7\n\n你可以聯絡 $1 或者其他嘅[[{{MediaWiki:Grouppage-sysop}}|管理員]],討論呢次封鎖。\n除非你已經響你嘅[[Special:Preferences|戶口喜好設定]]入面設定咗有效嘅電郵地址,否則你係唔可以用「電郵呢個用戶」嘅功能。當設定咗一個有效嘅電郵地址之後,呢個功能係唔會封鎖嘅。\n\n你現時嘅 IP 位址係 $3 ,而個封鎖 ID 係 #$5。 請你喺你嘅查詢都註明以上封鎖嘅資料。",
+       "blockedtext": "<strong>你嘅用戶名或者IP地址已經俾人封咗。</strong>\n\n呢次封鎖係由$1所封嘅。\n俾咗嘅原因係<em>$2</em>。\n\n* 呢次封鎖嘅開始時間係:$8\n* 呢次封鎖嘅到期時間係:$6\n* 被封鎖者:$7\n\n你可以聯絡 $1 或者其他嘅[[{{MediaWiki:Grouppage-sysop}}|管理員]]討論呢次封鎖。\n除非你已經響你嘅[[Special:Preferences|戶口喜好設定]]入面設定咗有效嘅電郵地址,否則你係唔可以用「{{int:emailuser}}」嘅功能。當設定咗一個有效嘅電郵地址之後,呢個功能係唔會被封鎖嘅。\n你現時嘅IP地址係 $3 ,而個封鎖ID係 #$5。\n請喺你嘅查詢都註明以上封鎖嘅資料。",
        "autoblockedtext": "你嘅IP地址已經被自動封鎖,由於之前嘅另一位用戶係畀$1封咗。\n而封鎖嘅原因係:\n\n:''$2''\n\n* 呢次封鎖嘅開始時間係:$8\n* 呢次封鎖嘅到期時間係:$6\n* 對於被封鎖者:$7\n\n你可以聯絡 $1 或者其他嘅[[{{MediaWiki:Grouppage-sysop}}|管理員]],討論呢次封鎖。\n\n除非你已經響你嘅[[Special:Preferences|戶口喜好設定]]入面設定咗有效嘅電郵地址,否則你係唔可以用「電郵呢個用戶」嘅功能。當設定咗一個有效嘅電郵地址之後,呢個功能係唔會封鎖嘅。\n\n你現時用緊嘅 IP 地址係 $3,個封鎖 ID 係 #$5。 請喺你嘅查詢都註明呢個封鎖上面嘅資料。",
        "systemblockedtext": "你嘅用戶名或者IP地址已經俾MediaWiki自動封鎖。\n封鎖原因係:\n\n:<em>$2</em>\n\n* 開始時間:$8\n* 到期時間:$6\n* 目標用戶:$7\n\n你而家嘅IP地址係$3。\n當你作出任何查詢嘅時候,請包含以上所有資料。",
        "blockednoreason": "無原因畀低",
        "post-expand-template-argument-warning": "警告: 呢一版有最少一個模參數有太大嘅擴展大細。\n呢啲參數會被略過。",
        "post-expand-template-argument-category": "包含住略過模參數嘅版",
        "parser-template-loop-warning": "已偵測迴模: [[$1]]",
+       "template-loop-category": "有循環模嘅頁",
        "parser-template-recursion-depth-warning": "迴模深度限制超過咗 ($1)",
        "language-converter-depth-warning": "字體變換器深度限制超過咗 ($1)",
        "node-count-exceeded-category": "有頁面超出咗指定數",
        "prefs-dateformat": "日期格式",
        "prefs-timeoffset": "時間偏移",
        "prefs-advancedediting": "普通選項",
+       "prefs-developertools": "開發者工具",
        "prefs-editor": "編輯",
        "prefs-preview": "預覽",
        "prefs-advancedrc": "進階選項",
        "right-editcontentmodel": "改版面嘅內容模型",
        "right-editinterface": "編輯用戶界面",
        "right-editusercss": "編輯其他用戶嘅CSS檔",
+       "right-edituserjson": "編輯其他用戶嘅JSON檔",
        "right-edituserjs": "編輯其他用戶嘅JavaScript檔",
-       "right-editmyusercss": "編輯戶口嘅CSS文件",
-       "right-editmyuserjs": "編輯戶口嘅JavaScript文件",
+       "right-editmyusercss": "編輯你自己嘅用戶CSS檔",
+       "right-editmyuserjson": "編輯你自己嘅用戶JSON檔",
+       "right-editmyuserjs": "編輯你自己嘅用戶JavaScript檔",
        "right-viewmywatchlist": "睇你自己嘅監視一覽",
        "right-viewmyprivateinfo": "睇下個人信息(例如電郵或真名)",
        "right-editmyprivateinfo": "修改個人信息(例如電郵或真名)",
        "right-sendemail": "寄電郵畀其他用戶",
        "right-managechangetags": "開同(取消)啟用[[Special:Tags|標籤]]",
        "right-applychangetags": "套用[[Special:Tags|標籤]]到某個人嘅改動",
+       "right-deletechangetags": "由資料庫刪[[Special:Tags|標籤]]",
+       "grant-generic": "「$1」權限組合",
        "grant-group-page-interaction": "同版面互動",
        "grant-group-file-interaction": "同傳媒互動",
        "grant-group-watchlist-interaction": "同監視清單互動",
        "grant-group-email": "送電郵",
+       "grant-group-high-volume": "執行大量活動",
        "grant-group-customization": "自訂同設定",
        "grant-group-administration": "做管理行動",
        "grant-group-private-information": "存取你嘅私隱資料",
        "grant-editmywatchlist": "改你嘅監視清單",
        "grant-editpage": "改已經有嘅版",
        "grant-editprotected": "改保護咗嘅版",
+       "grant-highvolume": "大量編輯",
+       "grant-oversight": "收埋用戶同禁止顯示修訂",
+       "grant-sendemail": "寄電郵畀其他用戶",
        "grant-uploadfile": "上載新檔案",
        "grant-basic": "基本權利",
+       "grant-viewdeleted": "睇刪咗嘅檔同頁",
        "grant-viewmywatchlist": "睇你嘅監視清單",
        "newuserlogpage": "使用者開戶記錄",
        "newuserlogpagetext": "呢個係一個使用者開戶嘅日誌",
        "action-editcontentmodel": "改頁面內容模型",
        "action-managechangetags": "從數據庫開或刪走啲符",
        "action-applychangetags": "套用標籤到你嘅改動",
+       "action-purge": "清呢版個快取版本",
        "nchanges": "$1次更改",
        "enhancedrc-since-last-visit": "{{PLURAL:$1|你上次嚟之後}}有 $1 個",
        "enhancedrc-history": "歷史",
        "watchlistedit-normal-legend": "響監視清單度拎走",
        "watchlistedit-normal-explain": "響你張監視清單度嘅標題響下面度顯示。要拎走一個標題,響佢前面剔一剔,跟住要撳『{{int:Watchlistedit-normal-submit}}』。你亦都可以[[Special:EditWatchlist/raw|編輯原始清單]]。",
        "watchlistedit-normal-submit": "拎走標題",
-       "watchlistedit-normal-done": "$1個標題已經響你嘅監視清單度拎走咗:",
+       "watchlistedit-normal-done": "響你嘅監視清單,拎走咗$1個標題:",
        "watchlistedit-raw-title": "編輯原始監視清單",
        "watchlistedit-raw-legend": "編輯原始監視清單",
        "watchlistedit-raw-explain": "你張監視清單嘅標題響下面度顯示,同時亦都可以透過編輯呢個表去加入同埋拎走標題;一行一個標題。當完成咗之後,撳{{int:Watchlistedit-raw-submit}}。你亦都可以去用[[Special:EditWatchlist|標準編輯器]]。",
index 0809fc0..53498bf 100644 (file)
@@ -97,7 +97,9 @@
                        "和平至上",
                        "Sanmosa",
                        "Dongzn",
-                       "Shangkuanlc"
+                       "Shangkuanlc",
+                       "Kanashimi",
+                       "Hello903hello"
                ]
        },
        "tog-underline": "底線標示連結:",
index 5b441f9..234e1b1 100644 (file)
@@ -38,6 +38,7 @@ class TitleCleanup extends TableCleanup {
        public function __construct() {
                parent::__construct();
                $this->addDescription( 'Script to clean up broken, unparseable titles' );
+               $this->batchSize = 1000;
        }
 
        /**
index aec9252..d30a077 100644 (file)
@@ -71,7 +71,7 @@ class GenerateCollationData extends Maintenance {
                $ucdallURL = "https://www.unicode.org/Public/<Unicode version>/ucdxml/ucd.all.grouped.zip";
 
                if ( !$allkeysPresent || !$ucdallPresent ) {
-                       $icuVersion = IcuCollation::getICUVersion();
+                       $icuVersion = INTL_ICU_VERSION;
                        $unicodeVersion = IcuCollation::getUnicodeVersionForICU();
 
                        $error = "";
@@ -88,16 +88,7 @@ class GenerateCollationData extends Maintenance {
                        }
 
                        $versionKnown = false;
-                       if ( !$icuVersion ) {
-                               // Unknown version - either very old intl,
-                               // or PHP < 5.3.7 which does not expose this information
-                               $error .= "As MediaWiki could not determine the version of ICU library used by your PHP's "
-                                       . "intl extension it can't suggest which file version to download. "
-                                       . "This can be caused by running a very old version of intl or PHP < 5.3.7. "
-                                       . "If you are sure everything is all right, find out the ICU version "
-                                       . "by running phpinfo(), check what is the Unicode version it is using "
-                                       . "at http://site.icu-project.org/download, then try finding appropriate data file(s) at:";
-                       } elseif ( version_compare( $icuVersion, "4.0", "<" ) ) {
+                       if ( version_compare( $icuVersion, "4.0", "<" ) ) {
                                // Extra old version
                                $error .= "You are using outdated version of ICU ($icuVersion), intended for "
                                        . ( $unicodeVersion ? "Unicode $unicodeVersion" : "an unknown version of Unicode" )
index b8b2b8e..af47d65 100644 (file)
@@ -35,7 +35,7 @@ class GenerateNormalizerDataAr extends Maintenance {
                parent::__construct();
                $this->addDescription( 'Generate the normalizer data file for Arabic' );
                $this->addOption( 'unicode-data-file', 'The local location of the data file ' .
-                       'from https://unicode.org/Public/UNIDATA/UnicodeData.txt', false, true );
+                       'from https://unicode.org/Public/6.0.0/ucd/UnicodeData.txt', false, true );
        }
 
        public function getDbType() {
@@ -122,7 +122,11 @@ class GenerateNormalizerDataAr extends Maintenance {
                }
 
                global $IP;
-               file_put_contents( "$IP/serialized/normalize-ar.ser", serialize( $pairs ) );
+               file_put_contents( "$IP/languages/data/normalize-ar.php", wfMakeStaticArrayFile(
+                       $pairs,
+                       'File created by generateNormalizerDataAr.php'
+               ) );
+
                echo "ar: " . count( $pairs ) . " pairs written.\n";
        }
 }
index 0bb491f..5b75d8b 100644 (file)
@@ -61,7 +61,11 @@ class GenerateNormalizerDataMl extends Maintenance {
                }
 
                global $IP;
-               file_put_contents( "$IP/serialized/normalize-ml.ser", serialize( $pairs ) );
+               file_put_contents( "$IP/languages/data/normalize-ml.php", wfMakeStaticArrayFile(
+                       $pairs,
+                       'File created by generateNormalizerDataMl.php'
+               ) );
+
                echo "ml: " . count( $pairs ) . " pairs written.\n";
        }
 }
index 7f12835..7467d50 100644 (file)
@@ -50,8 +50,6 @@
  * @class mw.Uri
  */
 
-/* eslint-disable no-use-before-define */
-
 ( function ( mw, $ ) {
        var parser, properties;
 
                                        return uri;
                                }
                                href = hrefCur;
+                               // eslint-disable-next-line no-use-before-define
                                uri = new Uri( href );
                                return uri;
                        };
index 5ae91e8..1be0052 100644 (file)
@@ -1,7 +1,7 @@
 /*!
  * Scripts for pre-emptive edit preparing on action=edit
  */
-/* eslint-disable no-use-before-define */
+
 ( function ( mw, $ ) {
        if ( !mw.config.get( 'wgAjaxEditStash' ) ) {
                return;
                        return;
                }
 
+               // 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' );
+               }
+
                // 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.
@@ -43,6 +53,7 @@
                        if ( stashReq ) {
                                if ( lastPriority > priority ) {
                                        // Stash request for summary change should wait on pending text change stash
+                                       // eslint-disable-next-line no-use-before-define
                                        stashReq.then( checkStash );
                                        return;
                                }
                        } );
                }
 
-               // 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' );
-               }
-
                // Check whether text or summary have changed and call stashEdit()
                function checkStash() {
                        if ( !isTextChanged() && !isSummaryChanged() ) {
index b95a436..ac65ac7 100644 (file)
@@ -215,7 +215,7 @@ table.toc td {
 }
 
 /* preference page with js-genrated toc */
-/* TODO: Delete #preftoc when Special:Preference's non-OOUI mode is disabled */
+/* TODO: Delete #preftoc when Special:Preferences's non-OOUI mode is disabled */
 #preftoc {
        float: left;
        margin: 1em 1em 1em 1em;
index 7927f20..892f044 100644 (file)
@@ -7,6 +7,8 @@
 ( function ( mw, $ ) {
        var $galleries,
                bound = false,
+               lastWidth = window.innerWidth,
+               justifyNeeded = false,
                // Is there a better way to detect a touchscreen? Current check taken from stack overflow.
                isTouchScreen = !!( window.ontouchstart !== undefined ||
                        window.DocumentTouch !== undefined && document instanceof window.DocumentTouch
        }
 
        function handleResizeStart() {
+               // Only do anything if window width changed. We don't care about the height.
+               if ( lastWidth === window.innerWidth ) {
+                       return;
+               }
+
+               justifyNeeded = true;
+               // Temporarily set min-height, so that content following the gallery is not reflowed twice
+               $galleries.css( 'min-height', function () {
+                       return $( this ).height();
+               } );
                $galleries.children( 'li.gallerybox' ).each( function () {
                        var imgWidth = $( this ).data( 'imgWidth' ),
                                imgHeight = $( this ).data( 'imgHeight' ),
        }
 
        function handleResizeEnd() {
-               $galleries.each( justify );
+               // If window width never changed during the resize, don't do anything.
+               if ( justifyNeeded ) {
+                       justifyNeeded = false;
+                       lastWidth = window.innerWidth;
+                       $galleries
+                               // Remove temporary min-height
+                               .css( 'min-height', '' )
+                               // Recalculate layout
+                               .each( justify );
+               }
        }
 
        mw.hook( 'wikipage.content' ).add( function ( $content ) {
index 06c34a5..1823ef0 100644 (file)
@@ -2,8 +2,6 @@
  * Implement AJAX navigation for multi-page images so the user may browse without a full page reload.
  */
 
-/* eslint-disable no-use-before-define */
-
 ( function ( mw, $ ) {
        var jqXhr, $multipageimage, $spinner,
                cache = {},
@@ -86,6 +84,7 @@
                        // Replace table contents
                        $multipageimage.empty().append( $contents.clone() );
 
+                       // eslint-disable-next-line no-use-before-define
                        bindPageNavigation( $multipageimage );
 
                        // Fire hook because the page's content has changed
index 702c18d..2d3f6ad 100644 (file)
@@ -9,7 +9,6 @@
  */
 
 /* global mwNow */
-/* eslint-disable no-use-before-define */
 
 ( function ( $ ) {
        'use strict';
                }() );
        }
 
+       /**
+        * Alias property to the global object.
+        *
+        * @private
+        * @static
+        * @member mw.Map
+        * @param {mw.Map} map
+        * @param {string} key
+        * @param {Mixed} value
+        */
+       function setGlobalMapValue( map, key, value ) {
+               map.values[ key ] = value;
+               log.deprecate(
+                       window,
+                       key,
+                       value,
+                       // Deprecation notice for mw.config globals (T58550, T72470)
+                       map === mw.config && 'Use mw.config instead.'
+               );
+       }
+
        /**
         * Create an object that can be read from or written to via methods that allow
         * interaction both with single and multiple properties at once.
                }
        }
 
-       /**
-        * Alias property to the global object.
-        *
-        * @private
-        * @static
-        * @param {mw.Map} map
-        * @param {string} key
-        * @param {Mixed} value
-        */
-       function setGlobalMapValue( map, key, value ) {
-               map.values[ key ] = value;
-               log.deprecate(
-                       window,
-                       key,
-                       value,
-                       // Deprecation notice for mw.config globals (T58550, T72470)
-                       map === mw.config && 'Use mw.config instead.'
-               );
-       }
-
        Map.prototype = {
                constructor: Map,
 
                                        mw.loader.store.set( module, registry[ module ] );
                                        for ( m in registry ) {
                                                if ( registry[ m ].state === 'loaded' && allReady( registry[ m ].dependencies ) ) {
+                                                       // eslint-disable-next-line no-use-before-define
                                                        execute( m );
                                                }
                                        }
index d9d58dd..33b9f02 100644 (file)
@@ -1,4 +1,3 @@
-/UnicodeData.txt
 /allkeys.txt
 /ucd.all.grouped.xml
 /ucd.all.grouped.zip
index 0a04d85..09369ef 100644 (file)
@@ -1,4 +1,4 @@
-SPECIAL_TARGETS=normalize-ar.ser normalize-ml.ser first-letters-root.ser
+SPECIAL_TARGETS=first-letters-root.ser
 ALL_TARGETS=$(SPECIAL_TARGETS)
 DIST_TARGETS=$(SPECIAL_TARGETS)
 UNICODE_VERSION=6.0.0
@@ -13,18 +13,9 @@ dist: $(DIST_TARGETS)
 clean:
        rm -f $(ALL_TARGETS)
 
-normalize-ar.ser: UnicodeData.txt
-       php ../maintenance/language/generateNormalizerDataAr.php
-
-normalize-ml.ser:
-       php ../maintenance/language/generateNormalizerDataMl.php
-
 first-letters-root.ser: allkeys.txt ucd.all.grouped.xml
        php ../maintenance/language/generateCollationData.php
 
-UnicodeData.txt:
-       wget https://www.unicode.org/Public/$(UNICODE_VERSION)/ucd/UnicodeData.txt
-
 allkeys.txt:
        wget https://www.unicode.org/Public/UCA/$(UNICODE_VERSION)/allkeys.txt
 
diff --git a/serialized/normalize-ar.ser b/serialized/normalize-ar.ser
deleted file mode 100644 (file)
index 2a7f122..0000000
+++ /dev/null
@@ -1 +0,0 @@
-a:731:{s:3:"ﭐ";s:2:"ٱ";s:3:"ﭑ";s:2:"ٱ";s:3:"ﭒ";s:2:"ٻ";s:3:"ﭓ";s:2:"ٻ";s:3:"ﭔ";s:2:"ٻ";s:3:"ﭕ";s:2:"ٻ";s:3:"ﭖ";s:2:"پ";s:3:"ﭗ";s:2:"پ";s:3:"ﭘ";s:2:"پ";s:3:"ﭙ";s:2:"پ";s:3:"ﭚ";s:2:"ڀ";s:3:"ﭛ";s:2:"ڀ";s:3:"ﭜ";s:2:"ڀ";s:3:"ﭝ";s:2:"ڀ";s:3:"ﭞ";s:2:"ٺ";s:3:"ﭟ";s:2:"ٺ";s:3:"ﭠ";s:2:"ٺ";s:3:"ﭡ";s:2:"ٺ";s:3:"ﭢ";s:2:"ٿ";s:3:"ﭣ";s:2:"ٿ";s:3:"ﭤ";s:2:"ٿ";s:3:"ﭥ";s:2:"ٿ";s:3:"ﭦ";s:2:"ٹ";s:3:"ﭧ";s:2:"ٹ";s:3:"ﭨ";s:2:"ٹ";s:3:"ﭩ";s:2:"ٹ";s:3:"ﭪ";s:2:"ڤ";s:3:"ﭫ";s:2:"ڤ";s:3:"ﭬ";s:2:"ڤ";s:3:"ﭭ";s:2:"ڤ";s:3:"ﭮ";s:2:"ڦ";s:3:"ﭯ";s:2:"ڦ";s:3:"ﭰ";s:2:"ڦ";s:3:"ﭱ";s:2:"ڦ";s:3:"ﭲ";s:2:"ڄ";s:3:"ﭳ";s:2:"ڄ";s:3:"ﭴ";s:2:"ڄ";s:3:"ﭵ";s:2:"ڄ";s:3:"ﭶ";s:2:"ڃ";s:3:"ﭷ";s:2:"ڃ";s:3:"ﭸ";s:2:"ڃ";s:3:"ﭹ";s:2:"ڃ";s:3:"ﭺ";s:2:"چ";s:3:"ﭻ";s:2:"چ";s:3:"ﭼ";s:2:"چ";s:3:"ﭽ";s:2:"چ";s:3:"ﭾ";s:2:"ڇ";s:3:"ﭿ";s:2:"ڇ";s:3:"ﮀ";s:2:"ڇ";s:3:"ﮁ";s:2:"ڇ";s:3:"ﮂ";s:2:"ڍ";s:3:"ﮃ";s:2:"ڍ";s:3:"ﮄ";s:2:"ڌ";s:3:"ﮅ";s:2:"ڌ";s:3:"ﮆ";s:2:"ڎ";s:3:"ﮇ";s:2:"ڎ";s:3:"ﮈ";s:2:"ڈ";s:3:"ﮉ";s:2:"ڈ";s:3:"ﮊ";s:2:"ژ";s:3:"ﮋ";s:2:"ژ";s:3:"ﮌ";s:2:"ڑ";s:3:"ﮍ";s:2:"ڑ";s:3:"ﮎ";s:2:"ک";s:3:"ﮏ";s:2:"ک";s:3:"ﮐ";s:2:"ک";s:3:"ﮑ";s:2:"ک";s:3:"ﮒ";s:2:"گ";s:3:"ﮓ";s:2:"گ";s:3:"ﮔ";s:2:"گ";s:3:"ﮕ";s:2:"گ";s:3:"ﮖ";s:2:"ڳ";s:3:"ﮗ";s:2:"ڳ";s:3:"ﮘ";s:2:"ڳ";s:3:"ﮙ";s:2:"ڳ";s:3:"ﮚ";s:2:"ڱ";s:3:"ﮛ";s:2:"ڱ";s:3:"ﮜ";s:2:"ڱ";s:3:"ﮝ";s:2:"ڱ";s:3:"ﮞ";s:2:"ں";s:3:"ﮟ";s:2:"ں";s:3:"ﮠ";s:2:"ڻ";s:3:"ﮡ";s:2:"ڻ";s:3:"ﮢ";s:2:"ڻ";s:3:"ﮣ";s:2:"ڻ";s:3:"ﮤ";s:2:"ۀ";s:3:"ﮥ";s:2:"ۀ";s:3:"ﮦ";s:2:"ہ";s:3:"ﮧ";s:2:"ہ";s:3:"ﮨ";s:2:"ہ";s:3:"ﮩ";s:2:"ہ";s:3:"ﮪ";s:2:"ھ";s:3:"ﮫ";s:2:"ھ";s:3:"ﮬ";s:2:"ھ";s:3:"ﮭ";s:2:"ھ";s:3:"ﮮ";s:2:"ے";s:3:"ﮯ";s:2:"ے";s:3:"ﮰ";s:2:"ۓ";s:3:"ﮱ";s:2:"ۓ";s:3:"ﯓ";s:2:"ڭ";s:3:"ﯔ";s:2:"ڭ";s:3:"ﯕ";s:2:"ڭ";s:3:"ﯖ";s:2:"ڭ";s:3:"ﯗ";s:2:"ۇ";s:3:"ﯘ";s:2:"ۇ";s:3:"ﯙ";s:2:"ۆ";s:3:"ﯚ";s:2:"ۆ";s:3:"ﯛ";s:2:"ۈ";s:3:"ﯜ";s:2:"ۈ";s:3:"ﯝ";s:2:"ٷ";s:3:"ﯞ";s:2:"ۋ";s:3:"ﯟ";s:2:"ۋ";s:3:"ﯠ";s:2:"ۅ";s:3:"ﯡ";s:2:"ۅ";s:3:"ﯢ";s:2:"ۉ";s:3:"ﯣ";s:2:"ۉ";s:3:"ﯤ";s:2:"ې";s:3:"ﯥ";s:2:"ې";s:3:"ﯦ";s:2:"ې";s:3:"ﯧ";s:2:"ې";s:3:"ﯨ";s:2:"ى";s:3:"ﯩ";s:2:"ى";s:3:"ﯪ";s:4:"ئا";s:3:"ﯫ";s:4:"ئا";s:3:"ﯬ";s:4:"ئە";s:3:"ﯭ";s:4:"ئە";s:3:"ﯮ";s:4:"ئو";s:3:"ﯯ";s:4:"ئو";s:3:"ﯰ";s:4:"ئۇ";s:3:"ﯱ";s:4:"ئۇ";s:3:"ﯲ";s:4:"ئۆ";s:3:"ﯳ";s:4:"ئۆ";s:3:"ﯴ";s:4:"ئۈ";s:3:"ﯵ";s:4:"ئۈ";s:3:"ﯶ";s:4:"ئې";s:3:"ﯷ";s:4:"ئې";s:3:"ﯸ";s:4:"ئې";s:3:"ﯹ";s:4:"ئى";s:3:"ﯺ";s:4:"ئى";s:3:"ﯻ";s:4:"ئى";s:3:"ﯼ";s:2:"ی";s:3:"ﯽ";s:2:"ی";s:3:"ﯾ";s:2:"ی";s:3:"ﯿ";s:2:"ی";s:3:"ﰀ";s:4:"ئج";s:3:"ﰁ";s:4:"ئح";s:3:"ﰂ";s:4:"ئم";s:3:"ﰃ";s:4:"ئى";s:3:"ﰄ";s:4:"ئي";s:3:"ﰅ";s:4:"بج";s:3:"ﰆ";s:4:"بح";s:3:"ﰇ";s:4:"بخ";s:3:"ﰈ";s:4:"بم";s:3:"ﰉ";s:4:"بى";s:3:"ﰊ";s:4:"بي";s:3:"ﰋ";s:4:"تج";s:3:"ﰌ";s:4:"تح";s:3:"ﰍ";s:4:"تخ";s:3:"ﰎ";s:4:"تم";s:3:"ﰏ";s:4:"تى";s:3:"ﰐ";s:4:"تي";s:3:"ﰑ";s:4:"ثج";s:3:"ﰒ";s:4:"ثم";s:3:"ﰓ";s:4:"ثى";s:3:"ﰔ";s:4:"ثي";s:3:"ﰕ";s:4:"جح";s:3:"ﰖ";s:4:"جم";s:3:"ﰗ";s:4:"حج";s:3:"ﰘ";s:4:"حم";s:3:"ﰙ";s:4:"خج";s:3:"ﰚ";s:4:"خح";s:3:"ﰛ";s:4:"خم";s:3:"ﰜ";s:4:"سج";s:3:"ﰝ";s:4:"سح";s:3:"ﰞ";s:4:"سخ";s:3:"ﰟ";s:4:"سم";s:3:"ﰠ";s:4:"صح";s:3:"ﰡ";s:4:"صم";s:3:"ﰢ";s:4:"ضج";s:3:"ﰣ";s:4:"ضح";s:3:"ﰤ";s:4:"ضخ";s:3:"ﰥ";s:4:"ضم";s:3:"ﰦ";s:4:"طح";s:3:"ﰧ";s:4:"طم";s:3:"ﰨ";s:4:"ظم";s:3:"ﰩ";s:4:"عج";s:3:"ﰪ";s:4:"عم";s:3:"ﰫ";s:4:"غج";s:3:"ﰬ";s:4:"غم";s:3:"ﰭ";s:4:"فج";s:3:"ﰮ";s:4:"فح";s:3:"ﰯ";s:4:"فخ";s:3:"ﰰ";s:4:"فم";s:3:"ﰱ";s:4:"فى";s:3:"ﰲ";s:4:"في";s:3:"ﰳ";s:4:"قح";s:3:"ﰴ";s:4:"قم";s:3:"ﰵ";s:4:"قى";s:3:"ﰶ";s:4:"قي";s:3:"ﰷ";s:4:"كا";s:3:"ﰸ";s:4:"كج";s:3:"ﰹ";s:4:"كح";s:3:"ﰺ";s:4:"كخ";s:3:"ﰻ";s:4:"كل";s:3:"ﰼ";s:4:"كم";s:3:"ﰽ";s:4:"كى";s:3:"ﰾ";s:4:"كي";s:3:"ﰿ";s:4:"لج";s:3:"ﱀ";s:4:"لح";s:3:"ﱁ";s:4:"لخ";s:3:"ﱂ";s:4:"لم";s:3:"ﱃ";s:4:"لى";s:3:"ﱄ";s:4:"لي";s:3:"ﱅ";s:4:"مج";s:3:"ﱆ";s:4:"مح";s:3:"ﱇ";s:4:"مخ";s:3:"ﱈ";s:4:"مم";s:3:"ﱉ";s:4:"مى";s:3:"ﱊ";s:4:"مي";s:3:"ﱋ";s:4:"نج";s:3:"ﱌ";s:4:"نح";s:3:"ﱍ";s:4:"نخ";s:3:"ﱎ";s:4:"نم";s:3:"ﱏ";s:4:"نى";s:3:"ﱐ";s:4:"ني";s:3:"ﱑ";s:4:"هج";s:3:"ﱒ";s:4:"هم";s:3:"ﱓ";s:4:"هى";s:3:"ﱔ";s:4:"هي";s:3:"ﱕ";s:4:"يج";s:3:"ﱖ";s:4:"يح";s:3:"ﱗ";s:4:"يخ";s:3:"ﱘ";s:4:"يم";s:3:"ﱙ";s:4:"يى";s:3:"ﱚ";s:4:"يي";s:3:"ﱛ";s:4:"ذٰ";s:3:"ﱜ";s:4:"رٰ";s:3:"ﱝ";s:4:"ىٰ";s:3:"ﱞ";s:5:" ٌّ";s:3:"ﱟ";s:5:" ٍّ";s:3:"ﱠ";s:5:" َّ";s:3:"ﱡ";s:5:" ُّ";s:3:"ﱢ";s:5:" ِّ";s:3:"ﱣ";s:5:" ّٰ";s:3:"ﱤ";s:4:"ئر";s:3:"ﱥ";s:4:"ئز";s:3:"ﱦ";s:4:"ئم";s:3:"ﱧ";s:4:"ئن";s:3:"ﱨ";s:4:"ئى";s:3:"ﱩ";s:4:"ئي";s:3:"ﱪ";s:4:"بر";s:3:"ﱫ";s:4:"بز";s:3:"ﱬ";s:4:"بم";s:3:"ﱭ";s:4:"بن";s:3:"ﱮ";s:4:"بى";s:3:"ﱯ";s:4:"بي";s:3:"ﱰ";s:4:"تر";s:3:"ﱱ";s:4:"تز";s:3:"ﱲ";s:4:"تم";s:3:"ﱳ";s:4:"تن";s:3:"ﱴ";s:4:"تى";s:3:"ﱵ";s:4:"تي";s:3:"ﱶ";s:4:"ثر";s:3:"ﱷ";s:4:"ثز";s:3:"ﱸ";s:4:"ثم";s:3:"ﱹ";s:4:"ثن";s:3:"ﱺ";s:4:"ثى";s:3:"ﱻ";s:4:"ثي";s:3:"ﱼ";s:4:"فى";s:3:"ﱽ";s:4:"في";s:3:"ﱾ";s:4:"قى";s:3:"ﱿ";s:4:"قي";s:3:"ﲀ";s:4:"كا";s:3:"ﲁ";s:4:"كل";s:3:"ﲂ";s:4:"كم";s:3:"ﲃ";s:4:"كى";s:3:"ﲄ";s:4:"كي";s:3:"ﲅ";s:4:"لم";s:3:"ﲆ";s:4:"لى";s:3:"ﲇ";s:4:"لي";s:3:"ﲈ";s:4:"ما";s:3:"ﲉ";s:4:"مم";s:3:"ﲊ";s:4:"نر";s:3:"ﲋ";s:4:"نز";s:3:"ﲌ";s:4:"نم";s:3:"ﲍ";s:4:"نن";s:3:"ﲎ";s:4:"نى";s:3:"ﲏ";s:4:"ني";s:3:"ﲐ";s:4:"ىٰ";s:3:"ﲑ";s:4:"ير";s:3:"ﲒ";s:4:"يز";s:3:"ﲓ";s:4:"يم";s:3:"ﲔ";s:4:"ين";s:3:"ﲕ";s:4:"يى";s:3:"ﲖ";s:4:"يي";s:3:"ﲗ";s:4:"ئج";s:3:"ﲘ";s:4:"ئح";s:3:"ﲙ";s:4:"ئخ";s:3:"ﲚ";s:4:"ئم";s:3:"ﲛ";s:4:"ئه";s:3:"ﲜ";s:4:"بج";s:3:"ﲝ";s:4:"بح";s:3:"ﲞ";s:4:"بخ";s:3:"ﲟ";s:4:"بم";s:3:"ﲠ";s:4:"به";s:3:"ﲡ";s:4:"تج";s:3:"ﲢ";s:4:"تح";s:3:"ﲣ";s:4:"تخ";s:3:"ﲤ";s:4:"تم";s:3:"ﲥ";s:4:"ته";s:3:"ﲦ";s:4:"ثم";s:3:"ﲧ";s:4:"جح";s:3:"ﲨ";s:4:"جم";s:3:"ﲩ";s:4:"حج";s:3:"ﲪ";s:4:"حم";s:3:"ﲫ";s:4:"خج";s:3:"ﲬ";s:4:"خم";s:3:"ﲭ";s:4:"سج";s:3:"ﲮ";s:4:"سح";s:3:"ﲯ";s:4:"سخ";s:3:"ﲰ";s:4:"سم";s:3:"ﲱ";s:4:"صح";s:3:"ﲲ";s:4:"صخ";s:3:"ﲳ";s:4:"صم";s:3:"ﲴ";s:4:"ضج";s:3:"ﲵ";s:4:"ضح";s:3:"ﲶ";s:4:"ضخ";s:3:"ﲷ";s:4:"ضم";s:3:"ﲸ";s:4:"طح";s:3:"ﲹ";s:4:"ظم";s:3:"ﲺ";s:4:"عج";s:3:"ﲻ";s:4:"عم";s:3:"ﲼ";s:4:"غج";s:3:"ﲽ";s:4:"غم";s:3:"ﲾ";s:4:"فج";s:3:"ﲿ";s:4:"فح";s:3:"ﳀ";s:4:"فخ";s:3:"ﳁ";s:4:"فم";s:3:"ﳂ";s:4:"قح";s:3:"ﳃ";s:4:"قم";s:3:"ﳄ";s:4:"كج";s:3:"ﳅ";s:4:"كح";s:3:"ﳆ";s:4:"كخ";s:3:"ﳇ";s:4:"كل";s:3:"ﳈ";s:4:"كم";s:3:"ﳉ";s:4:"لج";s:3:"ﳊ";s:4:"لح";s:3:"ﳋ";s:4:"لخ";s:3:"ﳌ";s:4:"لم";s:3:"ﳍ";s:4:"له";s:3:"ﳎ";s:4:"مج";s:3:"ﳏ";s:4:"مح";s:3:"ﳐ";s:4:"مخ";s:3:"ﳑ";s:4:"مم";s:3:"ﳒ";s:4:"نج";s:3:"ﳓ";s:4:"نح";s:3:"ﳔ";s:4:"نخ";s:3:"ﳕ";s:4:"نم";s:3:"ﳖ";s:4:"نه";s:3:"ﳗ";s:4:"هج";s:3:"ﳘ";s:4:"هم";s:3:"ﳙ";s:4:"هٰ";s:3:"ﳚ";s:4:"يج";s:3:"ﳛ";s:4:"يح";s:3:"ﳜ";s:4:"يخ";s:3:"ﳝ";s:4:"يم";s:3:"ﳞ";s:4:"يه";s:3:"ﳟ";s:4:"ئم";s:3:"ﳠ";s:4:"ئه";s:3:"ﳡ";s:4:"بم";s:3:"ﳢ";s:4:"به";s:3:"ﳣ";s:4:"تم";s:3:"ﳤ";s:4:"ته";s:3:"ﳥ";s:4:"ثم";s:3:"ﳦ";s:4:"ثه";s:3:"ﳧ";s:4:"سم";s:3:"ﳨ";s:4:"سه";s:3:"ﳩ";s:4:"شم";s:3:"ﳪ";s:4:"شه";s:3:"ﳫ";s:4:"كل";s:3:"ﳬ";s:4:"كم";s:3:"ﳭ";s:4:"لم";s:3:"ﳮ";s:4:"نم";s:3:"ﳯ";s:4:"نه";s:3:"ﳰ";s:4:"يم";s:3:"ﳱ";s:4:"يه";s:3:"ﳲ";s:6:"ـَّ";s:3:"ﳳ";s:6:"ـُّ";s:3:"ﳴ";s:6:"ـِّ";s:3:"ﳵ";s:4:"طى";s:3:"ﳶ";s:4:"طي";s:3:"ﳷ";s:4:"عى";s:3:"ﳸ";s:4:"عي";s:3:"ﳹ";s:4:"غى";s:3:"ﳺ";s:4:"غي";s:3:"ﳻ";s:4:"سى";s:3:"ﳼ";s:4:"سي";s:3:"ﳽ";s:4:"شى";s:3:"ﳾ";s:4:"شي";s:3:"ﳿ";s:4:"حى";s:3:"ﴀ";s:4:"حي";s:3:"ﴁ";s:4:"جى";s:3:"ﴂ";s:4:"جي";s:3:"ﴃ";s:4:"خى";s:3:"ﴄ";s:4:"خي";s:3:"ﴅ";s:4:"صى";s:3:"ﴆ";s:4:"صي";s:3:"ﴇ";s:4:"ضى";s:3:"ﴈ";s:4:"ضي";s:3:"ﴉ";s:4:"شج";s:3:"ﴊ";s:4:"شح";s:3:"ﴋ";s:4:"شخ";s:3:"ﴌ";s:4:"شم";s:3:"ﴍ";s:4:"شر";s:3:"ﴎ";s:4:"سر";s:3:"ﴏ";s:4:"صر";s:3:"ﴐ";s:4:"ضر";s:3:"ﴑ";s:4:"طى";s:3:"ﴒ";s:4:"طي";s:3:"ﴓ";s:4:"عى";s:3:"ﴔ";s:4:"عي";s:3:"ﴕ";s:4:"غى";s:3:"ﴖ";s:4:"غي";s:3:"ﴗ";s:4:"سى";s:3:"ﴘ";s:4:"سي";s:3:"ﴙ";s:4:"شى";s:3:"ﴚ";s:4:"شي";s:3:"ﴛ";s:4:"حى";s:3:"ﴜ";s:4:"حي";s:3:"ﴝ";s:4:"جى";s:3:"ﴞ";s:4:"جي";s:3:"ﴟ";s:4:"خى";s:3:"ﴠ";s:4:"خي";s:3:"ﴡ";s:4:"صى";s:3:"ﴢ";s:4:"صي";s:3:"ﴣ";s:4:"ضى";s:3:"ﴤ";s:4:"ضي";s:3:"ﴥ";s:4:"شج";s:3:"ﴦ";s:4:"شح";s:3:"ﴧ";s:4:"شخ";s:3:"ﴨ";s:4:"شم";s:3:"ﴩ";s:4:"شر";s:3:"ﴪ";s:4:"سر";s:3:"ﴫ";s:4:"صر";s:3:"ﴬ";s:4:"ضر";s:3:"ﴭ";s:4:"شج";s:3:"ﴮ";s:4:"شح";s:3:"ﴯ";s:4:"شخ";s:3:"ﴰ";s:4:"شم";s:3:"ﴱ";s:4:"سه";s:3:"ﴲ";s:4:"شه";s:3:"ﴳ";s:4:"طم";s:3:"ﴴ";s:4:"سج";s:3:"ﴵ";s:4:"سح";s:3:"ﴶ";s:4:"سخ";s:3:"ﴷ";s:4:"شج";s:3:"ﴸ";s:4:"شح";s:3:"ﴹ";s:4:"شخ";s:3:"ﴺ";s:4:"طم";s:3:"ﴻ";s:4:"ظم";s:3:"ﴼ";s:4:"اً";s:3:"ﴽ";s:4:"اً";s:3:"ﵐ";s:6:"تجم";s:3:"ﵑ";s:6:"تحج";s:3:"ﵒ";s:6:"تحج";s:3:"ﵓ";s:6:"تحم";s:3:"ﵔ";s:6:"تخم";s:3:"ﵕ";s:6:"تمج";s:3:"ﵖ";s:6:"تمح";s:3:"ﵗ";s:6:"تمخ";s:3:"ﵘ";s:6:"جمح";s:3:"ﵙ";s:6:"جمح";s:3:"ﵚ";s:6:"حمي";s:3:"ﵛ";s:6:"حمى";s:3:"ﵜ";s:6:"سحج";s:3:"ﵝ";s:6:"سجح";s:3:"ﵞ";s:6:"سجى";s:3:"ﵟ";s:6:"سمح";s:3:"ﵠ";s:6:"سمح";s:3:"ﵡ";s:6:"سمج";s:3:"ﵢ";s:6:"سمم";s:3:"ﵣ";s:6:"سمم";s:3:"ﵤ";s:6:"صحح";s:3:"ﵥ";s:6:"صحح";s:3:"ﵦ";s:6:"صمم";s:3:"ﵧ";s:6:"شحم";s:3:"ﵨ";s:6:"شحم";s:3:"ﵩ";s:6:"شجي";s:3:"ﵪ";s:6:"شمخ";s:3:"ﵫ";s:6:"شمخ";s:3:"ﵬ";s:6:"شمم";s:3:"ﵭ";s:6:"شمم";s:3:"ﵮ";s:6:"ضحى";s:3:"ﵯ";s:6:"ضخم";s:3:"ﵰ";s:6:"ضخم";s:3:"ﵱ";s:6:"طمح";s:3:"ﵲ";s:6:"طمح";s:3:"ﵳ";s:6:"طمم";s:3:"ﵴ";s:6:"طمي";s:3:"ﵵ";s:6:"عجم";s:3:"ﵶ";s:6:"عمم";s:3:"ﵷ";s:6:"عمم";s:3:"ﵸ";s:6:"عمى";s:3:"ﵹ";s:6:"غمم";s:3:"ﵺ";s:6:"غمي";s:3:"ﵻ";s:6:"غمى";s:3:"ﵼ";s:6:"فخم";s:3:"ﵽ";s:6:"فخم";s:3:"ﵾ";s:6:"قمح";s:3:"ﵿ";s:6:"قمم";s:3:"ﶀ";s:6:"لحم";s:3:"ﶁ";s:6:"لحي";s:3:"ﶂ";s:6:"لحى";s:3:"ﶃ";s:6:"لجج";s:3:"ﶄ";s:6:"لجج";s:3:"ﶅ";s:6:"لخم";s:3:"ﶆ";s:6:"لخم";s:3:"ﶇ";s:6:"لمح";s:3:"ﶈ";s:6:"لمح";s:3:"ﶉ";s:6:"محج";s:3:"ﶊ";s:6:"محم";s:3:"ﶋ";s:6:"محي";s:3:"ﶌ";s:6:"مجح";s:3:"ﶍ";s:6:"مجم";s:3:"ﶎ";s:6:"مخج";s:3:"ﶏ";s:6:"مخم";s:3:"ﶒ";s:6:"مجخ";s:3:"ﶓ";s:6:"همج";s:3:"ﶔ";s:6:"همم";s:3:"ﶕ";s:6:"نحم";s:3:"ﶖ";s:6:"نحى";s:3:"ﶗ";s:6:"نجم";s:3:"ﶘ";s:6:"نجم";s:3:"ﶙ";s:6:"نجى";s:3:"ﶚ";s:6:"نمي";s:3:"ﶛ";s:6:"نمى";s:3:"ﶜ";s:6:"يمم";s:3:"ﶝ";s:6:"يمم";s:3:"ﶞ";s:6:"بخي";s:3:"ﶟ";s:6:"تجي";s:3:"ﶠ";s:6:"تجى";s:3:"ﶡ";s:6:"تخي";s:3:"ﶢ";s:6:"تخى";s:3:"ﶣ";s:6:"تمي";s:3:"ﶤ";s:6:"تمى";s:3:"ﶥ";s:6:"جمي";s:3:"ﶦ";s:6:"جحى";s:3:"ﶧ";s:6:"جمى";s:3:"ﶨ";s:6:"سخى";s:3:"ﶩ";s:6:"صحي";s:3:"ﶪ";s:6:"شحي";s:3:"ﶫ";s:6:"ضحي";s:3:"ﶬ";s:6:"لجي";s:3:"ﶭ";s:6:"لمي";s:3:"ﶮ";s:6:"يحي";s:3:"ﶯ";s:6:"يجي";s:3:"ﶰ";s:6:"يمي";s:3:"ﶱ";s:6:"ممي";s:3:"ﶲ";s:6:"قمي";s:3:"ﶳ";s:6:"نحي";s:3:"ﶴ";s:6:"قمح";s:3:"ﶵ";s:6:"لحم";s:3:"ﶶ";s:6:"عمي";s:3:"ﶷ";s:6:"كمي";s:3:"ﶸ";s:6:"نجح";s:3:"ﶹ";s:6:"مخي";s:3:"ﶺ";s:6:"لجم";s:3:"ﶻ";s:6:"كمم";s:3:"ﶼ";s:6:"لجم";s:3:"ﶽ";s:6:"نجح";s:3:"ﶾ";s:6:"جحي";s:3:"ﶿ";s:6:"حجي";s:3:"ﷀ";s:6:"مجي";s:3:"ﷁ";s:6:"فمي";s:3:"ﷂ";s:6:"بحي";s:3:"ﷃ";s:6:"كمم";s:3:"ﷄ";s:6:"عجم";s:3:"ﷅ";s:6:"صمم";s:3:"ﷆ";s:6:"سخي";s:3:"ﷇ";s:6:"نجي";s:3:"ﷰ";s:6:"صلے";s:3:"ﷱ";s:6:"قلے";s:3:"ﷲ";s:8:"الله";s:3:"ﷳ";s:8:"اكبر";s:3:"ﷴ";s:8:"محمد";s:3:"ﷵ";s:8:"صلعم";s:3:"ﷶ";s:8:"رسول";s:3:"ﷷ";s:8:"عليه";s:3:"ﷸ";s:8:"وسلم";s:3:"ﷹ";s:6:"صلى";s:3:"ﷺ";s:33:"صلى الله عليه وسلم";s:3:"ﷻ";s:15:"جل جلاله";s:3:"﷼";s:8:"ریال";s:3:"ﹰ";s:3:" ً";s:3:"ﹱ";s:4:"ـً";s:3:"ﹲ";s:3:" ٌ";s:3:"ﹴ";s:3:" ٍ";s:3:"ﹶ";s:3:" َ";s:3:"ﹷ";s:4:"ـَ";s:3:"ﹸ";s:3:" ُ";s:3:"ﹹ";s:4:"ـُ";s:3:"ﹺ";s:3:" ِ";s:3:"ﹻ";s:4:"ـِ";s:3:"ﹼ";s:3:" ّ";s:3:"ﹽ";s:4:"ـّ";s:3:"ﹾ";s:3:" ْ";s:3:"ﹿ";s:4:"ـْ";s:3:"ﺀ";s:2:"ء";s:3:"ﺁ";s:2:"آ";s:3:"ﺂ";s:2:"آ";s:3:"ﺃ";s:2:"أ";s:3:"ﺄ";s:2:"أ";s:3:"ﺅ";s:2:"ؤ";s:3:"ﺆ";s:2:"ؤ";s:3:"ﺇ";s:2:"إ";s:3:"ﺈ";s:2:"إ";s:3:"ﺉ";s:2:"ئ";s:3:"ﺊ";s:2:"ئ";s:3:"ﺋ";s:2:"ئ";s:3:"ﺌ";s:2:"ئ";s:3:"ﺍ";s:2:"ا";s:3:"ﺎ";s:2:"ا";s:3:"ﺏ";s:2:"ب";s:3:"ﺐ";s:2:"ب";s:3:"ﺑ";s:2:"ب";s:3:"ﺒ";s:2:"ب";s:3:"ﺓ";s:2:"ة";s:3:"ﺔ";s:2:"ة";s:3:"ﺕ";s:2:"ت";s:3:"ﺖ";s:2:"ت";s:3:"ﺗ";s:2:"ت";s:3:"ﺘ";s:2:"ت";s:3:"ﺙ";s:2:"ث";s:3:"ﺚ";s:2:"ث";s:3:"ﺛ";s:2:"ث";s:3:"ﺜ";s:2:"ث";s:3:"ﺝ";s:2:"ج";s:3:"ﺞ";s:2:"ج";s:3:"ﺟ";s:2:"ج";s:3:"ﺠ";s:2:"ج";s:3:"ﺡ";s:2:"ح";s:3:"ﺢ";s:2:"ح";s:3:"ﺣ";s:2:"ح";s:3:"ﺤ";s:2:"ح";s:3:"ﺥ";s:2:"خ";s:3:"ﺦ";s:2:"خ";s:3:"ﺧ";s:2:"خ";s:3:"ﺨ";s:2:"خ";s:3:"ﺩ";s:2:"د";s:3:"ﺪ";s:2:"د";s:3:"ﺫ";s:2:"ذ";s:3:"ﺬ";s:2:"ذ";s:3:"ﺭ";s:2:"ر";s:3:"ﺮ";s:2:"ر";s:3:"ﺯ";s:2:"ز";s:3:"ﺰ";s:2:"ز";s:3:"ﺱ";s:2:"س";s:3:"ﺲ";s:2:"س";s:3:"ﺳ";s:2:"س";s:3:"ﺴ";s:2:"س";s:3:"ﺵ";s:2:"ش";s:3:"ﺶ";s:2:"ش";s:3:"ﺷ";s:2:"ش";s:3:"ﺸ";s:2:"ش";s:3:"ﺹ";s:2:"ص";s:3:"ﺺ";s:2:"ص";s:3:"ﺻ";s:2:"ص";s:3:"ﺼ";s:2:"ص";s:3:"ﺽ";s:2:"ض";s:3:"ﺾ";s:2:"ض";s:3:"ﺿ";s:2:"ض";s:3:"ﻀ";s:2:"ض";s:3:"ﻁ";s:2:"ط";s:3:"ﻂ";s:2:"ط";s:3:"ﻃ";s:2:"ط";s:3:"ﻄ";s:2:"ط";s:3:"ﻅ";s:2:"ظ";s:3:"ﻆ";s:2:"ظ";s:3:"ﻇ";s:2:"ظ";s:3:"ﻈ";s:2:"ظ";s:3:"ﻉ";s:2:"ع";s:3:"ﻊ";s:2:"ع";s:3:"ﻋ";s:2:"ع";s:3:"ﻌ";s:2:"ع";s:3:"ﻍ";s:2:"غ";s:3:"ﻎ";s:2:"غ";s:3:"ﻏ";s:2:"غ";s:3:"ﻐ";s:2:"غ";s:3:"ﻑ";s:2:"ف";s:3:"ﻒ";s:2:"ف";s:3:"ﻓ";s:2:"ف";s:3:"ﻔ";s:2:"ف";s:3:"ﻕ";s:2:"ق";s:3:"ﻖ";s:2:"ق";s:3:"ﻗ";s:2:"ق";s:3:"ﻘ";s:2:"ق";s:3:"ﻙ";s:2:"ك";s:3:"ﻚ";s:2:"ك";s:3:"ﻛ";s:2:"ك";s:3:"ﻜ";s:2:"ك";s:3:"ﻝ";s:2:"ل";s:3:"ﻞ";s:2:"ل";s:3:"ﻟ";s:2:"ل";s:3:"ﻠ";s:2:"ل";s:3:"ﻡ";s:2:"م";s:3:"ﻢ";s:2:"م";s:3:"ﻣ";s:2:"م";s:3:"ﻤ";s:2:"م";s:3:"ﻥ";s:2:"ن";s:3:"ﻦ";s:2:"ن";s:3:"ﻧ";s:2:"ن";s:3:"ﻨ";s:2:"ن";s:3:"ﻩ";s:2:"ه";s:3:"ﻪ";s:2:"ه";s:3:"ﻫ";s:2:"ه";s:3:"ﻬ";s:2:"ه";s:3:"ﻭ";s:2:"و";s:3:"ﻮ";s:2:"و";s:3:"ﻯ";s:2:"ى";s:3:"ﻰ";s:2:"ى";s:3:"ﻱ";s:2:"ي";s:3:"ﻲ";s:2:"ي";s:3:"ﻳ";s:2:"ي";s:3:"ﻴ";s:2:"ي";s:3:"ﻵ";s:4:"لآ";s:3:"ﻶ";s:4:"لآ";s:3:"ﻷ";s:4:"لأ";s:3:"ﻸ";s:4:"لأ";s:3:"ﻹ";s:4:"لإ";s:3:"ﻺ";s:4:"لإ";s:3:"ﻻ";s:4:"لا";s:3:"ﻼ";s:4:"لا";}
\ No newline at end of file
diff --git a/serialized/normalize-ml.ser b/serialized/normalize-ml.ser
deleted file mode 100644 (file)
index b27a217..0000000
+++ /dev/null
@@ -1 +0,0 @@
-a:6:{s:9:"ണ്‍";s:3:"ൺ";s:9:"ന്‍";s:3:"ൻ";s:9:"ര്‍";s:3:"ർ";s:9:"ല്‍";s:3:"ൽ";s:9:"ള്‍";s:3:"ൾ";s:9:"ക്‍";s:3:"ൿ";}
\ No newline at end of file
index 08ec9f6..ce1dae6 100644 (file)
@@ -829,6 +829,13 @@ class ParserTestRunner {
                        $titleText = 'Parser test';
                }
 
+               if ( isset( $opts['maxincludesize'] ) ) {
+                       $options->setMaxIncludeSize( $opts['maxincludesize'] );
+               }
+               if ( isset( $opts['maxtemplatedepth'] ) ) {
+                       $options->setMaxTemplateDepth( $opts['maxtemplatedepth'] );
+               }
+
                $local = isset( $opts['local'] );
                $preprocessor = isset( $opts['preprocessor'] ) ? $opts['preprocessor'] : null;
                $parser = $this->getParser( $preprocessor );
@@ -1083,6 +1090,11 @@ class ParserTestRunner {
                        'wgFragmentMode' => [ 'legacy' ],
                ];
 
+               $nonIncludable = self::getOptionValue( 'wgNonincludableNamespaces', $opts, false );
+               if ( $nonIncludable !== false ) {
+                       $setup['wgNonincludableNamespaces'] = [ $nonIncludable ];
+               }
+
                if ( $config ) {
                        $configLines = explode( "\n", $config );
 
index d17fbbe..bffc56e 100644 (file)
@@ -109,6 +109,14 @@ Template:echo
 {{{1}}}
 !! endarticle
 
+!! article
+Template:echo3
+!! text
+{{{1}}}
+{{{1}}}
+{{{1}}}
+!! endarticle
+
 // For Serbian; localize Template namespace
 !! article
 Шаблон:Echo
@@ -128,6 +136,12 @@ Template:echo_with_div
 <div>{{{1}}}</div>
 !! endarticle
 
+!! article
+Template:echo with depth
+!! text
+{{echo|{{{1}}}}}
+!! endarticle
+
 !! article
 Template:blank_param
 !! text
@@ -1825,6 +1839,28 @@ b
 </p>
 !! end
 
+!! test
+post-expand include size being exceeded
+!! options
+maxincludesize=20
+!! wikitext
+{{echo3|1234567890}}
+!! html
+<p><a href="/wiki/Template:Echo3" title="Template:Echo3">Template:Echo3</a><!-- WARNING: template omitted, post-expand include size too large -->
+</p>
+!! end
+
+!! test
+max template depth being reached
+!! options
+maxtemplatedepth=1
+!! wikitext
+{{echo with depth|too deep!}}
+!! html
+<p><span class="error">Template recursion depth limit exceeded (1)</span>
+</p>
+!! end
+
 !! test
 Multiple comments should still parse as SOL-transparent
 !! options
@@ -11504,6 +11540,17 @@ Template from main namespace
 </p>
 !! end
 
+!! test
+Template from non-includable namespace
+!! options
+wgNonincludableNamespaces=10
+!! wikitext
+{{echo|uh oh!}}
+!! html
+<p><a href="/wiki/Template:Echo" title="Template:Echo">Template:Echo</a>
+</p>
+!! end
+
 !! article
 Template:table
 !! text
diff --git a/tests/phpunit/data/autoloader/psr4/TestFooBar.php b/tests/phpunit/data/autoloader/psr4/TestFooBar.php
new file mode 100644 (file)
index 0000000..4a2e11f
--- /dev/null
@@ -0,0 +1,6 @@
+<?php
+
+namespace Test\MediaWiki\AutoLoader;
+
+class TestFooBar {
+}
diff --git a/tests/phpunit/includes/AutoLoaderTest.php b/tests/phpunit/includes/AutoLoaderTest.php
new file mode 100644 (file)
index 0000000..af6911d
--- /dev/null
@@ -0,0 +1,64 @@
+<?php
+
+/**
+ * @covers AutoLoader
+ */
+class AutoLoaderTest extends MediaWikiTestCase {
+
+       private $oldPsr4;
+
+       protected function setUp() {
+               parent::setUp();
+
+               // Fancy dance to trigger a rebuild of AutoLoader::$autoloadLocalClassesLower
+               $this->mergeMwGlobalArrayValue( 'wgAutoloadLocalClasses', [
+                       'TestAutoloadedLocalClass' =>
+                               __DIR__ . '/../data/autoloader/TestAutoloadedLocalClass.php',
+                       'TestAutoloadedCamlClass' =>
+                               __DIR__ . '/../data/autoloader/TestAutoloadedCamlClass.php',
+                       'TestAutoloadedSerializedClass' =>
+                               __DIR__ . '/../data/autoloader/TestAutoloadedSerializedClass.php',
+               ] );
+               AutoLoader::resetAutoloadLocalClassesLower();
+
+               $this->mergeMwGlobalArrayValue( 'wgAutoloadClasses', [
+                       'TestAutoloadedClass' => __DIR__ . '/../data/autoloader/TestAutoloadedClass.php',
+               ] );
+
+               $this->oldPsr4 = AutoLoader::$psr4Namespaces;
+               AutoLoader::$psr4Namespaces['Test\\MediaWiki\\AutoLoader\\'] =
+                       __DIR__ . '/../data/autoloader/psr4';
+       }
+
+       protected function tearDown() {
+               AutoLoader::$psr4Namespaces = $this->oldPsr4;
+               parent::tearDown();
+       }
+
+       public function testCoreClass() {
+               $this->assertTrue( class_exists( 'TestAutoloadedLocalClass' ) );
+       }
+
+       public function testExtensionClass() {
+               $this->assertTrue( class_exists( 'TestAutoloadedClass' ) );
+       }
+
+       public function testWrongCaseClass() {
+               $this->setMwGlobals( 'wgAutoloadAttemptLowercase', true );
+
+               $this->assertTrue( class_exists( 'testautoLoadedcamlCLASS' ) );
+       }
+
+       public function testWrongCaseSerializedClass() {
+               $this->setMwGlobals( 'wgAutoloadAttemptLowercase', true );
+
+               $dummyCereal = 'O:29:"testautoloadedserializedclass":0:{}';
+               $uncerealized = unserialize( $dummyCereal );
+               $this->assertFalse( $uncerealized instanceof __PHP_Incomplete_Class,
+                       "unserialize() can load classes case-insensitively." );
+       }
+
+       public function testPsr4() {
+               $this->assertTrue( class_exists( 'Test\\MediaWiki\\AutoLoader\\TestFooBar' ) );
+       }
+}
index efe92ec..c1efc7f 100644 (file)
@@ -33,6 +33,12 @@ class HooksTest extends MediaWikiTestCase {
                                'changed-static',
                                'original'
                        ],
+                       [
+                               'Class::method static call as array',
+                               [ [ 'NothingClass::someStatic' ] ],
+                               'changed-static',
+                               'original'
+                       ],
                        [ 'Global function', [ 'NothingFunction' ], 'changed-func', 'original' ],
                        [ 'Global function with data', [ 'NothingFunctionData', 'data' ], 'data', 'original' ],
                        [ 'Closure', [ function ( &$foo, $bar ) {
@@ -81,10 +87,50 @@ class HooksTest extends MediaWikiTestCase {
                $this->assertSame( $expectedBar, $bar, $msg );
        }
 
+       /**
+        * @covers Hooks::getHandlers
+        */
+       public function testGetHandlers() {
+               global $wgHooks;
+
+               $this->assertSame(
+                       [],
+                       Hooks::getHandlers( 'MediaWikiHooksTest001' ),
+                       'No hooks registered'
+               );
+
+               $a = new NothingClass();
+               $b = new NothingClass();
+
+               $wgHooks['MediaWikiHooksTest001'][] = $a;
+
+               $this->assertSame(
+                       [ $a ],
+                       Hooks::getHandlers( 'MediaWikiHooksTest001' ),
+                       'Hook registered by $wgHooks'
+               );
+
+               Hooks::register( 'MediaWikiHooksTest001', $b );
+               $this->assertSame(
+                       [ $b, $a ],
+                       Hooks::getHandlers( 'MediaWikiHooksTest001' ),
+                       'Hooks::getHandlers() should return hooks registered via wgHooks as well as Hooks::register'
+               );
+
+               Hooks::clear( 'MediaWikiHooksTest001' );
+               unset( $wgHooks['MediaWikiHooksTest001'] );
+
+               Hooks::register( 'MediaWikiHooksTest001', $b );
+               $this->assertSame(
+                       [ $b ],
+                       Hooks::getHandlers( 'MediaWikiHooksTest001' ),
+                       'Hook registered by Hook::register'
+               );
+       }
+
        /**
         * @covers Hooks::isRegistered
         * @covers Hooks::register
-        * @covers Hooks::getHandlers
         * @covers Hooks::run
         * @covers Hooks::callHook
         */
@@ -151,6 +197,56 @@ class HooksTest extends MediaWikiTestCase {
                $this->assertSame( 'original', $foo, 'Hooks abort after a false return.' );
        }
 
+       /**
+        * @covers Hooks::run
+        */
+       public function testNullReturn() {
+               Hooks::register( 'MediaWikiHooksTest001', function ( &$foo ) {
+                       return;
+               } );
+               Hooks::register( 'MediaWikiHooksTest001', function ( &$foo ) {
+                       $foo = 'test';
+
+                       return true;
+               } );
+               $foo = 'original';
+               Hooks::run( 'MediaWikiHooksTest001', [ &$foo ] );
+               $this->assertSame( 'test', $foo, 'Hooks continue after a null return.' );
+       }
+
+       /**
+        * @covers Hooks::callHook
+        */
+       public function testCallHook_FalseHook() {
+               Hooks::register( 'MediaWikiHooksTest001', false );
+               Hooks::register( 'MediaWikiHooksTest001', function ( &$foo ) {
+                       $foo = 'test';
+
+                       return true;
+               } );
+               $foo = 'original';
+               Hooks::run( 'MediaWikiHooksTest001', [ &$foo ] );
+               $this->assertSame( 'test', $foo, 'Hooks that are falsey are skipped.' );
+       }
+
+       /**
+        * @covers Hooks::callHook
+        * @expectedException MWException
+        */
+       public function testCallHook_UnknownDatatype() {
+               Hooks::register( 'MediaWikiHooksTest001', 12345 );
+               Hooks::run( 'MediaWikiHooksTest001' );
+       }
+
+       /**
+        * @covers Hooks::callHook
+        * @expectedException PHPUnit_Framework_Error_Deprecated
+        */
+       public function testCallHook_Deprecated() {
+               Hooks::register( 'MediaWikiHooksTest001', 'NothingClass::someStatic' );
+               Hooks::run( 'MediaWikiHooksTest001', [], '1.31' );
+       }
+
        /**
         * @covers Hooks::runWithoutAbort
         * @covers Hooks::callHook
diff --git a/tests/phpunit/includes/api/query/ApiQueryUserContribsTest.php b/tests/phpunit/includes/api/query/ApiQueryUserContribsTest.php
new file mode 100644 (file)
index 0000000..1d0b471
--- /dev/null
@@ -0,0 +1,194 @@
+<?php
+
+/**
+ * @group API
+ * @group Database
+ * @group medium
+ * @covers ApiQueryUserContribs
+ */
+class ApiQueryUserContribsTest extends ApiTestCase {
+       public function addDBDataOnce() {
+               global $wgActorTableSchemaMigrationStage;
+
+               $reset = new \Wikimedia\ScopedCallback( function ( $v ) {
+                       global $wgActorTableSchemaMigrationStage;
+                       $wgActorTableSchemaMigrationStage = $v;
+                       $this->overrideMwServices();
+               }, [ $wgActorTableSchemaMigrationStage ] );
+               $wgActorTableSchemaMigrationStage = MIGRATION_WRITE_BOTH;
+               $this->overrideMwServices();
+
+               $users = [
+                       User::newFromName( '192.168.2.2', false ),
+                       User::newFromName( '192.168.2.1', false ),
+                       User::newFromName( '192.168.2.3', false ),
+                       User::createNew( __CLASS__ . ' B' ),
+                       User::createNew( __CLASS__ . ' A' ),
+                       User::createNew( __CLASS__ . ' C' ),
+                       User::newFromName( 'IW>' . __CLASS__, false ),
+               ];
+
+               $title = Title::newFromText( __CLASS__ );
+               $page = WikiPage::factory( $title );
+               for ( $i = 0; $i < 3; $i++ ) {
+                       foreach ( array_reverse( $users ) as $user ) {
+                               $status = $page->doEditContent(
+                                       ContentHandler::makeContent( "Test revision $user #$i", $title ), 'Test edit', 0, false, $user
+                               );
+                               if ( !$status->isOK() ) {
+                                       $this->fail( "Failed to edit $title: " . $status->getWikiText( false, false, 'en' ) );
+                               }
+                       }
+               }
+       }
+
+       /**
+        * @dataProvider provideSorting
+        * @param int $stage One of the MIGRATION_* constants for $wgActorTableSchemaMigrationStage
+        * @param array $params Extra parameters for the query
+        * @param bool $reverse Reverse order?
+        * @param int $revs Number of revisions to expect
+        */
+       public function testSorting( $stage, $params, $reverse, $revs ) {
+               if ( isset( $params['ucuserprefix'] ) &&
+                       ( $stage === MIGRATION_WRITE_BOTH || $stage === MIGRATION_WRITE_NEW ) &&
+                       $this->db->getType() === 'mysql' && $this->usesTemporaryTables()
+               ) {
+                       // https://bugs.mysql.com/bug.php?id=10327
+                       $this->markTestSkipped( 'MySQL bug 10327 - can\'t reopen temporary tables' );
+               }
+
+               $this->setMwGlobals( 'wgActorTableSchemaMigrationStage', $stage );
+               $this->overrideMwServices();
+
+               if ( isset( $params['ucuserids'] ) ) {
+                       $params['ucuserids'] = implode( '|', array_map( 'User::idFromName', $params['ucuserids'] ) );
+               }
+               if ( isset( $params['ucuser'] ) ) {
+                       $params['ucuser'] = implode( '|', $params['ucuser'] );
+               }
+
+               $sort = 'rsort';
+               if ( $reverse ) {
+                       $params['ucdir'] = 'newer';
+                       $sort = 'sort';
+               }
+
+               $params += [
+                       'action' => 'query',
+                       'list' => 'usercontribs',
+                       'ucprop' => 'ids',
+               ];
+
+               $apiResult = $this->doApiRequest( $params + [ 'uclimit' => 500 ] );
+               $this->assertArrayNotHasKey( 'continue', $apiResult[0] );
+               $this->assertArrayHasKey( 'query', $apiResult[0] );
+               $this->assertArrayHasKey( 'usercontribs', $apiResult[0]['query'] );
+
+               $count = 0;
+               $ids = [];
+               foreach ( $apiResult[0]['query']['usercontribs'] as $page ) {
+                       $count++;
+                       $ids[$page['user']][] = $page['revid'];
+               }
+               $this->assertSame( $revs, $count, 'Expected number of revisions' );
+               foreach ( $ids as $user => $revids ) {
+                       $sorted = $revids;
+                       call_user_func_array( $sort, [ &$sorted ] );
+                       $this->assertSame( $sorted, $revids, "IDs for $user are sorted" );
+               }
+
+               for ( $limit = 1; $limit < $revs; $limit++ ) {
+                       $continue = [];
+                       $count = 0;
+                       $batchedIds = [];
+                       while ( $continue !== null ) {
+                               $apiResult = $this->doApiRequest( $params + [ 'uclimit' => $limit ] + $continue );
+                               $this->assertArrayHasKey( 'query', $apiResult[0], "Batching with limit $limit" );
+                               $this->assertArrayHasKey( 'usercontribs', $apiResult[0]['query'],
+                                       "Batching with limit $limit" );
+                               $continue = isset( $apiResult[0]['continue'] ) ? $apiResult[0]['continue'] : null;
+                               foreach ( $apiResult[0]['query']['usercontribs'] as $page ) {
+                                       $count++;
+                                       $batchedIds[$page['user']][] = $page['revid'];
+                               }
+                               $this->assertLessThanOrEqual( $revs, $count, "Batching with limit $limit" );
+                       }
+                       $this->assertSame( $ids, $batchedIds, "Result set is the same when batching with limit $limit" );
+               }
+       }
+
+       public static function provideSorting() {
+               $users = [ __CLASS__ . ' A', __CLASS__ . ' B', __CLASS__ . ' C' ];
+               $users2 = [ __CLASS__ . ' A', __CLASS__ . ' B', __CLASS__ . ' D' ];
+               $ips = [ '192.168.2.1', '192.168.2.2', '192.168.2.3', '192.168.2.4' ];
+
+               foreach (
+                       [
+                               'old' => MIGRATION_OLD,
+                               'write both' => MIGRATION_WRITE_BOTH,
+                               'write new' => MIGRATION_WRITE_NEW,
+                               'new' => MIGRATION_NEW,
+                       ] as $stageName => $stage
+               ) {
+                       foreach ( [ false, true ] as $reverse ) {
+                               $name = $stageName . ( $reverse ? ', reverse' : '' );
+                               yield "Named users, $name" => [ $stage, [ 'ucuser' => $users ], $reverse, 9 ];
+                               yield "Named users including a no-edit user, $name" => [
+                                       $stage, [ 'ucuser' => $users2 ], $reverse, 6
+                               ];
+                               yield "IP users, $name" => [ $stage, [ 'ucuser' => $ips ], $reverse, 9 ];
+                               yield "All users, $name" => [
+                                       $stage, [ 'ucuser' => array_merge( $users, $ips ) ], $reverse, 18
+                               ];
+                               yield "User IDs, $name" => [ $stage, [ 'ucuserids' => $users ], $reverse, 9 ];
+                               yield "Users by prefix, $name" => [ $stage, [ 'ucuserprefix' => __CLASS__ ], $reverse, 9 ];
+                               yield "IPs by prefix, $name" => [ $stage, [ 'ucuserprefix' => '192.168.2.' ], $reverse, 9 ];
+                       }
+               }
+       }
+
+       /**
+        * @dataProvider provideInterwikiUser
+        * @param int $stage One of the MIGRATION_* constants for $wgActorTableSchemaMigrationStage
+        */
+       public function testInterwikiUser( $stage ) {
+               $this->setMwGlobals( 'wgActorTableSchemaMigrationStage', $stage );
+               $this->overrideMwServices();
+
+               $params = [
+                       'action' => 'query',
+                       'list' => 'usercontribs',
+                       'ucuser' => 'IW>' . __CLASS__,
+                       'ucprop' => 'ids',
+                       'uclimit' => 'max',
+               ];
+
+               $apiResult = $this->doApiRequest( $params );
+               $this->assertArrayNotHasKey( 'continue', $apiResult[0] );
+               $this->assertArrayHasKey( 'query', $apiResult[0] );
+               $this->assertArrayHasKey( 'usercontribs', $apiResult[0]['query'] );
+
+               $count = 0;
+               $ids = [];
+               foreach ( $apiResult[0]['query']['usercontribs'] as $page ) {
+                       $count++;
+                       $this->assertSame( 'IW>' . __CLASS__, $page['user'], 'Correct user returned' );
+                       $ids[] = $page['revid'];
+               }
+               $this->assertSame( 3, $count, 'Expected number of revisions' );
+               $sorted = $ids;
+               rsort( $sorted );
+               $this->assertSame( $sorted, $ids, "IDs are sorted" );
+       }
+
+       public static function provideInterwikiUser() {
+               return [
+                       'old' => [ MIGRATION_OLD ],
+                       'write both' => [ MIGRATION_WRITE_BOTH ],
+                       'write new' => [ MIGRATION_WRITE_NEW ],
+                       'new' => [ MIGRATION_NEW ],
+               ];
+       }
+
+}
diff --git a/tests/phpunit/includes/api/query/ApiQueryUserContributionsTest.php b/tests/phpunit/includes/api/query/ApiQueryUserContributionsTest.php
deleted file mode 100644 (file)
index ca6a929..0000000
+++ /dev/null
@@ -1,194 +0,0 @@
-<?php
-
-/**
- * @group API
- * @group Database
- * @group medium
- * @covers ApiQueryContributions
- */
-class ApiQueryContributionsTest extends ApiTestCase {
-       public function addDBDataOnce() {
-               global $wgActorTableSchemaMigrationStage;
-
-               $reset = new \Wikimedia\ScopedCallback( function ( $v ) {
-                       global $wgActorTableSchemaMigrationStage;
-                       $wgActorTableSchemaMigrationStage = $v;
-                       $this->overrideMwServices();
-               }, [ $wgActorTableSchemaMigrationStage ] );
-               $wgActorTableSchemaMigrationStage = MIGRATION_WRITE_BOTH;
-               $this->overrideMwServices();
-
-               $users = [
-                       User::newFromName( '192.168.2.2', false ),
-                       User::newFromName( '192.168.2.1', false ),
-                       User::newFromName( '192.168.2.3', false ),
-                       User::createNew( __CLASS__ . ' B' ),
-                       User::createNew( __CLASS__ . ' A' ),
-                       User::createNew( __CLASS__ . ' C' ),
-                       User::newFromName( 'IW>' . __CLASS__, false ),
-               ];
-
-               $title = Title::newFromText( __CLASS__ );
-               $page = WikiPage::factory( $title );
-               for ( $i = 0; $i < 3; $i++ ) {
-                       foreach ( array_reverse( $users ) as $user ) {
-                               $status = $page->doEditContent(
-                                       ContentHandler::makeContent( "Test revision $user #$i", $title ), 'Test edit', 0, false, $user
-                               );
-                               if ( !$status->isOK() ) {
-                                       $this->fail( "Failed to edit $title: " . $status->getWikiText( false, false, 'en' ) );
-                               }
-                       }
-               }
-       }
-
-       /**
-        * @dataProvider provideSorting
-        * @param int $stage One of the MIGRATION_* constants for $wgActorTableSchemaMigrationStage
-        * @param array $params Extra parameters for the query
-        * @param bool $reverse Reverse order?
-        * @param int $revs Number of revisions to expect
-        */
-       public function testSorting( $stage, $params, $reverse, $revs ) {
-               if ( isset( $params['ucuserprefix'] ) &&
-                       ( $stage === MIGRATION_WRITE_BOTH || $stage === MIGRATION_WRITE_NEW ) &&
-                       $this->db->getType() === 'mysql' && $this->usesTemporaryTables()
-               ) {
-                       // https://bugs.mysql.com/bug.php?id=10327
-                       $this->markTestSkipped( 'MySQL bug 10327 - can\'t reopen temporary tables' );
-               }
-
-               $this->setMwGlobals( 'wgActorTableSchemaMigrationStage', $stage );
-               $this->overrideMwServices();
-
-               if ( isset( $params['ucuserids'] ) ) {
-                       $params['ucuserids'] = implode( '|', array_map( 'User::idFromName', $params['ucuserids'] ) );
-               }
-               if ( isset( $params['ucuser'] ) ) {
-                       $params['ucuser'] = implode( '|', $params['ucuser'] );
-               }
-
-               $sort = 'rsort';
-               if ( $reverse ) {
-                       $params['ucdir'] = 'newer';
-                       $sort = 'sort';
-               }
-
-               $params += [
-                       'action' => 'query',
-                       'list' => 'usercontribs',
-                       'ucprop' => 'ids',
-               ];
-
-               $apiResult = $this->doApiRequest( $params + [ 'uclimit' => 500 ] );
-               $this->assertArrayNotHasKey( 'continue', $apiResult[0] );
-               $this->assertArrayHasKey( 'query', $apiResult[0] );
-               $this->assertArrayHasKey( 'usercontribs', $apiResult[0]['query'] );
-
-               $count = 0;
-               $ids = [];
-               foreach ( $apiResult[0]['query']['usercontribs'] as $page ) {
-                       $count++;
-                       $ids[$page['user']][] = $page['revid'];
-               }
-               $this->assertSame( $revs, $count, 'Expected number of revisions' );
-               foreach ( $ids as $user => $revids ) {
-                       $sorted = $revids;
-                       call_user_func_array( $sort, [ &$sorted ] );
-                       $this->assertSame( $sorted, $revids, "IDs for $user are sorted" );
-               }
-
-               for ( $limit = 1; $limit < $revs; $limit++ ) {
-                       $continue = [];
-                       $count = 0;
-                       $batchedIds = [];
-                       while ( $continue !== null ) {
-                               $apiResult = $this->doApiRequest( $params + [ 'uclimit' => $limit ] + $continue );
-                               $this->assertArrayHasKey( 'query', $apiResult[0], "Batching with limit $limit" );
-                               $this->assertArrayHasKey( 'usercontribs', $apiResult[0]['query'],
-                                       "Batching with limit $limit" );
-                               $continue = isset( $apiResult[0]['continue'] ) ? $apiResult[0]['continue'] : null;
-                               foreach ( $apiResult[0]['query']['usercontribs'] as $page ) {
-                                       $count++;
-                                       $batchedIds[$page['user']][] = $page['revid'];
-                               }
-                               $this->assertLessThanOrEqual( $revs, $count, "Batching with limit $limit" );
-                       }
-                       $this->assertSame( $ids, $batchedIds, "Result set is the same when batching with limit $limit" );
-               }
-       }
-
-       public static function provideSorting() {
-               $users = [ __CLASS__ . ' A', __CLASS__ . ' B', __CLASS__ . ' C' ];
-               $users2 = [ __CLASS__ . ' A', __CLASS__ . ' B', __CLASS__ . ' D' ];
-               $ips = [ '192.168.2.1', '192.168.2.2', '192.168.2.3', '192.168.2.4' ];
-
-               foreach (
-                       [
-                               'old' => MIGRATION_OLD,
-                               'write both' => MIGRATION_WRITE_BOTH,
-                               'write new' => MIGRATION_WRITE_NEW,
-                               'new' => MIGRATION_NEW,
-                       ] as $stageName => $stage
-               ) {
-                       foreach ( [ false, true ] as $reverse ) {
-                               $name = $stageName . ( $reverse ? ', reverse' : '' );
-                               yield "Named users, $name" => [ $stage, [ 'ucuser' => $users ], $reverse, 9 ];
-                               yield "Named users including a no-edit user, $name" => [
-                                       $stage, [ 'ucuser' => $users2 ], $reverse, 6
-                               ];
-                               yield "IP users, $name" => [ $stage, [ 'ucuser' => $ips ], $reverse, 9 ];
-                               yield "All users, $name" => [
-                                       $stage, [ 'ucuser' => array_merge( $users, $ips ) ], $reverse, 18
-                               ];
-                               yield "User IDs, $name" => [ $stage, [ 'ucuserids' => $users ], $reverse, 9 ];
-                               yield "Users by prefix, $name" => [ $stage, [ 'ucuserprefix' => __CLASS__ ], $reverse, 9 ];
-                               yield "IPs by prefix, $name" => [ $stage, [ 'ucuserprefix' => '192.168.2.' ], $reverse, 9 ];
-                       }
-               }
-       }
-
-       /**
-        * @dataProvider provideInterwikiUser
-        * @param int $stage One of the MIGRATION_* constants for $wgActorTableSchemaMigrationStage
-        */
-       public function testInterwikiUser( $stage ) {
-               $this->setMwGlobals( 'wgActorTableSchemaMigrationStage', $stage );
-               $this->overrideMwServices();
-
-               $params = [
-                       'action' => 'query',
-                       'list' => 'usercontribs',
-                       'ucuser' => 'IW>' . __CLASS__,
-                       'ucprop' => 'ids',
-                       'uclimit' => 'max',
-               ];
-
-               $apiResult = $this->doApiRequest( $params );
-               $this->assertArrayNotHasKey( 'continue', $apiResult[0] );
-               $this->assertArrayHasKey( 'query', $apiResult[0] );
-               $this->assertArrayHasKey( 'usercontribs', $apiResult[0]['query'] );
-
-               $count = 0;
-               $ids = [];
-               foreach ( $apiResult[0]['query']['usercontribs'] as $page ) {
-                       $count++;
-                       $this->assertSame( 'IW>' . __CLASS__, $page['user'], 'Correct user returned' );
-                       $ids[] = $page['revid'];
-               }
-               $this->assertSame( 3, $count, 'Expected number of revisions' );
-               $sorted = $ids;
-               rsort( $sorted );
-               $this->assertSame( $sorted, $ids, "IDs are sorted" );
-       }
-
-       public static function provideInterwikiUser() {
-               return [
-                       'old' => [ MIGRATION_OLD ],
-                       'write both' => [ MIGRATION_WRITE_BOTH ],
-                       'write new' => [ MIGRATION_WRITE_NEW ],
-                       'new' => [ MIGRATION_NEW ],
-               ];
-       }
-
-}
index f963ad9..12e8a49 100644 (file)
@@ -199,7 +199,7 @@ class ThrottlerTest extends \MediaWikiTestCase {
                $logger->expects( $this->once() )->method( 'log' )->with( $this->anything(), $this->anything(), [
                        'throttle' => 'custom',
                        'index' => 0,
-                       'ip' => '1.2.3.4',
+                       'ipKey' => '1.2.3.4',
                        'username' => 'SomeUser',
                        'count' => 1,
                        'expiry' => 10,
index 7c2476f..71a6339 100644 (file)
@@ -596,11 +596,11 @@ mw.example();
                }
        }
 
-       protected function getFailFerryMock() {
+       protected function getFailFerryMock( $getter = 'getScript' ) {
                $mock = $this->getMockBuilder( ResourceLoaderTestModule::class )
-                       ->setMethods( [ 'getScript' ] )
+                       ->setMethods( [ $getter ] )
                        ->getMock();
-               $mock->method( 'getScript' )->will( $this->throwException(
+               $mock->method( $getter )->will( $this->throwException(
                        new Exception( 'Ferry not found' )
                ) );
                return $mock;
@@ -614,6 +614,14 @@ mw.example();
                return $mock;
        }
 
+       protected function getSimpleStyleModuleMock( $styles = '' ) {
+               $mock = $this->getMockBuilder( ResourceLoaderTestModule::class )
+                       ->setMethods( [ 'getStyles' ] )
+                       ->getMock();
+               $mock->method( 'getStyles' )->willReturn( [ '' => $styles ] );
+               return $mock;
+       }
+
        /**
         * @covers ResourceLoader::getCombinedVersion
         */
@@ -770,6 +778,43 @@ mw.example();
                );
        }
 
+       /**
+        * Verify that exceptions in PHP for one module will not break others
+        * (stylesheet response).
+        *
+        * @covers ResourceLoader::makeModuleResponse
+        */
+       public function testMakeModuleResponseErrorCSS() {
+               $modules = [
+                       'foo' => self::getSimpleStyleModuleMock( '.foo{}' ),
+                       'ferry' => self::getFailFerryMock( 'getStyles' ),
+                       'bar' => self::getSimpleStyleModuleMock( '.bar{}' ),
+               ];
+               $rl = new EmptyResourceLoader();
+               $rl->register( $modules );
+               $context = $this->getResourceLoaderContext(
+                       [
+                               'modules' => 'foo|ferry|bar',
+                               'only' => 'styles',
+                               'debug' => 'false',
+                       ],
+                       $rl
+               );
+
+               // Disable log from makeModuleResponse via outputErrorAndLog
+               $this->setLogger( 'exception', new Psr\Log\NullLogger() );
+
+               $response = $rl->makeModuleResponse( $context, $modules );
+               $errors = $rl->getErrors();
+
+               $this->assertCount( 2, $errors );
+               $this->assertRegExp( '/Ferry not found/', $errors[0] );
+               $this->assertRegExp( '/Problem.+\n\s*"ferry":\s*"error"/m', $errors[1] );
+               $this->assertEquals(
+                       '.foo{}.bar{}',
+                       $response
+               );
+       }
        /**
         * Verify that when building the startup module response,
         * an exception from one module class will not break the entire
diff --git a/tests/phpunit/structure/AutoLoaderStructureTest.php b/tests/phpunit/structure/AutoLoaderStructureTest.php
new file mode 100644 (file)
index 0000000..50ec5fa
--- /dev/null
@@ -0,0 +1,186 @@
+<?php
+
+/**
+ * @coversNothing
+ */
+class AutoLoaderStructureTest extends MediaWikiTestCase {
+       /**
+        * Assert that there were no classes loaded that are not registered with the AutoLoader.
+        *
+        * For example foo.php having class Foo and class Bar but only registering Foo.
+        * This is important because we should not be relying on Foo being used before Bar.
+        */
+       public function testAutoLoadConfig() {
+               $results = self::checkAutoLoadConf();
+
+               $this->assertEquals(
+                       $results['expected'],
+                       $results['actual']
+               );
+       }
+
+       public function providePSR4Completeness() {
+               foreach ( AutoLoader::$psr4Namespaces as $prefix => $dir ) {
+                       foreach ( $this->recurseFiles( $dir ) as $file ) {
+                               yield [ $prefix, $file ];
+                       }
+               }
+       }
+
+       private function recurseFiles( $dir ) {
+               return ( new File_Iterator_Facade() )->getFilesAsArray( $dir, [ '.php' ] );
+       }
+
+       /**
+        * @dataProvider providePSR4Completeness
+        */
+       public function testPSR4Completeness( $prefix, $file ) {
+               global $wgAutoloadLocalClasses, $wgAutoloadClasses;
+               $contents = file_get_contents( $file );
+               list( $classesInFile, $aliasesInFile ) = self::parseFile( $contents );
+               $classes = array_keys( $classesInFile );
+               if ( $classes ) {
+                       $this->assertCount( 1, $classes,
+                               "Only one class per file in PSR-4 autoloaded classes ($file)" );
+
+                       $this->assertStringStartsWith( $prefix, $classes[0] );
+                       $this->assertTrue(
+                               class_exists( $classes[0] ) || interface_exists( $classes[0] ) || trait_exists( $classes[0] ),
+                               "Class {$classes[0]} not autoloaded properly"
+                       );
+               } else {
+                       // Dummy assertion so this test isn't marked in risky
+                       // if the file has no classes nor aliases in it
+                       $this->assertCount( 0, $classes );
+               }
+
+               if ( $aliasesInFile ) {
+                       $otherClasses = $wgAutoloadLocalClasses + $wgAutoloadClasses;
+                       foreach ( $aliasesInFile as $alias => $class ) {
+                               $this->assertArrayHasKey( $alias, $otherClasses,
+                                       'Alias must be in the classmap autoloader'
+                               );
+                       }
+               }
+       }
+
+       private static function parseFile( $contents ) {
+               // We could use token_get_all() here, but this is faster
+               // Note: Keep in sync with ClassCollector
+               $matches = [];
+               preg_match_all( '/
+                               ^ [\t ]* (?:
+                                       (?:final\s+)? (?:abstract\s+)? (?:class|interface|trait) \s+
+                                       (?P<class> [a-zA-Z0-9_]+)
+                               |
+                                       class_alias \s* \( \s*
+                                               ([\'"]) (?P<original> [^\'"]+) \g{-2} \s* , \s*
+                                               ([\'"]) (?P<alias> [^\'"]+ ) \g{-2} \s*
+                                       \) \s* ;
+                               |
+                                       class_alias \s* \( \s*
+                                               (?P<originalStatic> [a-zA-Z0-9_]+)::class \s* , \s*
+                                               ([\'"]) (?P<aliasString> [^\'"]+ ) \g{-2} \s*
+                                       \) \s* ;
+                               )
+                       /imx', $contents, $matches, PREG_SET_ORDER );
+
+               $namespaceMatch = [];
+               preg_match( '/
+                               ^ [\t ]*
+                                       namespace \s+
+                                               ([a-zA-Z0-9_]+(\\\\[a-zA-Z0-9_]+)*)
+                                       \s* ;
+                       /imx', $contents, $namespaceMatch );
+               $fileNamespace = $namespaceMatch ? $namespaceMatch[1] . '\\' : '';
+
+               $classesInFile = [];
+               $aliasesInFile = [];
+
+               foreach ( $matches as $match ) {
+                       if ( !empty( $match['class'] ) ) {
+                               // 'class Foo {}'
+                               $class = $fileNamespace . $match['class'];
+                               $classesInFile[$class] = true;
+                       } else {
+                               if ( !empty( $match['original'] ) ) {
+                                       // 'class_alias( "Foo", "Bar" );'
+                                       $aliasesInFile[$match['alias']] = $match['original'];
+                               } else {
+                                       // 'class_alias( Foo::class, "Bar" );'
+                                       $aliasesInFile[$match['aliasString']] = $fileNamespace . $match['originalStatic'];
+                               }
+                       }
+               }
+
+               return [ $classesInFile, $aliasesInFile ];
+       }
+
+       protected static function checkAutoLoadConf() {
+               global $wgAutoloadLocalClasses, $wgAutoloadClasses, $IP;
+
+               // wgAutoloadLocalClasses has precedence, just like in includes/AutoLoader.php
+               $expected = $wgAutoloadLocalClasses + $wgAutoloadClasses;
+               $actual = [];
+
+               $files = array_unique( $expected );
+
+               foreach ( $files as $class => $file ) {
+                       // Only prefix $IP if it doesn't have it already.
+                       // Generally local classes don't have it, and those from extensions and test suites do.
+                       if ( substr( $file, 0, 1 ) != '/' && substr( $file, 1, 1 ) != ':' ) {
+                               $filePath = "$IP/$file";
+                       } else {
+                               $filePath = $file;
+                       }
+
+                       if ( !file_exists( $filePath ) ) {
+                               $actual[$class] = "[file '$filePath' does not exist]";
+                               continue;
+                       }
+
+                       Wikimedia\suppressWarnings();
+                       $contents = file_get_contents( $filePath );
+                       Wikimedia\restoreWarnings();
+
+                       if ( $contents === false ) {
+                               $actual[$class] = "[couldn't read file '$filePath']";
+                               continue;
+                       }
+
+                       list( $classesInFile, $aliasesInFile ) = self::parseFile( $contents );
+
+                       foreach ( $classesInFile as $className => $ignore ) {
+                               $actual[$className] = $file;
+                       }
+
+                       // Only accept aliases for classes in the same file, because for correct
+                       // behavior, all aliases for a class must be set up when the class is loaded
+                       // (see <https://bugs.php.net/bug.php?id=61422>).
+                       foreach ( $aliasesInFile as $alias => $class ) {
+                               if ( isset( $classesInFile[$class] ) ) {
+                                       $actual[$alias] = $file;
+                               } else {
+                                       $actual[$alias] = "[original class not in $file]";
+                               }
+                       }
+               }
+
+               return [
+                       'expected' => $expected,
+                       'actual' => $actual,
+               ];
+       }
+
+       public function testAutoloadOrder() {
+               $path = realpath( __DIR__ . '/../../..' );
+               $oldAutoload = file_get_contents( $path . '/autoload.php' );
+               $generator = new AutoloadGenerator( $path, 'local' );
+               $generator->setExcludePaths( array_values( AutoLoader::getAutoloadNamespaces() ) );
+               $generator->initMediaWikiDefault();
+               $newAutoload = $generator->getAutoload( 'maintenance/generateLocalAutoload.php' );
+
+               $this->assertEquals( $oldAutoload, $newAutoload, 'autoload.php does not match' .
+                       ' output of generateLocalAutoload.php script.' );
+       }
+}
diff --git a/tests/phpunit/structure/AutoLoaderTest.php b/tests/phpunit/structure/AutoLoaderTest.php
deleted file mode 100644 (file)
index 217232e..0000000
+++ /dev/null
@@ -1,171 +0,0 @@
-<?php
-
-class AutoLoaderTest extends MediaWikiTestCase {
-       protected function setUp() {
-               parent::setUp();
-
-               // Fancy dance to trigger a rebuild of AutoLoader::$autoloadLocalClassesLower
-               $this->mergeMwGlobalArrayValue( 'wgAutoloadLocalClasses', [
-                       'TestAutoloadedLocalClass' =>
-                               __DIR__ . '/../data/autoloader/TestAutoloadedLocalClass.php',
-                       'TestAutoloadedCamlClass' =>
-                               __DIR__ . '/../data/autoloader/TestAutoloadedCamlClass.php',
-                       'TestAutoloadedSerializedClass' =>
-                               __DIR__ . '/../data/autoloader/TestAutoloadedSerializedClass.php',
-               ] );
-               AutoLoader::resetAutoloadLocalClassesLower();
-
-               $this->mergeMwGlobalArrayValue( 'wgAutoloadClasses', [
-                       'TestAutoloadedClass' => __DIR__ . '/../data/autoloader/TestAutoloadedClass.php',
-               ] );
-       }
-
-       /**
-        * Assert that there were no classes loaded that are not registered with the AutoLoader.
-        *
-        * For example foo.php having class Foo and class Bar but only registering Foo.
-        * This is important because we should not be relying on Foo being used before Bar.
-        */
-       public function testAutoLoadConfig() {
-               $results = self::checkAutoLoadConf();
-
-               $this->assertEquals(
-                       $results['expected'],
-                       $results['actual']
-               );
-       }
-
-       protected static function checkAutoLoadConf() {
-               global $wgAutoloadLocalClasses, $wgAutoloadClasses, $IP;
-
-               // wgAutoloadLocalClasses has precedence, just like in includes/AutoLoader.php
-               $expected = $wgAutoloadLocalClasses + $wgAutoloadClasses;
-               $actual = [];
-
-               $files = array_unique( $expected );
-
-               foreach ( $files as $class => $file ) {
-                       // Only prefix $IP if it doesn't have it already.
-                       // Generally local classes don't have it, and those from extensions and test suites do.
-                       if ( substr( $file, 0, 1 ) != '/' && substr( $file, 1, 1 ) != ':' ) {
-                               $filePath = "$IP/$file";
-                       } else {
-                               $filePath = $file;
-                       }
-
-                       if ( !file_exists( $filePath ) ) {
-                               $actual[$class] = "[file '$filePath' does not exist]";
-                               continue;
-                       }
-
-                       Wikimedia\suppressWarnings();
-                       $contents = file_get_contents( $filePath );
-                       Wikimedia\restoreWarnings();
-
-                       if ( $contents === false ) {
-                               $actual[$class] = "[couldn't read file '$filePath']";
-                               continue;
-                       }
-
-                       // We could use token_get_all() here, but this is faster
-                       // Note: Keep in sync with ClassCollector
-                       $matches = [];
-                       preg_match_all( '/
-                               ^ [\t ]* (?:
-                                       (?:final\s+)? (?:abstract\s+)? (?:class|interface|trait) \s+
-                                       (?P<class> [a-zA-Z0-9_]+)
-                               |
-                                       class_alias \s* \( \s*
-                                               ([\'"]) (?P<original> [^\'"]+) \g{-2} \s* , \s*
-                                               ([\'"]) (?P<alias> [^\'"]+ ) \g{-2} \s*
-                                       \) \s* ;
-                               |
-                                       class_alias \s* \( \s*
-                                               (?P<originalStatic> [a-zA-Z0-9_]+)::class \s* , \s*
-                                               ([\'"]) (?P<aliasString> [^\'"]+ ) \g{-2} \s*
-                                       \) \s* ;
-                               )
-                       /imx', $contents, $matches, PREG_SET_ORDER );
-
-                       $namespaceMatch = [];
-                       preg_match( '/
-                               ^ [\t ]*
-                                       namespace \s+
-                                               ([a-zA-Z0-9_]+(\\\\[a-zA-Z0-9_]+)*)
-                                       \s* ;
-                       /imx', $contents, $namespaceMatch );
-                       $fileNamespace = $namespaceMatch ? $namespaceMatch[1] . '\\' : '';
-
-                       $classesInFile = [];
-                       $aliasesInFile = [];
-
-                       foreach ( $matches as $match ) {
-                               if ( !empty( $match['class'] ) ) {
-                                       // 'class Foo {}'
-                                       $class = $fileNamespace . $match['class'];
-                                       $actual[$class] = $file;
-                                       $classesInFile[$class] = true;
-                               } else {
-                                       if ( !empty( $match['original'] ) ) {
-                                               // 'class_alias( "Foo", "Bar" );'
-                                               $aliasesInFile[$match['alias']] = $match['original'];
-                                       } else {
-                                               // 'class_alias( Foo::class, "Bar" );'
-                                               $aliasesInFile[$match['aliasString']] = $fileNamespace . $match['originalStatic'];
-                                       }
-                               }
-                       }
-
-                       // Only accept aliases for classes in the same file, because for correct
-                       // behavior, all aliases for a class must be set up when the class is loaded
-                       // (see <https://bugs.php.net/bug.php?id=61422>).
-                       foreach ( $aliasesInFile as $alias => $class ) {
-                               if ( isset( $classesInFile[$class] ) ) {
-                                       $actual[$alias] = $file;
-                               } else {
-                                       $actual[$alias] = "[original class not in $file]";
-                               }
-                       }
-               }
-
-               return [
-                       'expected' => $expected,
-                       'actual' => $actual,
-               ];
-       }
-
-       function testCoreClass() {
-               $this->assertTrue( class_exists( 'TestAutoloadedLocalClass' ) );
-       }
-
-       function testExtensionClass() {
-               $this->assertTrue( class_exists( 'TestAutoloadedClass' ) );
-       }
-
-       function testWrongCaseClass() {
-               $this->setMwGlobals( 'wgAutoloadAttemptLowercase', true );
-
-               $this->assertTrue( class_exists( 'testautoLoadedcamlCLASS' ) );
-       }
-
-       function testWrongCaseSerializedClass() {
-               $this->setMwGlobals( 'wgAutoloadAttemptLowercase', true );
-
-               $dummyCereal = 'O:29:"testautoloadedserializedclass":0:{}';
-               $uncerealized = unserialize( $dummyCereal );
-               $this->assertFalse( $uncerealized instanceof __PHP_Incomplete_Class,
-                       "unserialize() can load classes case-insensitively." );
-       }
-
-       function testAutoloadOrder() {
-               $path = realpath( __DIR__ . '/../../..' );
-               $oldAutoload = file_get_contents( $path . '/autoload.php' );
-               $generator = new AutoloadGenerator( $path, 'local' );
-               $generator->setExcludePaths( array_values( AutoLoader::getAutoloadNamespaces() ) );
-               $generator->initMediaWikiDefault();
-               $newAutoload = $generator->getAutoload( 'maintenance/generateLocalAutoload.php' );
-
-               $this->assertEquals( $oldAutoload, $newAutoload, 'autoload.php does not match' .
-                       ' output of generateLocalAutoload.php script.' );
-       }
-}